From b50c94cbad719632bea966b68c566621413019b3 Mon Sep 17 00:00:00 2001 From: mananth Date: Mon, 24 Nov 2003 05:36:01 +0000 Subject: Postpone attr reads, remove getpagesize() usage, sysfs_driver.c cleanup remove sysutils references --- COPYING | 4 +- ChangeLog | 7 +++ README | 4 +- cmd/lsbus.c | 48 +++++++------- cmd/systool.c | 51 ++++++++------- include/libsysfs.h | 8 ++- lib/sysfs.h | 1 - lib/sysfs_bus.c | 12 +++- lib/sysfs_class.c | 14 +++-- lib/sysfs_device.c | 14 ++++- lib/sysfs_dir.c | 75 +++++++++++++++++----- lib/sysfs_driver.c | 181 ++++++++++++++++++++++++++++++++++------------------- lib/sysfs_utils.c | 4 +- test/get_driver.c | 18 +++++- 14 files changed, 291 insertions(+), 150 deletions(-) diff --git a/COPYING b/COPYING index a8ad126..355916d 100644 --- a/COPYING +++ b/COPYING @@ -2,9 +2,9 @@ The commands are licensed under the GNU General Public License (GPL) Version 2, June 1991. The full text of the GPL is located at: -sysutils/cmd/GPL +sysfsutils/cmd/GPL The sysfs library is licensed under the GNU Lesser Public License (LGPL) Version 2.1, February 1999. The full text of the LGPL is located at: -sysutils/lib/LGPL +sysfsutils/lib/LGPL diff --git a/ChangeLog b/ChangeLog index 3dedc31..47c35c1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,11 @@ +11/24/2003 - Ananth Mavinakayanahalli + * Removed getpagesize() usage (Dan) + * Added patch to postpone reading of attributes until + absolutely necessary + * Cleaned up sysfs_driver.c + * Changed stale sysutils references to sysfsutils + 11/04/2003 - Ananth Mavinakayanahalli * Added code to consider "block" part of "class" * Fixed systool to show driver details (if available) diff --git a/README b/README index a678a4e..6a33772 100644 --- a/README +++ b/README @@ -49,13 +49,13 @@ The commands are licensed under the GNU Public License (GPL) Version2, June 1991. The full text of the GPL is located in this package's "cmd" directory: -sysutils/cmd/GPL +sysfsutils/cmd/GPL The library is licensed under the GNU Lesser Public License (LGPL) Version 2.1, February 1999. The full text of the LGPL is located in this package's "lib" directory: -sysutils/lib/LGPL +sysfsutils/lib/LGPL 4. Reporting Bugs diff --git a/cmd/lsbus.c b/cmd/lsbus.c index 0c2e5ce..7082874 100644 --- a/cmd/lsbus.c +++ b/cmd/lsbus.c @@ -200,33 +200,35 @@ void print_device(struct sysfs_device *device) { struct dlist *attributes = NULL; unsigned int vendor_id, device_id; - unsigned char buf[128], *value = NULL; + unsigned char buf[128], path[SYSFS_PATH_MAX], value[256]; if (device != NULL) { - if (!(strcmp(bus_to_print, "pci"))) + if (!(strcmp(bus_to_print, "pci"))) { fprintf(stdout, " %s: ", device->bus_id); - else + memset(path, 0, SYSFS_PATH_MAX); + memset(value, 0, SYSFS_PATH_MAX); + strcpy(path, device->path); + strcat(path, "/config"); + if ((sysfs_read_attribute_value(path, + value, 256)) == 0) { + vendor_id = get_pciconfig_word + (PCI_VENDOR_ID, value); + device_id = get_pciconfig_word + (PCI_DEVICE_ID, value); + fprintf(stdout, "%s\n", + pci_lookup_name(pacc, buf, 128, + PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE, + vendor_id, device_id, 0, 0)); + } else + fprintf(stdout, "\n"); + } else fprintf(stdout, " %s:\n", device->bus_id); - attributes = sysfs_get_device_attributes(device); - if (attributes != NULL) { - if (!(strcmp(bus_to_print, "pci"))) { - value = sysfs_get_value_from_attributes - (attributes, "config"); - if (value != NULL) { - vendor_id = get_pciconfig_word - (PCI_VENDOR_ID, value); - device_id = get_pciconfig_word - (PCI_DEVICE_ID, value); - fprintf(stdout, "%s\n", - pci_lookup_name(pacc, buf, 128, - PCI_LOOKUP_VENDOR | - PCI_LOOKUP_DEVICE, - vendor_id, device_id, 0, 0)); - } - } - if (show_options & (SHOW_ATTRIBUTES | - SHOW_ATTRIBUTE_VALUE | SHOW_ALL_ATTRIB_VALUES)) - print_device_attributes(attributes); + + if (show_options & (SHOW_ATTRIBUTES | SHOW_ATTRIBUTE_VALUE | + SHOW_ALL_ATTRIB_VALUES)) { + attributes = sysfs_get_device_attributes(device); + if (attributes != NULL) + print_device_attributes(attributes); } if (isalnum(device->driver_name[0])) fprintf (stdout, "\tDriver: %s\n\n", diff --git a/cmd/systool.c b/cmd/systool.c index a2a6bbe..44dba5c 100644 --- a/cmd/systool.c +++ b/cmd/systool.c @@ -243,37 +243,36 @@ void show_device(struct sysfs_device *device, int level) { struct dlist *attributes = NULL; unsigned int vendor_id, device_id; - unsigned char buf[128], *value = NULL; + unsigned char buf[128], value[256], path[SYSFS_PATH_MAX]; if (device != NULL) { indent(level); - if (show_bus != NULL && (!(strcmp(show_bus, "pci")))) + if (show_bus != NULL && (!(strcmp(show_bus, "pci")))) { fprintf(stdout, "%s: ", device->bus_id); - else + memset(path, 0, SYSFS_PATH_MAX); + memset(value, 0, SYSFS_PATH_MAX); + strcpy(path, device->path); + strcat(path, "/config"); + if ((sysfs_read_attribute_value(path, + value, 256)) == 0) { + vendor_id = get_pciconfig_word + (PCI_VENDOR_ID, value); + device_id = get_pciconfig_word + (PCI_DEVICE_ID, value); + fprintf(stdout, "%s\n", + pci_lookup_name(pacc, buf, 128, + PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE, + vendor_id, device_id, 0, 0)); + } else + fprintf(stdout, "\n"); + } else fprintf(stdout, "%s\n", device->bus_id); - attributes = sysfs_get_device_attributes(device); - if (attributes != NULL) { - if (show_bus != NULL && (!(strcmp(show_bus, "pci")))) { - value = sysfs_get_value_from_attributes - (attributes, "config"); - if (value != NULL) { - vendor_id = get_pciconfig_word - (PCI_VENDOR_ID, value); - device_id = get_pciconfig_word - (PCI_DEVICE_ID, value); - fprintf(stdout, "%s\n", - pci_lookup_name(pacc, buf, 128, - PCI_LOOKUP_VENDOR | - PCI_LOOKUP_DEVICE, - vendor_id, device_id, - 0, 0)); - } - } - if (show_options & (SHOW_ATTRIBUTES | - SHOW_ATTRIBUTE_VALUE | + + if (show_options & (SHOW_ATTRIBUTES | SHOW_ATTRIBUTE_VALUE | SHOW_ALL_ATTRIB_VALUES)) { + attributes = sysfs_get_device_attributes(device); + if (attributes != NULL) show_attributes(attributes, (level+4)); - } } if (device->children != NULL) show_device_children(device->children, (level+4)); @@ -281,7 +280,7 @@ void show_device(struct sysfs_device *device, int level) indent(level+6); fprintf (stdout, "Driver: %s\n", device->driver_name); - } + } } } @@ -312,7 +311,7 @@ void show_driver_attributes(struct sysfs_driver *driver, int level) { if (driver != NULL) { struct dlist *attributes = NULL; - + attributes = sysfs_get_driver_attributes(driver); if (attributes != NULL) { struct sysfs_attribute *cur = NULL; diff --git a/include/libsysfs.h b/include/libsysfs.h index f7e989e..70cd5e8 100644 --- a/include/libsysfs.h +++ b/include/libsysfs.h @@ -163,6 +163,7 @@ extern unsigned char *sysfs_get_value_from_attributes(struct dlist *attr, const unsigned char * name); extern void sysfs_close_directory(struct sysfs_directory *sysdir); extern struct sysfs_directory *sysfs_open_directory(const unsigned char *path); +extern int sysfs_read_dir_attributes(struct sysfs_directory *sysdir); extern int sysfs_read_directory(struct sysfs_directory *sysdir); extern int sysfs_read_all_subdirs(struct sysfs_directory *sysdir); extern struct sysfs_directory *sysfs_get_subdirectory @@ -177,15 +178,16 @@ extern struct sysfs_attribute *sysfs_get_directory_attribute (struct sysfs_directory *dir, unsigned char *attrname); /* sysfs driver access */ +extern void sysfs_close_bus_driver(struct sysfs_driver *driver); +extern struct sysfs_driver *sysfs_open_bus_driver(const unsigned char *path); extern void sysfs_close_driver(struct sysfs_driver *driver); extern struct sysfs_driver *sysfs_open_driver(const unsigned char *path); extern struct sysfs_attribute *sysfs_get_driver_attr (struct sysfs_driver *drv, const unsigned char *name); extern struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *driver); extern struct dlist *sysfs_get_driver_links(struct sysfs_driver *driver); -extern void sysfs_close_driver_by_name(struct sysfs_driver *driver); -extern struct sysfs_driver *sysfs_open_driver_by_name - (const unsigned char *drv_name, const unsigned char *bus, size_t bsize); +extern struct sysfs_device *sysfs_get_driver_device + (struct sysfs_driver *driver, const unsigned char *name); extern struct sysfs_attribute *sysfs_open_driver_attr(const unsigned char *bus, const unsigned char *drv, const unsigned char *attrib); diff --git a/lib/sysfs.h b/lib/sysfs.h index 0059995..e4c148c 100644 --- a/lib/sysfs.h +++ b/lib/sysfs.h @@ -36,7 +36,6 @@ /* external library functions */ extern int lstat(const char *file_name, struct stat *buf); extern int readlink(const char *path, char *buf, size_t bufsize); -extern int getpagesize(void); extern int isascii(int c); /* Debugging */ diff --git a/lib/sysfs_bus.c b/lib/sysfs_bus.c index 3111154..ec5a6f6 100644 --- a/lib/sysfs_bus.c +++ b/lib/sysfs_bus.c @@ -30,7 +30,7 @@ static void sysfs_close_dev(void *dev) static void sysfs_close_drv(void *drv) { - sysfs_close_driver((struct sysfs_driver *)drv); + sysfs_close_bus_driver((struct sysfs_driver *)drv); } /* @@ -202,7 +202,7 @@ static int get_all_bus_drivers(struct sysfs_bus *bus) continue; dlist_for_each_data(cur->subdirs, cursub, struct sysfs_directory) { - driver = sysfs_open_driver(cursub->path); + driver = sysfs_open_bus_driver(cursub->path); if (driver == NULL) { dprintf("Error opening driver at %s\n", cursub->path); @@ -362,6 +362,10 @@ struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus) { if (bus == NULL || bus->directory == NULL) return NULL; + if (bus->directory->attributes == NULL) { + if ((sysfs_read_dir_attributes(bus->directory)) != 0) + return NULL; + } return bus->directory->attributes; } @@ -379,6 +383,10 @@ struct sysfs_attribute *sysfs_get_bus_attribute(struct sysfs_bus *bus, errno = EINVAL; return NULL; } + if (bus->directory->attributes == NULL) { + if ((sysfs_read_dir_attributes(bus->directory)) != 0) + return NULL; + } return sysfs_get_directory_attribute(bus->directory, attrname); } diff --git a/lib/sysfs_class.c b/lib/sysfs_class.c index d7521df..b57d8d7 100644 --- a/lib/sysfs_class.c +++ b/lib/sysfs_class.c @@ -236,7 +236,7 @@ struct sysfs_class_device *sysfs_open_class_device(const unsigned char *path) } } else if (strncmp(curl->name, SYSFS_DRIVERS_NAME, 6) == 0) { - drv = sysfs_open_driver(curl->target); + drv = sysfs_open_bus_driver(curl->target); if (drv != NULL) { cdev->driver = drv; if (cdev->sysdevice != NULL) { @@ -425,6 +425,10 @@ struct dlist *sysfs_get_classdev_attributes(struct sysfs_class_device *cdev) if (cdev == NULL || cdev->directory == NULL) return NULL; + if (cdev->directory->attributes == NULL) { + if ((sysfs_read_dir_attributes(cdev->directory)) != 0) + return NULL; + } return (cdev->directory->attributes); } @@ -439,12 +443,14 @@ struct sysfs_attribute *sysfs_get_classdev_attr { struct sysfs_attribute *cur = NULL; - if (clsdev == NULL || clsdev->directory == NULL || - clsdev->directory->attributes == NULL || name == NULL) { + if (clsdev == NULL || clsdev->directory == NULL || name == NULL) { errno = EINVAL; return NULL; } - + if (clsdev->directory->attributes == NULL) { + if ((sysfs_read_dir_attributes(clsdev->directory)) != 0) + return NULL; + } cur = sysfs_get_directory_attribute(clsdev->directory, (unsigned char *)name); if (cur != NULL) diff --git a/lib/sysfs_device.c b/lib/sysfs_device.c index fbd046f..01a7fc1 100644 --- a/lib/sysfs_device.c +++ b/lib/sysfs_device.c @@ -165,12 +165,16 @@ struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev, { struct sysfs_attribute *cur = NULL; - if (dev == NULL || dev->directory == NULL - || dev->directory->attributes == NULL || name == NULL) { + if (dev == NULL || dev->directory == NULL || name == NULL) { errno = EINVAL; return NULL; } + if (dev->directory->attributes == NULL) { + if ((sysfs_read_dir_attributes(dev->directory)) != 0) + return NULL; + } + cur = sysfs_get_directory_attribute(dev->directory, (unsigned char *)name); if (cur != NULL) @@ -316,7 +320,7 @@ static struct sysfs_directory *open_root_device_dir(const unsigned char *name) name); return NULL; } - if (sysfs_read_directory(rdir) != 0) { + if ((sysfs_read_directory(rdir)) != 0) { dprintf ("Error reading %s root device at dir %s\n", name, rootpath); sysfs_close_directory(rdir); @@ -409,6 +413,10 @@ struct dlist *sysfs_get_device_attributes(struct sysfs_device *device) if (device == NULL || device->directory == NULL) return NULL; + if (device->directory->attributes == NULL) { + if ((sysfs_read_dir_attributes(device->directory)) != 0) + return NULL; + } return (device->directory->attributes); } diff --git a/lib/sysfs_dir.c b/lib/sysfs_dir.c index ff2edf4..fabb695 100644 --- a/lib/sysfs_dir.c +++ b/lib/sysfs_dir.c @@ -254,7 +254,7 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr) unsigned char *fbuf = NULL; unsigned char *vbuf = NULL; size_t length = 0; - int pgsize = 0; + long pgsize = 0; int fd; if (sysattr == NULL) { @@ -266,7 +266,7 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr) sysattr->path); return -1; } - pgsize = getpagesize(); + pgsize = sysconf(_SC_PAGESIZE); fbuf = (unsigned char *)calloc(1, pgsize+1); if (fbuf == NULL) { dprintf("calloc failed\n"); @@ -423,7 +423,7 @@ int sysfs_read_all_subdirs(struct sysfs_directory *sysdir) if (sysdir->subdirs == NULL) return 0; dlist_for_each_data(sysdir->subdirs, cursub, struct sysfs_directory) { - if (sysfs_read_directory(cursub) != 0) + if ((sysfs_read_directory(cursub)) != 0) dprintf ("Error reading subdirectory %s\n", cursub->name); } @@ -490,18 +490,16 @@ struct sysfs_link *sysfs_open_link(const unsigned char *linkpath) } /** - * sysfs_read_directory: grabs attributes, links, and subdirectories + * sysfs_read_dir_attributes: grabs attributes for the given directory * @sysdir: sysfs directory to open * returns 0 with success and -1 with error. */ -int sysfs_read_directory(struct sysfs_directory *sysdir) +int sysfs_read_dir_attributes(struct sysfs_directory *sysdir) { DIR *dir = NULL; struct dirent *dirent = NULL; struct stat astats; struct sysfs_attribute *attr = NULL; - struct sysfs_directory *subdir = NULL; - struct sysfs_link *ln = NULL; unsigned char file_path[SYSFS_PATH_MAX]; int retval = 0; @@ -550,7 +548,51 @@ int sysfs_read_directory(struct sysfs_directory *sysdir) sysfs_del_attribute); } dlist_unshift(sysdir->attributes, attr); - } else if (S_ISDIR(astats.st_mode)) { + } + } + closedir(dir); + return(retval); +} + +/** + * sysfs_read_directory: grabs attributes, links, and subdirectories + * @sysdir: sysfs directory to open + * returns 0 with success and -1 with error. + */ +int sysfs_read_directory(struct sysfs_directory *sysdir) +{ + DIR *dir = NULL; + struct dirent *dirent = NULL; + struct stat astats; + struct sysfs_attribute *attr = NULL; + struct sysfs_directory *subdir = NULL; + struct sysfs_link *ln = NULL; + unsigned char file_path[SYSFS_PATH_MAX]; + int retval = 0; + + if (sysdir == NULL) { + errno = EINVAL; + return -1; + } + dir = opendir(sysdir->path); + if (dir == NULL) { + dprintf("Error opening directory %s\n", sysdir->path); + return -1; + } + while(((dirent = readdir(dir)) != NULL) && retval == 0) { + if (0 == strcmp(dirent->d_name, ".")) + continue; + if (0 == strcmp(dirent->d_name, "..")) + continue; + memset(file_path, 0, SYSFS_PATH_MAX); + strncpy(file_path, sysdir->path, sizeof(file_path)); + strncat(file_path, "/", sizeof(file_path)); + strncat(file_path, dirent->d_name, sizeof(file_path)); + if ((lstat(file_path, &astats)) != 0) { + dprintf("stat failed\n"); + continue; + } + if (S_ISDIR(astats.st_mode)) { subdir = sysfs_open_directory(file_path); if (subdir == NULL) { dprintf("Error opening directory %s\n", @@ -597,17 +639,20 @@ struct sysfs_attribute *sysfs_get_directory_attribute errno = EINVAL; return NULL; } - - attr = (struct sysfs_attribute *)dlist_find_custom(dir->attributes, - attrname, dir_attribute_name_equal); - if (attr != NULL) - return attr; + + if (dir->attributes == NULL) { + if ((sysfs_read_dir_attributes(dir)) != 0) { + return NULL; + } + attr = (struct sysfs_attribute *)dlist_find_custom + (dir->attributes, attrname, dir_attribute_name_equal); + if (attr != NULL) + return attr; + } if (dir->subdirs != NULL) { dlist_for_each_data(dir->subdirs, sdir, struct sysfs_directory) { - if (sdir->attributes == NULL) - continue; attr = sysfs_get_directory_attribute(sdir, attrname); if (attr != NULL) return attr; diff --git a/lib/sysfs_driver.c b/lib/sysfs_driver.c index 0011177..15eb239 100644 --- a/lib/sysfs_driver.c +++ b/lib/sysfs_driver.c @@ -23,17 +23,17 @@ #include "libsysfs.h" #include "sysfs.h" -static void sysfs_close_driver_by_name_dev(void *device) +static void sysfs_close_driver_device(void *device) { sysfs_close_device((struct sysfs_device *)device); } /** - * sysfs_close_driver: closes and cleans up driver structure + * sysfs_close_bus_driver: closes and cleans up driver structure * NOTE: This routine does not deallocate devices list * @driver: driver to close */ -void sysfs_close_driver(struct sysfs_driver *driver) +void sysfs_close_bus_driver(struct sysfs_driver *driver) { if (driver != NULL) { if (driver->devices != NULL) { @@ -49,10 +49,10 @@ void sysfs_close_driver(struct sysfs_driver *driver) } /** - * sysfs_close_driver_by_name: closes driver and deletes device lists too + * sysfs_close_driver: closes driver and deletes device lists too * @driver: driver to close */ -void sysfs_close_driver_by_name(struct sysfs_driver *driver) +void sysfs_close_driver(struct sysfs_driver *driver) { if (driver != NULL) { if (driver->devices != NULL) @@ -73,11 +73,11 @@ static struct sysfs_driver *alloc_driver(void) } /** - * sysfs_open_driver: opens and initializes driver structure + * sysfs_open_bus_driver: opens and initializes driver structure * @path: path to driver directory * returns struct sysfs_driver with success and NULL with error */ -struct sysfs_driver *sysfs_open_driver(const unsigned char *path) +struct sysfs_driver *sysfs_open_bus_driver(const unsigned char *path) { struct sysfs_driver *driver = NULL; struct sysfs_directory *sdir = NULL; @@ -120,6 +120,10 @@ struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *driver) if (driver == NULL || driver->directory == NULL) return NULL; + if (driver->directory->attributes == NULL) { + if ((sysfs_read_dir_attributes(driver->directory)) != 0) + return NULL; + } return(driver->directory->attributes); } @@ -134,12 +138,15 @@ struct sysfs_attribute *sysfs_get_driver_attr(struct sysfs_driver *drv, { struct sysfs_attribute *cur = NULL; - if (drv == NULL || drv->directory == NULL - || drv->directory->attributes == NULL || name == NULL) { + if (drv == NULL || drv->directory == NULL || name == NULL) { errno = EINVAL; return NULL; } + if (drv->directory->attributes == NULL) { + if ((sysfs_read_dir_attributes(drv->directory)) != 0) + return NULL; + } cur = sysfs_get_directory_attribute(drv->directory, (unsigned char *)name); if (cur != NULL) @@ -162,91 +169,137 @@ struct dlist *sysfs_get_driver_links(struct sysfs_driver *driver) return(driver->directory->links); } + /** - * get_driver_path: looks up the bus the driver is on and builds path to - * the driver. - * @bus: bus on which to search - * @drv: driver to look for - * @path: buffer to return path to driver - * @psize: size of "path" - * Returns 0 on success and -1 on error - */ -static int get_driver_path(const unsigned char *bus, const unsigned char *drv, - unsigned char *path, size_t psize) + * sysfs_open_driver_devices: open up the list of devices this driver supports + * @driver: sysfs_driver for which devices are needed + * Returns 0 on SUCCESS or -1 with ERROR + */ +static int sysfs_open_driver_devices(struct sysfs_driver *driver) { - if (bus == NULL || drv == NULL || path == NULL) { + struct sysfs_link *curlink = NULL; + struct sysfs_device *device = NULL; + + if (driver == NULL) { errno = EINVAL; return -1; } - if (sysfs_get_mnt_path(path, psize) != 0) { - dprintf("Error getting sysfs mount path\n"); - return -1; + + if (driver->devices != NULL) + return 0; + + if (driver->directory->links != NULL) { + dlist_for_each_data(driver->directory->links, curlink, + struct sysfs_link) { + device = sysfs_open_device(curlink->target); + if (device == NULL) { + dprintf("Error opening device at %s\n", + curlink->target); + return -1; + } + strcpy(device->driver_name, driver->name); + if (driver->devices == NULL) + driver->devices = dlist_new_with_delete + (sizeof(struct sysfs_device), + sysfs_close_driver_device); + dlist_unshift(driver->devices, device); + } } - strcat(path, SYSFS_BUS_DIR); - strcat(path, "/"); - strcat(path, bus); - strcat(path, SYSFS_DRIVERS_DIR); - strcat(path, "/"); - strcat(path, drv); return 0; } - /** - * sysfs_open_driver_by_name: open a driver by name and return the bus - * the driver is on. - * @drv_name: driver to open - * @bus: the driver bus - * @bsize: size of bus buffer + * sysfs_open_driver: open a driver given its path + * @path: path to driver to open * returns struct sysfs_driver if found, NULL otherwise * NOTE: - * 1. Need to call sysfs_close_driver_by_name to free up memory - * 2. Bus the driver is registered with must be supplied. - * Use sysfs_find_driver_bus() to obtain the bus name + * 1. Need to call sysfs_close_driver to free up memory */ -struct sysfs_driver *sysfs_open_driver_by_name(const unsigned char *drv_name, - const unsigned char *bus, size_t bsize) +struct sysfs_driver *sysfs_open_driver(const unsigned char *path) { struct sysfs_driver *driver = NULL; - struct sysfs_device *device = NULL; - struct sysfs_link *curlink = NULL; - unsigned char path[SYSFS_PATH_MAX]; - if (drv_name == NULL || bus == NULL) { + if (path == NULL) { errno = EINVAL; return NULL; } - memset(path, 0, SYSFS_PATH_MAX); - if (get_driver_path(bus, drv_name, path, SYSFS_PATH_MAX) != 0) { - dprintf("Error getting to driver %s\n", drv_name); - return NULL; - } - driver = sysfs_open_driver(path); + driver = sysfs_open_bus_driver(path); if (driver == NULL) { dprintf("Could not open driver %s\n", drv_name); return NULL; } if (driver->directory->links != NULL) { - dlist_for_each_data(driver->directory->links, curlink, - struct sysfs_link) { - device = sysfs_open_device(curlink->target); - if (device == NULL) { - dprintf("Error opening device at %s\n", - curlink->target); - sysfs_close_driver_by_name(driver); + if ((sysfs_open_driver_devices(driver)) != 0) { + dprintf("Error reading driver devices\n"); + sysfs_close_driver(driver); + return NULL; + } + } + return driver; +} + +/** + * sysfs_get_driver_device: looks up a device from a list of driver's devices + * and returns its sysfs_device corresponding to it + * @driver: sysfs_driver on which to search + * @name: name of the device to search + * Returns a sysfs_device if found, NULL otherwise + */ +struct sysfs_device *sysfs_get_driver_device(struct sysfs_driver *driver, + const unsigned char *name) +{ + struct sysfs_device *device = NULL; + + if (driver == NULL || name == NULL) { + errno = EINVAL; + return NULL; + } + + if (driver->devices == NULL) { + if (driver->directory->links == NULL) { + return NULL; + } else { + if ((sysfs_open_driver_devices(driver)) != 0) { + dprintf("Error getting driver devices\n"); return NULL; } - strcpy(device->driver_name, drv_name); - if (driver->devices == NULL) - driver->devices = dlist_new_with_delete - (sizeof(struct sysfs_device), - sysfs_close_driver_by_name_dev); - dlist_unshift(driver->devices, device); } } - return driver; + dlist_for_each_data(driver->devices, device, struct sysfs_device) { + if (!(strncmp(device->name, name, SYSFS_NAME_LEN))) + return device; + } + return NULL; } +/** + * get_driver_path: looks up the bus the driver is on and builds path to + * the driver. + * @bus: bus on which to search + * @drv: driver to look for + * @path: buffer to return path to driver + * @psize: size of "path" + * Returns 0 on success and -1 on error + */ +static int get_driver_path(const unsigned char *bus, + const unsigned char *drv, unsigned char *path, size_t psize) +{ + if (bus == NULL || drv == NULL || path == NULL) { + errno = EINVAL; + return -1; + } + if (sysfs_get_mnt_path(path, psize) != 0) { + dprintf("Error getting sysfs mount path\n"); + return -1; + } + strcat(path, SYSFS_BUS_DIR); + strcat(path, "/"); + strcat(path, bus); + strcat(path, SYSFS_DRIVERS_DIR); + strcat(path, "/"); + strcat(path, drv); + return 0; +} /** * sysfs_open_driver_attr: read the user supplied driver attribute diff --git a/lib/sysfs_utils.c b/lib/sysfs_utils.c index 7563dff..ede4058 100644 --- a/lib/sysfs_utils.c +++ b/lib/sysfs_utils.c @@ -225,7 +225,7 @@ struct dlist *sysfs_open_subsystem_list(unsigned char *name) return NULL; } - if (sysfs_read_directory(dir) != 0) { + if ((sysfs_read_directory(dir)) != 0) { dprintf("Error reading sysfs_directory at %s\n", sysfs_path); sysfs_close_directory(dir); return NULL; @@ -303,7 +303,7 @@ struct dlist *sysfs_open_bus_devices_list(unsigned char *name) return NULL; } - if (sysfs_read_directory(dir) != 0) { + if ((sysfs_read_directory(dir)) != 0) { dprintf("Error reading sysfs_directory at %s\n", sysfs_path); sysfs_close_directory(dir); return NULL; diff --git a/test/get_driver.c b/test/get_driver.c index 8628486..107c9bf 100644 --- a/test/get_driver.c +++ b/test/get_driver.c @@ -32,7 +32,7 @@ void print_usage(void) int main(int argc, char *argv[]) { - char *bus = NULL; + char *bus = NULL, path[SYSFS_PATH_MAX]; struct sysfs_driver *driver = NULL; struct sysfs_device *device = NULL; @@ -41,6 +41,7 @@ int main(int argc, char *argv[]) return 1; } + memset(path, 0, SYSFS_PATH_MAX); bus = (char *)calloc(1, SYSFS_NAME_LEN); if ((sysfs_find_driver_bus(argv[1], bus, SYSFS_NAME_LEN)) < 0) { fprintf(stdout, "Driver %s not found\n", argv[1]); @@ -48,7 +49,18 @@ int main(int argc, char *argv[]) return 1; } fprintf(stdout, "Driver %s is a member of bus %s\n", argv[1], bus); - driver = sysfs_open_driver_by_name(argv[1], bus, SYSFS_NAME_LEN); + + if ((sysfs_get_mnt_path(path, SYSFS_PATH_MAX)) != 0) { + fprintf(stdout, "Sysfs not mounted?\n"); + return 1; + } + strcat(path, SYSFS_BUS_DIR); + strcat(path, "/"); + strcat(path, bus); + strcat(path, SYSFS_DRIVERS_DIR); + strcat(path, "/"); + strcat(path, argv[1]); + driver = sysfs_open_driver(path); if (driver == NULL) { fprintf(stdout, "Device %s not found\n", argv[1]); free(bus); @@ -61,7 +73,7 @@ int main(int argc, char *argv[]) } else fprintf(stdout, "%s is presently not used by any device\n", argv[1]); - sysfs_close_driver_by_name(driver); + sysfs_close_driver(driver); free(bus); return 0; } -- cgit v1.2.1