cmd/names.c | 14 ++--- cmd/names.h | 6 +- cmd/systool.c | 2 +- configure.ac | 2 +- lib/Makefile.am | 2 +- lib/dlist.c | 2 +- lib/libsysfs.map | 19 +++++++ lib/sysfs_utils.c | 161 ++++++++++++++++++++++++++++++++++-------------------- test/Makefile.am | 2 +- test/dlist_test.c | 2 +- test/get_driver.c | 1 - 11 files changed, 137 insertions(+), 76 deletions(-) diff --git a/cmd/names.c b/cmd/names.c index 1e80d1b..1ba0e5d 100644 --- a/cmd/names.c +++ b/cmd/names.c @@ -22,7 +22,7 @@ struct nl_entry { struct nl_entry *next; unsigned short id1, id2, id3, id4; int cat; - unsigned char *name; + char *name; }; #define NL_VENDOR 0 @@ -58,7 +58,7 @@ static struct nl_entry *nl_lookup(struct pci_access *a, int num, int cat, int id return n; } -static int nl_add(struct pci_access *a, int cat, int id1, int id2, int id3, int id4, unsigned char *text) +static int nl_add(struct pci_access *a, int cat, int id1, int id2, int id3, int id4, char *text) { unsigned int h = nl_calc_hash(cat, id1, id2, id3, id4); struct nl_entry *n = a->nl_hash[h]; @@ -81,7 +81,7 @@ static int nl_add(struct pci_access *a, int cat, int id1, int id2, int id3, int } static void -err_name_list(struct pci_access *a, unsigned char *msg) +err_name_list(struct pci_access *a, char *msg) { fprintf(stderr, "%s: %s: %s\n", a->pci_id_file_name, msg, strerror(errno)); } @@ -89,8 +89,8 @@ err_name_list(struct pci_access *a, unsigned char *msg) static void parse_name_list(struct pci_access *a) { - unsigned char *p = a->nl_list; - unsigned char *q, *r; + char *p = a->nl_list; + char *q, *r; int lino = 0; unsigned int id1=0, id2=0, id3=0, id4=0; int cat = -1; @@ -241,8 +241,8 @@ pci_free_name_list(struct pci_access *a) a->nl_hash = NULL; } -unsigned char * -pci_lookup_name(struct pci_access *a, unsigned char *buf, int size, int flags, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4) +char * +pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4) { int num = a->numeric_ids; int res; diff --git a/cmd/names.h b/cmd/names.h index dc32e9f..54dbcc7 100644 --- a/cmd/names.h +++ b/cmd/names.h @@ -23,12 +23,12 @@ struct pci_access { unsigned int numeric_ids; - unsigned char *pci_id_file_name; - unsigned char *nl_list; + char *pci_id_file_name; + char *nl_list; struct nl_entry **nl_hash; }; -extern unsigned char *pci_lookup_name(struct pci_access *a, unsigned char *buf, +extern char *pci_lookup_name(struct pci_access *a, char *buf, int size, int flags, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4); extern void pci_free_name_list(struct pci_access *a); diff --git a/cmd/systool.c b/cmd/systool.c index aaa90a9..bac39a0 100644 --- a/cmd/systool.c +++ b/cmd/systool.c @@ -82,7 +82,7 @@ static char *binary_files[] = { static int binfiles = 2; -static unsigned int get_pciconfig_word(int offset, unsigned char *buf) +static unsigned int get_pciconfig_word(int offset, char *buf) { unsigned short val = (unsigned char)buf[offset] | ((unsigned char)buf[offset+1] << 8); diff --git a/configure.ac b/configure.ac index ed801c0..33562a3 100644 --- a/configure.ac +++ b/configure.ac @@ -5,7 +5,7 @@ AC_CONFIG_SRCDIR([config.h.in]) AM_CONFIG_HEADER([config.h]) # Checks for KLIBC support (should be before AC_PROG_LIBTOOL and AC_PROG_CC) -AC_CHECK_KLIBC +dnl AC_CHECK_KLIBC if test "X$KLIBC" == Xyes; then # Should disable/enable building of shared libraries ... I am open to better diff --git a/lib/Makefile.am b/lib/Makefile.am index 8d37bcc..063489d 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -2,6 +2,6 @@ lib_LTLIBRARIES = libsysfs.la libsysfs_la_SOURCES = sysfs_utils.c sysfs_attr.c sysfs_class.c dlist.c \ sysfs_device.c sysfs_driver.c sysfs_bus.c sysfs_module.c sysfs.h INCLUDES = -I../include -libsysfs_la_LDFLAGS = -version-info 2:1:0 +libsysfs_la_LDFLAGS = -version-info 2:1:0 -Wl,--version-script=libsysfs.map -Wl,-z,defs EXTRA_CFLAGS = @EXTRA_CLFAGS@ libsysfs_la_CFLAGS = -Wall -W -Wstrict-prototypes $(EXTRA_CLFAGS) diff --git a/lib/dlist.c b/lib/dlist.c index a0c771a..a42245c 100644 --- a/lib/dlist.c +++ b/lib/dlist.c @@ -646,7 +646,7 @@ sort: No sense in juggling node pointers when we can just swap the data pointers */ -void _dlist_swap(struct dlist *list, struct dl_node *a, struct dl_node *b) +void _dlist_swap(struct dlist *list __attribute__((unused)), struct dl_node *a, struct dl_node *b) { void *swap=a->data; diff --git a/lib/libsysfs.map b/lib/libsysfs.map new file mode 100644 index 0000000..27f9c45 --- /dev/null +++ b/lib/libsysfs.map @@ -0,0 +1,19 @@ +SYSFS_2.1.0 { + global: + sysfs_close_dev_tree; + sysfs_open_device_tree; + sysfs_open_link_list; + sysfs_read_dir_subdirs; + local: + add_subdirectory; + get_attribute; + get_attributes_list; + get_dev_attributes_list; + read_dir_links; + read_dir_subdirs; + _[^d]*; + _d[^l]*; + _dl[^i]*; + _dli[^s]*; + _dlist[^_]*; +}; diff --git a/lib/sysfs_utils.c b/lib/sysfs_utils.c index 9ca207c..7e7dc54 100644 --- a/lib/sysfs_utils.c +++ b/lib/sysfs_utils.c @@ -22,6 +22,7 @@ */ #include "libsysfs.h" #include "sysfs.h" +#include /** * sysfs_remove_trailing_slash: Removes any trailing '/' in the given path @@ -53,6 +54,9 @@ int sysfs_get_mnt_path(char *mnt_path, size_t len) { static char sysfs_path[SYSFS_PATH_MAX] = ""; const char *sysfs_path_env; + FILE *mnt; + struct mntent *mntent; + int ret; if (len == 0 || mnt_path == NULL) return -1; @@ -64,12 +68,31 @@ int sysfs_get_mnt_path(char *mnt_path, size_t len) if (sysfs_path_env != NULL) { safestrcpymax(mnt_path, sysfs_path_env, len); sysfs_remove_trailing_slash(mnt_path); - return 0; + } else { + safestrcpymax(mnt_path, SYSFS_MNT_PATH, len); } - safestrcpymax(mnt_path, SYSFS_MNT_PATH, len); } - return 0; + /* check that mount point is indeed mounted */ + ret = -1; + if ((mnt = setmntent(SYSFS_PROC_MNTS, "r")) == NULL) { + dprintf("Error getting mount information\n"); + return -1; + } + while ((mntent = getmntent(mnt)) != NULL) { + if (strcmp(mntent->mnt_type, SYSFS_FSTYPE_NAME) == 0 && + strcmp(mntent->mnt_dir, mnt_path) == 0) { + ret = 0; + break; + } + } + + endmntent(mnt); + + if (ret < 0) + errno = ENOENT; + + return ret; } /** @@ -117,84 +140,104 @@ int sysfs_get_link(const char *path, char *target, size_t len) { char devdir[SYSFS_PATH_MAX]; char linkpath[SYSFS_PATH_MAX]; - char temp_path[SYSFS_PATH_MAX]; - char *d = NULL, *s = NULL; - int slashes = 0, count = 0; + char *d, *s; + int count; if (!path || !target || len == 0) { errno = EINVAL; return -1; } - memset(devdir, 0, SYSFS_PATH_MAX); - memset(linkpath, 0, SYSFS_PATH_MAX); - memset(temp_path, 0, SYSFS_PATH_MAX); - safestrcpy(devdir, path); - - if ((readlink(path, linkpath, SYSFS_PATH_MAX)) < 0) { + count = readlink(path, linkpath, SYSFS_PATH_MAX); + if (count < 0) return -1; - } - d = linkpath; + else + linkpath[count] = '\0'; /* * Three cases here: * 1. relative path => format ../.. * 2. absolute path => format /abcd/efgh * 3. relative path _from_ this dir => format abcd/efgh */ - switch (*d) { - case '.': + if (*linkpath == '/') { + /* absolute path - copy as is */ + safestrcpymax(target, linkpath, len); + return 0; + } + + safestrcpy(devdir, path); + s = strrchr(devdir, '/'); + if (s == NULL) + s = devdir - 1; + d = linkpath; + while (*d == '.') { + if (*(d+1) == '/') { /* * handle the case where link is of type ./abcd/xxx */ - safestrcpy(temp_path, devdir); - if (*(d+1) == '/') - d += 2; - else if (*(d+1) == '.') - goto parse_path; - s = strrchr(temp_path, '/'); - if (s != NULL) { - *(s+1) = '\0'; - safestrcat(temp_path, d); - } else { - safestrcpy(temp_path, d); - } - safestrcpymax(target, temp_path, len); - break; + d += 2; + while (*d == '/') + d++; + continue; + } else if (*(d+1) != '.' || *(d+2) != '/') /* - * relative path, getting rid of leading "../.." + * relative path from this directory, starting + * with a hidden directory */ -parse_path: - while (*d == '/' || *d == '.') { - if (*d == '/') - slashes++; - d++; - } - d--; - s = &devdir[strlen(devdir)-1]; - while (s != NULL && count != (slashes+1)) { + break; + + /* + * relative path, getting rid of leading "../.."; must + * be careful here since any path component of devdir + * could be a symlink again + */ + for (;;) { + while (s > devdir && *s == '/') { s--; - if (*s == '/') - count++; + if (*s == '.' + && (s == devdir || *(s-1) == '/')) + s--; } - safestrcpymax(s, d, (SYSFS_PATH_MAX-strlen(devdir))); - safestrcpymax(target, devdir, len); - break; - case '/': - /* absolute path - copy as is */ - safestrcpymax(target, linkpath, len); - break; - default: - /* relative path from this directory */ - safestrcpy(temp_path, devdir); - s = strrchr(temp_path, '/'); - if (s != NULL) { - *(s+1) = '\0'; - safestrcat(temp_path, linkpath); - } else { - safestrcpy(temp_path, linkpath); + *(s+1) = '\0'; + if (*devdir == '\0' || sysfs_path_is_link(devdir)) + /* + * condition will be true eventually + * because we already know that all + * but the last component of path + * resolve to a directory + */ + break; + if (sysfs_get_link(devdir, devdir, SYSFS_PATH_MAX)) + return -1; + s = devdir + strlen(devdir) - 1; + } + while (s >= devdir) { + if (*s == '/') { + if (*(s+1) != '.' || *(s+2) != '.' + || *(s+3) != '\0') { + d += 3; + while (*d == '/') + d++; + } else + s += 2; + break; } - safestrcpymax(target, temp_path, len); + s--; + } + if (s < devdir || *(s+1) == '\0') + break; } + + /* + * appending to devdir a slash and the (possibly shortened) + * relative path to the link source + */ + s++; + if (s > devdir && *s == '\0') + *s++ = '/'; + *s = '\0'; + safestrcpymax(s, d, SYSFS_PATH_MAX-(s-devdir)); + safestrcpymax(target, devdir, len); return 0; } diff --git a/test/Makefile.am b/test/Makefile.am index 953f2df..7730a7d 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,4 +1,4 @@ -bin_PROGRAMS = dlist_test get_device get_driver get_module +noinst_PROGRAMS = dlist_test get_device get_driver get_module BUILT_SOURCES = test.h CLEANFILES = test.h test.h: diff --git a/test/dlist_test.c b/test/dlist_test.c index d36f5f6..4b1c5d0 100644 --- a/test/dlist_test.c +++ b/test/dlist_test.c @@ -60,7 +60,7 @@ int complex_filter(void *a); Simple *simple_maker(int ,char *); -int main (int argc,char *argv[]) +int main (int argc __attribute__((unused)),char *argv[] __attribute__((unused))) { Dlist *list; Simple *s1,*s2,*s3,*stemp; diff --git a/test/get_driver.c b/test/get_driver.c index 51c6522..0929b83 100644 --- a/test/get_driver.c +++ b/test/get_driver.c @@ -37,7 +37,6 @@ int main(int argc, char *argv[]) struct sysfs_driver *driver = NULL; struct sysfs_device *device = NULL; struct dlist *devlist = NULL; - struct sysfs_attribute *attr = NULL; if (argc != 3) { print_usage();