From e1660f07958223956f3b4fac6f66eecaa002ab92 Mon Sep 17 00:00:00 2001 From: mananth Date: Thu, 4 Dec 2003 06:06:58 +0000 Subject: This is the complete optimization patch --- ChangeLog | 3 + cmd/lsbus.c | 62 ++++++------ cmd/systool.c | 111 +++++++++++---------- include/libsysfs.h | 30 +++--- lib/sysfs_bus.c | 142 +++++++++++++++------------ lib/sysfs_class.c | 272 +++++++++++++++++++++++++++++++-------------------- lib/sysfs_device.c | 197 +++++++++++++++++++------------------ lib/sysfs_dir.c | 1 + lib/sysfs_driver.c | 195 ++++++++++++++++++------------------ lib/sysfs_utils.c | 24 ++++- test/get_class_dev.c | 8 +- test/get_driver.c | 6 +- 12 files changed, 593 insertions(+), 458 deletions(-) diff --git a/ChangeLog b/ChangeLog index 47c35c1..22d5d36 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,7 @@ +11/27/2003 - Ananth Mavinakayanahalli + * Updated library and utilities with the optimization patch + 11/24/2003 - Ananth Mavinakayanahalli * Removed getpagesize() usage (Dan) * Added patch to postpone reading of attributes until diff --git a/cmd/lsbus.c b/cmd/lsbus.c index 7082874..89b3562 100644 --- a/cmd/lsbus.c +++ b/cmd/lsbus.c @@ -258,33 +258,24 @@ void print_driver_attributes(struct sysfs_driver *driver) } } -/** - * print_driver_devices: prints out devices under driver. - * @driver: print devices bound to this driver. - */ -void print_driver_devices(struct sysfs_driver *driver) -{ - struct sysfs_device *device = NULL; - - if (driver != NULL) { - if (driver->devices != NULL) { - fprintf (stdout, "\tDevices:\n"); - dlist_for_each_data(driver->devices, device, - struct sysfs_device) - fprintf(stdout, "\t\t%s\n", device->bus_id); - } - } -} - /** * print_driver: prints out driver information. * @driver: driver to print. */ void print_driver(struct sysfs_driver *driver) { + struct dlist *devlist = NULL; + if (driver != NULL) { fprintf (stdout, " %s\n", driver->name); - print_driver_devices(driver); + devlist = sysfs_get_driver_devices(driver); + if (devlist != NULL) { + struct sysfs_device *dev = NULL; + fprintf(stdout, "\tDevices:\n"); + dlist_for_each_data(driver->devices, dev, + struct sysfs_device) + fprintf(stdout, "\t\t%s\n", dev->bus_id); + } if(show_options & (SHOW_ATTRIBUTES | SHOW_ATTRIBUTE_VALUE | SHOW_ALL_ATTRIB_VALUES)) print_driver_attributes(driver); @@ -301,6 +292,8 @@ int print_sysfs_bus(unsigned char *busname) struct sysfs_bus *bus = NULL; struct sysfs_device *curdev = NULL; struct sysfs_driver *curdrv = NULL; + struct dlist *devlist = NULL; + struct dlist *drvlist = NULL; if (busname == NULL) { errno = EINVAL; @@ -313,20 +306,27 @@ int print_sysfs_bus(unsigned char *busname) } fprintf(stdout, "Bus: %s\n", busname); - if (bus->devices != NULL && (show_options & SHOW_DEVICES)) { - if (bus_device == NULL) - fprintf(stdout, "Devices:\n"); - dlist_for_each_data(bus->devices, curdev, - struct sysfs_device) { - if (bus_device == NULL || (strcmp(bus_device, - curdev->bus_id) == 0)) - print_device(curdev); + if (show_options & SHOW_DEVICES) { + devlist = sysfs_get_bus_devices(bus); + if (devlist != NULL) { + if (bus_device == NULL) + fprintf(stdout, "Devices:\n"); + dlist_for_each_data(bus->devices, curdev, + struct sysfs_device) { + if (bus_device == NULL || (strcmp(bus_device, + curdev->bus_id) == 0)) + print_device(curdev); + } } } - if (bus->drivers != NULL && (show_options & SHOW_DRIVERS)) { - fprintf(stdout, "Drivers:\n"); - dlist_for_each_data(bus->drivers, curdrv, struct sysfs_driver) { - print_driver(curdrv); + if (show_options & SHOW_DRIVERS) { + drvlist = sysfs_get_bus_drivers(bus); + if (drvlist != NULL) { + fprintf(stdout, "Drivers:\n"); + dlist_for_each_data(bus->drivers, curdrv, + struct sysfs_driver) { + print_driver(curdrv); + } } } sysfs_close_bus(bus); diff --git a/cmd/systool.c b/cmd/systool.c index 44dba5c..5a675b5 100644 --- a/cmd/systool.c +++ b/cmd/systool.c @@ -326,39 +326,29 @@ void show_driver_attributes(struct sysfs_driver *driver, int level) } } -/** - * show_driver_devices: prints out devices under driver. - * @driver: print devices bound to this driver. - */ -void show_driver_devices(struct sysfs_driver *driver, int level) -{ - if (driver != NULL) { - if (driver->devices != NULL) { - struct sysfs_device *cur = NULL; - - indent(level); - fprintf (stdout, "Devices:\n"); - dlist_for_each_data(driver->devices, cur, - struct sysfs_device) { - indent(level+4); - fprintf (stdout, "%s\n", cur->bus_id); - } - } - } -} - /** * show_driver: prints out driver information. * @driver: driver to print. */ void show_driver(struct sysfs_driver *driver, int level) { + struct dlist *devlist = NULL; + if (driver != NULL) { indent(level); fprintf (stdout, "%s\n", driver->name); - if (driver->devices != NULL) - show_driver_devices(driver, (level+4)); + devlist = sysfs_get_driver_devices(driver); + if (devlist != NULL) { + struct sysfs_device *cur = NULL; + indent(level+4); + fprintf(stdout, "Devices:\n"); + dlist_for_each_data(devlist, cur, + struct sysfs_device) { + indent(level+8); + fprintf(stdout, "%s\n", cur->bus_id); + } + } if (show_options & (SHOW_ATTRIBUTES | SHOW_ATTRIBUTE_VALUE | SHOW_ALL_ATTRIB_VALUES)) show_driver_attributes(driver, (level+4)); @@ -397,6 +387,8 @@ int show_sysfs_bus(unsigned char *busname) struct sysfs_bus *bus = NULL; struct sysfs_device *curdev = NULL; struct sysfs_driver *curdrv = NULL; + struct dlist *devlist = NULL; + struct dlist *drvlist = NULL; if (busname == NULL) { errno = EINVAL; @@ -409,19 +401,28 @@ int show_sysfs_bus(unsigned char *busname) } fprintf(stdout, "Bus: %s\n", busname); - if (bus->devices != NULL && (show_options & SHOW_DEVICES)) { - if (device_to_show == NULL) - fprintf(stdout, "Devices:\n"); - dlist_for_each_data(bus->devices, curdev, struct sysfs_device) { - if (device_to_show == NULL || (strcmp(device_to_show, - curdev->bus_id) == 0)) - show_device(curdev, 2); + if (show_options & SHOW_DEVICES) { + devlist = sysfs_get_bus_devices(bus); + if (devlist != NULL) { + if (device_to_show == NULL) + fprintf(stdout, "Devices:\n"); + dlist_for_each_data(bus->devices, curdev, + struct sysfs_device) { + if (device_to_show == NULL || + (strcmp(device_to_show, + curdev->bus_id) == 0)) + show_device(curdev, 2); + } } } - if (bus->drivers != NULL && (show_options & SHOW_DRIVERS)) { - fprintf(stdout, "Drivers:\n"); - dlist_for_each_data(bus->drivers, curdrv, struct sysfs_driver) { - show_driver(curdrv, 2); + if (show_options & SHOW_DRIVERS) { + drvlist = sysfs_get_bus_drivers(bus); + if (drvlist != NULL) { + fprintf(stdout, "Drivers:\n"); + dlist_for_each_data(bus->drivers, curdrv, + struct sysfs_driver) { + show_driver(curdrv, 2); + } } } sysfs_close_bus(bus); @@ -435,6 +436,8 @@ int show_sysfs_bus(unsigned char *busname) void show_class_device(struct sysfs_class_device *dev, int level) { struct dlist *attributes = NULL; + struct sysfs_device *device = NULL; + struct sysfs_driver *driver = NULL; if (dev != NULL) { indent(level); @@ -444,13 +447,17 @@ void show_class_device(struct sysfs_class_device *dev, int level) attributes = sysfs_get_classdev_attributes(dev); if (attributes != NULL) show_attributes(attributes, (level+4)); - } - if (dev->sysdevice != NULL && (show_options & (SHOW_DEVICES | - SHOW_ALL_ATTRIB_VALUES))) - show_device(dev->sysdevice, (level+4)); - if (dev->driver != NULL && (show_options & (SHOW_DRIVERS | - SHOW_ALL_ATTRIB_VALUES))) - show_driver(dev->driver, (level+4)); + } + if (show_options & (SHOW_DEVICES | SHOW_ALL_ATTRIB_VALUES)) { + device = sysfs_get_classdev_device(dev); + if (device != NULL) + show_device(device, (level+4)); + } + if (show_options & (SHOW_DRIVERS | SHOW_ALL_ATTRIB_VALUES)) { + driver = sysfs_get_classdev_driver(dev); + if (driver != NULL) + show_driver(driver, (level+4)); + } } } @@ -463,6 +470,7 @@ int show_sysfs_class(unsigned char *classname) { struct sysfs_class *cls = NULL; struct sysfs_class_device *cur = NULL; + struct dlist *clsdevlist = NULL; if (classname == NULL) { errno = EINVAL; @@ -474,10 +482,11 @@ int show_sysfs_class(unsigned char *classname) return 1; } fprintf(stdout, "Class: %s\n", classname); - if (cls->devices != NULL) { + clsdevlist = sysfs_get_class_devices(cls); + if (clsdevlist != NULL) { if (device_to_show == NULL) fprintf(stdout, "Class Devices:\n"); - dlist_for_each_data(cls->devices, cur, + dlist_for_each_data(clsdevlist, cur, struct sysfs_class_device) { if (device_to_show == NULL || (strcmp(device_to_show, cur->name) == 0)) @@ -498,6 +507,7 @@ int show_sysfs_root(unsigned char *rootname) { struct sysfs_root_device *root = NULL; struct sysfs_device *device = NULL; + struct dlist *devlist = NULL; unsigned char path[SYSFS_PATH_MAX]; if (rootname == NULL) { @@ -510,12 +520,15 @@ int show_sysfs_root(unsigned char *rootname) return 1; } - fprintf(stdout, "Root Device Tree: %s\n", rootname); - - if (root->devices != NULL) { - dlist_for_each_data(root->devices, device, - struct sysfs_device) { - show_device_tree(device, 2); + devlist = sysfs_get_root_devices(root); + if (devlist != NULL) { + fprintf(stdout, "Root Device Tree: %s\n", rootname); + + if (devlist != NULL) { + dlist_for_each_data(devlist, device, + struct sysfs_device) { + show_device_tree(device, 2); + } } } sysfs_close_root_device(root); diff --git a/include/libsysfs.h b/include/libsysfs.h index 70cd5e8..ee2b23d 100644 --- a/include/libsysfs.h +++ b/include/libsysfs.h @@ -75,17 +75,15 @@ struct sysfs_directory { }; struct sysfs_driver { - struct dlist *devices; unsigned char name[SYSFS_NAME_LEN]; unsigned char path[SYSFS_PATH_MAX]; /* for internal use only */ + struct dlist *devices; struct sysfs_directory *directory; }; struct sysfs_device { - struct sysfs_device *parent; - struct dlist *children; unsigned char name[SYSFS_NAME_LEN]; unsigned char bus_id[SYSFS_NAME_LEN]; unsigned char bus[SYSFS_NAME_LEN]; @@ -93,45 +91,47 @@ struct sysfs_device { unsigned char path[SYSFS_PATH_MAX]; /* for internal use only */ + struct sysfs_device *parent; + struct dlist *children; struct sysfs_directory *directory; }; struct sysfs_root_device { - struct dlist *devices; unsigned char name[SYSFS_NAME_LEN]; unsigned char path[SYSFS_PATH_MAX]; /* for internal use only */ + struct dlist *devices; struct sysfs_directory *directory; }; struct sysfs_bus { - struct dlist *drivers; - struct dlist *devices; unsigned char name[SYSFS_NAME_LEN]; unsigned char path[SYSFS_PATH_MAX]; /* internal use only */ + struct dlist *drivers; + struct dlist *devices; struct sysfs_directory *directory; }; struct sysfs_class_device { - struct sysfs_device *sysdevice; /* NULL if virtual */ - struct sysfs_driver *driver; /* NULL if not implemented */ unsigned char name[SYSFS_NAME_LEN]; unsigned char classname[SYSFS_NAME_LEN]; unsigned char path[SYSFS_PATH_MAX]; /* for internal use only */ + struct sysfs_device *sysdevice; /* NULL if virtual */ + struct sysfs_driver *driver; /* NULL if not implemented */ struct sysfs_directory *directory; }; struct sysfs_class { - struct dlist *devices; unsigned char name[SYSFS_NAME_LEN]; unsigned char path[SYSFS_PATH_MAX]; /* for internal use only */ + struct dlist *devices; struct sysfs_directory *directory; }; @@ -145,6 +145,7 @@ extern "C" { extern int sysfs_get_mnt_path(unsigned char *mnt_path, size_t len); extern int sysfs_get_name_from_path(const unsigned char *path, unsigned char *name, size_t len); +extern int sysfs_path_is_dir(const unsigned char *path); extern int sysfs_get_link(const unsigned char *path, unsigned char *target, size_t len); extern struct dlist *sysfs_open_subsystem_list(unsigned char *name); @@ -178,13 +179,12 @@ 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_devices(struct sysfs_driver *driver); extern struct dlist *sysfs_get_driver_links(struct sysfs_driver *driver); extern struct sysfs_device *sysfs_get_driver_device (struct sysfs_driver *driver, const unsigned char *name); @@ -195,6 +195,7 @@ extern struct sysfs_attribute *sysfs_open_driver_attr(const unsigned char *bus, extern void sysfs_close_root_device(struct sysfs_root_device *root); extern struct sysfs_root_device *sysfs_open_root_device (const unsigned char *name); +extern struct dlist *sysfs_get_root_devices(struct sysfs_root_device *root); extern void sysfs_close_device(struct sysfs_device *dev); extern struct sysfs_device *sysfs_open_device(const unsigned char *path); extern struct sysfs_attribute *sysfs_get_device_attr @@ -212,6 +213,8 @@ extern struct sysfs_device *sysfs_get_bus_device(struct sysfs_bus *bus, unsigned char *id); extern struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus, unsigned char *drvname); +extern struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus); +extern struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus); extern struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus); extern struct sysfs_attribute *sysfs_get_bus_attribute(struct sysfs_bus *bus, unsigned char *attrname); @@ -224,8 +227,13 @@ extern int sysfs_find_driver_bus(const unsigned char *driver, extern void sysfs_close_class_device(struct sysfs_class_device *dev); extern struct sysfs_class_device *sysfs_open_class_device (const unsigned char *path); +extern struct sysfs_device *sysfs_get_classdev_device + (struct sysfs_class_device *clsdev); +extern struct sysfs_driver *sysfs_get_classdev_driver + (struct sysfs_class_device *clsdev); extern void sysfs_close_class(struct sysfs_class *cls); extern struct sysfs_class *sysfs_open_class(const unsigned char *name); +extern struct dlist *sysfs_get_class_devices(struct sysfs_class *cls); extern struct sysfs_class_device *sysfs_get_class_device (struct sysfs_class *class, unsigned char *name); extern struct sysfs_class_device *sysfs_open_class_device_by_name diff --git a/lib/sysfs_bus.c b/lib/sysfs_bus.c index ec5a6f6..eb21e10 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_bus_driver((struct sysfs_driver *)drv); + sysfs_close_driver((struct sysfs_driver *)drv); } /* @@ -96,35 +96,22 @@ static struct sysfs_bus *alloc_bus(void) * open_bus_dir: opens up sysfs bus directory * returns sysfs_directory struct with success and NULL with error */ -static struct sysfs_directory *open_bus_dir(const unsigned char *name) +static struct sysfs_directory *open_bus_dir(const unsigned char *buspath) { struct sysfs_directory *busdir = NULL; - unsigned char buspath[SYSFS_PATH_MAX]; - if (name == NULL) { + if (buspath == NULL) { errno = EINVAL; return NULL; } - memset(buspath, 0, SYSFS_PATH_MAX); - if ((sysfs_get_mnt_path(buspath, SYSFS_PATH_MAX)) != 0) { - dprintf("Sysfs not supported on this system\n"); - return NULL; - } - - strcat(buspath, SYSFS_BUS_DIR); - strcat(buspath, "/"); - strcat(buspath, name); busdir = sysfs_open_directory(buspath); if (busdir == NULL) { - errno = EINVAL; - dprintf("Bus %s not supported on this system\n", - name); + dprintf("Error opening directory at path %s\n", buspath); return NULL; } if ((sysfs_read_directory(busdir)) != 0) { - dprintf("Error reading %s bus dir %s\n", name, - buspath); + dprintf("Error reading bus dir %s\n", buspath); sysfs_close_directory(busdir); return NULL; } @@ -135,22 +122,27 @@ static struct sysfs_directory *open_bus_dir(const unsigned char *name) } /** - * get_all_bus_devices: gets all devices for bus + * sysfs_get_bus_devices: gets all devices for bus * @bus: bus to get devices for - * returns 0 with success and -1 with failure + * returns dlist of devices with success and NULL with failure */ -static int get_all_bus_devices(struct sysfs_bus *bus) +struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus) { struct sysfs_device *bdev = NULL; struct sysfs_directory *cur = NULL; struct sysfs_link *curl = NULL; - if (bus == NULL || bus->directory == NULL) { + if (bus == NULL) { errno = EINVAL; - return -1; + return NULL; + } + if (bus->directory == NULL) { + bus->directory = open_bus_dir(bus->path); + if (bus->directory == NULL) + return NULL; } if (bus->directory->subdirs == NULL) - return 0; + return NULL; dlist_for_each_data(bus->directory->subdirs, cur, struct sysfs_directory) { @@ -173,26 +165,31 @@ static int get_all_bus_devices(struct sysfs_bus *bus) } } - return 0; + return (bus->devices); } /** - * get_all_bus_drivers: get all pci drivers + * sysfs_get_bus_drivers: get all pci drivers * @bus: pci bus to add drivers to - * returns 0 with success and -1 with error + * returns dlist of drivers with success and NULL with error */ -static int get_all_bus_drivers(struct sysfs_bus *bus) +struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus) { struct sysfs_driver *driver = NULL; struct sysfs_directory *cur = NULL; struct sysfs_directory *cursub = NULL; - if (bus == NULL || bus->directory == NULL) { + if (bus == NULL) { errno = EINVAL; - return -1; + return NULL; + } + if (bus->directory == NULL) { + bus->directory = open_bus_dir(bus->path); + if (bus->directory == NULL) + return NULL; } if (bus->directory->subdirs == NULL) - return 0; + return NULL; dlist_for_each_data(bus->directory->subdirs, cur, struct sysfs_directory) { @@ -202,7 +199,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_bus_driver(cursub->path); + driver = sysfs_open_driver(cursub->path); if (driver == NULL) { dprintf("Error opening driver at %s\n", cursub->path); @@ -215,8 +212,7 @@ static int get_all_bus_drivers(struct sysfs_bus *bus) dlist_unshift(bus->drivers, driver); } } - - return 0; + return (bus->drivers); } /** @@ -229,14 +225,17 @@ static int match_bus_device_to_driver(struct sysfs_driver *driver, unsigned char *busid) { struct sysfs_link *cur = NULL; + struct dlist *links = NULL; int found = 0; - if (driver == NULL || driver->directory == NULL || busid == NULL) { + if (driver == NULL || busid == NULL) { errno = EINVAL; return found; } - if (driver->directory->links != NULL) { - dlist_for_each_data(driver->directory->links, cur, + + links = sysfs_get_driver_links(driver); + if (links != NULL) { + dlist_for_each_data(links, cur, struct sysfs_link) { if ((strcmp(cur->name, busid)) == 0) found++; @@ -280,39 +279,33 @@ static void link_bus_devices_to_drivers(struct sysfs_bus *bus) struct sysfs_bus *sysfs_open_bus(const unsigned char *name) { struct sysfs_bus *bus = NULL; - struct sysfs_directory *busdir = NULL; + unsigned char buspath[SYSFS_PATH_MAX]; if (name == NULL) { errno = EINVAL; return NULL; } - bus = alloc_bus(); - if (bus == NULL) { - dprintf("calloc failed\n"); - return NULL; - } - strcpy(bus->name, name); - busdir = open_bus_dir(name); - if (busdir == NULL) { - dprintf("Invalid bus, %s not supported on this system\n", - name); - sysfs_close_bus(bus); + memset(buspath, 0, SYSFS_PATH_MAX); + if ((sysfs_get_mnt_path(buspath, SYSFS_PATH_MAX)) != 0) { + dprintf("Sysfs not supported on this system\n"); return NULL; } - strcpy(bus->path, busdir->path); - bus->directory = busdir; - if ((get_all_bus_devices(bus)) != 0) { - dprintf("Error reading %s bus devices\n", name); - sysfs_close_bus(bus); + + strcat(buspath, SYSFS_BUS_DIR); + strcat(buspath, "/"); + strcat(buspath, name); + if ((sysfs_path_is_dir(buspath)) != 0) { + dprintf("Invalid path to bus: %s\n", buspath); return NULL; } - if ((get_all_bus_drivers(bus)) != 0) { - dprintf("Error reading %s bus drivers\n", name); - sysfs_close_bus(bus); + bus = alloc_bus(); + if (bus == NULL) { + dprintf("calloc failed\n"); return NULL; } - link_bus_devices_to_drivers(bus); + strcpy(bus->name, name); + strcpy(bus->path, buspath); return bus; } @@ -326,11 +319,19 @@ struct sysfs_bus *sysfs_open_bus(const unsigned char *name) struct sysfs_device *sysfs_get_bus_device(struct sysfs_bus *bus, unsigned char *id) { + struct dlist *devlist = NULL; + if (bus == NULL || id == NULL) { errno = EINVAL; return NULL; } + if (bus->devices == NULL) { + bus->devices = sysfs_get_bus_devices(bus); + if (bus->devices == NULL) + return NULL; + } + return (struct sysfs_device *)dlist_find_custom(bus->devices, id, bus_device_id_equal); } @@ -349,6 +350,12 @@ struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus, return NULL; } + if (bus->drivers == NULL) { + bus->drivers = sysfs_get_bus_drivers(bus); + if (bus->drivers == NULL) + return NULL; + } + return (struct sysfs_driver *)dlist_find_custom(bus->drivers, drvname, bus_driver_name_equal); } @@ -360,8 +367,13 @@ struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus, */ struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus) { - if (bus == NULL || bus->directory == NULL) + if (bus == NULL) return NULL; + if (bus->directory == NULL) { + bus->directory = sysfs_open_directory(bus->path); + if (bus->directory == NULL) + return NULL; + } if (bus->directory->attributes == NULL) { if ((sysfs_read_dir_attributes(bus->directory)) != 0) return NULL; @@ -379,14 +391,16 @@ struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus) struct sysfs_attribute *sysfs_get_bus_attribute(struct sysfs_bus *bus, unsigned char *attrname) { - if (bus == NULL || bus->directory == NULL || attrname == NULL) { + struct dlist *attrlist = NULL; + + if (bus == NULL) { errno = EINVAL; return NULL; } - if (bus->directory->attributes == NULL) { - if ((sysfs_read_dir_attributes(bus->directory)) != 0) - return NULL; - } + attrlist = sysfs_get_bus_attributes(bus); + if (attrlist == NULL) + return NULL; + return sysfs_get_directory_attribute(bus->directory, attrname); } diff --git a/lib/sysfs_class.c b/lib/sysfs_class.c index b57d8d7..5efe166 100644 --- a/lib/sysfs_class.c +++ b/lib/sysfs_class.c @@ -100,41 +100,22 @@ static struct sysfs_class *alloc_class(void) * open_class_dir: opens up sysfs class directory * returns sysfs_directory struct with success and NULL with error */ -static struct sysfs_directory *open_class_dir(const unsigned char *name) +static struct sysfs_directory *open_class_dir(const unsigned char *path) { struct sysfs_directory *classdir = NULL; - unsigned char classpath[SYSFS_PATH_MAX]; - if (name == NULL) { + if (path == NULL) { errno = EINVAL; return NULL; } - memset(classpath, 0, SYSFS_PATH_MAX); - if ((sysfs_get_mnt_path(classpath, SYSFS_PATH_MAX)) != 0) { - dprintf("Sysfs not supported on this system\n"); - return NULL; - } - - /* - * We shall now treat "block" also as a class. Hence, check here - * if "name" is "block" and proceed accordingly - */ - if (strcmp(name, SYSFS_BLOCK_NAME) == 0) { - strcat(classpath, SYSFS_BLOCK_DIR); - } else { - strcat(classpath, SYSFS_CLASS_DIR); - strcat(classpath, "/"); - strcat(classpath, name); - } - classdir = sysfs_open_directory(classpath); + classdir = sysfs_open_directory(path); if (classdir == NULL) { errno = EINVAL; - dprintf("Class %s not supported on this system\n", name); return NULL; } if ((sysfs_read_directory(classdir)) != 0) { - dprintf("Error reading %s class dir %s\n", name, classpath); + dprintf("Error reading class dir %s\n", path); sysfs_close_directory(classdir); return NULL; } @@ -163,11 +144,10 @@ static void set_classdev_classname(struct sysfs_class_device *cdev) if (c == NULL) strcpy(cdev->classname, SYSFS_UNKNOWN); - else { c++; e = c; - while (e != NULL && *e != '/') { + while (e != NULL && *e != '/' && *e != '\0') { e++; count++; } @@ -183,15 +163,15 @@ static void set_classdev_classname(struct sysfs_class_device *cdev) struct sysfs_class_device *sysfs_open_class_device(const unsigned char *path) { struct sysfs_class_device *cdev = NULL; - struct sysfs_directory *dir = NULL; - struct sysfs_link *curl = NULL; - struct sysfs_device *sdev = NULL; - struct sysfs_driver *drv = NULL; if (path == NULL) { errno = EINVAL; return NULL; } + if ((sysfs_path_is_dir(path)) != 0) { + dprintf("%s is not a valid path to a class device\n", path); + return NULL; + } cdev = alloc_class_device(); if (cdev == NULL) { dprintf("calloc failed\n"); @@ -199,81 +179,39 @@ struct sysfs_class_device *sysfs_open_class_device(const unsigned char *path) } if ((sysfs_get_name_from_path(path, cdev->name, SYSFS_NAME_LEN)) != 0) { errno = EINVAL; - dprintf("Invalid class device path %s\n", path); + dprintf("Error getting class device name\n"); sysfs_close_class_device(cdev); return NULL; } - dir = sysfs_open_directory(path); - if (dir == NULL) { - dprintf("Error opening class device at %s\n", path); - sysfs_close_class_device(cdev); - return NULL; - } - if ((sysfs_read_directory(dir)) != 0) { - dprintf("Error reading class device at %s\n", path); - sysfs_close_directory(dir); - sysfs_close_class_device(cdev); - return NULL; - } - sysfs_read_all_subdirs(dir); - cdev->directory = dir; - strcpy(cdev->path, dir->path); + strcpy(cdev->path, path); set_classdev_classname(cdev); - /* get driver and device, if implemented */ - if (cdev->directory->links != NULL) { - dlist_for_each_data(cdev->directory->links, curl, - struct sysfs_link) { - if (strncmp(curl->name, SYSFS_DEVICES_NAME, 6) == 0) { - sdev = sysfs_open_device(curl->target); - if (sdev != NULL) { - cdev->sysdevice = sdev; - if (cdev->driver != NULL) - strncpy(sdev->driver_name, - cdev->driver->name, - SYSFS_NAME_LEN); - } - } else if (strncmp(curl->name, - SYSFS_DRIVERS_NAME, 6) == 0) { - drv = sysfs_open_bus_driver(curl->target); - if (drv != NULL) { - cdev->driver = drv; - if (cdev->sysdevice != NULL) { - strncpy(cdev->sysdevice->name, - drv->name, - SYSFS_NAME_LEN); - if (drv->devices == NULL) - drv->devices = - dlist_new - (sizeof(struct - sysfs_device)); - dlist_unshift(drv->devices, - cdev->sysdevice); - } - } - } - } - } return cdev; } /** - * get_all_class_devices: gets all devices for class + * sysfs_get_class_devices: gets all devices for class * @class: class to get devices for - * returns 0 with success and -1 with failure + * returns dlist of class_devices with success and NULL with error */ -static int get_all_class_devices(struct sysfs_class *cls) +struct dlist *sysfs_get_class_devices(struct sysfs_class *cls) { struct sysfs_class_device *dev = NULL; struct sysfs_directory *cur = NULL; - if (cls == NULL || cls->directory == NULL) { + if (cls == NULL) { errno = EINVAL; - return -1; + return NULL; } + if (cls->directory == NULL) { + cls->directory = open_class_dir(cls->path); + if (cls->directory == NULL) + return NULL; + } + if (cls->directory->subdirs == NULL) - return 0; + return NULL; dlist_for_each_data(cls->directory->subdirs, cur, struct sysfs_directory) { dev = sysfs_open_class_device(cur->path); @@ -287,7 +225,7 @@ static int get_all_class_devices(struct sysfs_class *cls) sysfs_close_cls_dev); dlist_unshift(cls->devices, dev); } - return 0; + return cls->devices; } /** @@ -297,34 +235,43 @@ static int get_all_class_devices(struct sysfs_class *cls) struct sysfs_class *sysfs_open_class(const unsigned char *name) { struct sysfs_class *cls = NULL; - struct sysfs_directory *classdir = NULL; + unsigned char classpath[SYSFS_PATH_MAX]; if (name == NULL) { errno = EINVAL; return NULL; } + memset(classpath, 0, SYSFS_PATH_MAX); + if ((sysfs_get_mnt_path(classpath, SYSFS_PATH_MAX)) != 0) { + dprintf("Sysfs not supported on this system\n"); + return NULL; + } + + /* + * We shall now treat "block" also as a class. Hence, check here + * if "name" is "block" and proceed accordingly + */ + if (strcmp(name, SYSFS_BLOCK_NAME) == 0) { + strcat(classpath, SYSFS_BLOCK_DIR); + } else { + strcat(classpath, SYSFS_CLASS_DIR); + strcat(classpath, "/"); + strcat(classpath, name); + } + if ((sysfs_path_is_dir(classpath)) != 0) { + dprintf("Class %s not found on the system\n", name); + return NULL; + } + cls = alloc_class(); if (cls == NULL) { dprintf("calloc failed\n"); return NULL; } strcpy(cls->name, name); - classdir = open_class_dir(name); - if (classdir == NULL) { - dprintf("Invalid class, %s not supported on this system\n", - name); - sysfs_close_class(cls); - return NULL; - } - cls->directory = classdir; - strcpy(cls->path, classdir->path); - if ((get_all_class_devices(cls)) != 0) { - dprintf("Error reading %s class devices\n", name); - sysfs_close_class(cls); - return NULL; - } - + strcpy(cls->path, classpath); + return cls; } @@ -336,15 +283,105 @@ struct sysfs_class *sysfs_open_class(const unsigned char *name) struct sysfs_class_device *sysfs_get_class_device(struct sysfs_class *class, unsigned char *name) { + struct dlist *devlist = NULL; + if (class == NULL || name == NULL) { errno = EINVAL; return NULL; } + if (class->devices == NULL) { + class->devices = sysfs_get_class_devices(class); + if (devlist == NULL) + return NULL; + } return (struct sysfs_class_device *)dlist_find_custom(class->devices, name, class_name_equal); } +/** + * sysfs_get_classdev_device: returns the sysfs_device corresponding to + * sysfs_class_device, if present + * @clsdev: class device whose sysfs_device is required + * Returns sysfs_device on success, NULL on error or if device is not + * implemented + */ +struct sysfs_device *sysfs_get_classdev_device + (struct sysfs_class_device *clsdev) +{ + struct sysfs_link *curlink = NULL; + + if (clsdev == NULL) { + errno = EINVAL; + return NULL; + } + + if (clsdev->sysdevice != NULL) + return (clsdev->sysdevice); + + if (clsdev->directory == NULL) { + clsdev->directory = open_class_dir(clsdev->path); + if (clsdev->directory == NULL) + return NULL; + } + if (clsdev->directory->links != NULL) { + dlist_for_each_data(clsdev->directory->links, + curlink, struct sysfs_link) { + if ((strstr(curlink->target, + SYSFS_DEVICES_NAME)) != NULL) { + clsdev->sysdevice = sysfs_open_device + (curlink->target); + if (clsdev->sysdevice == NULL) + return NULL; + if (clsdev->driver != NULL) + strcpy(clsdev->sysdevice->driver_name, + clsdev->driver->name); + } + } + } + return (clsdev->sysdevice); +} + +/** + * sysfs_get_classdev_driver: returns the sysfs_driver corresponding to + * sysfs_class_device, if present + * @clsdev: class device whose sysfs_device is required + * Returns sysfs_driver on success, NULL on error or if driver is not + * implemented + */ +struct sysfs_driver *sysfs_get_classdev_driver + (struct sysfs_class_device *clsdev) +{ + struct sysfs_link *curlink = NULL; + + if (clsdev == NULL) { + errno = EINVAL; + return NULL; + } + + if (clsdev->driver != NULL) + return (clsdev->driver); + + if (clsdev->directory == NULL) { + clsdev->directory = open_class_dir(clsdev->path); + if (clsdev->directory == NULL) + return NULL; + } + if (clsdev->directory->links != NULL) { + dlist_for_each_data(clsdev->directory->links, + curlink, struct sysfs_link) { + if ((strstr(curlink->target, + SYSFS_DRIVERS_NAME)) != NULL) { + clsdev->driver = sysfs_open_driver + (curlink->target); + if (clsdev->driver == NULL) + return NULL; + } + } + } + return (clsdev->driver); +} + /** * get_classdev_path: given the class and a device in the class, return the * absolute path to the device @@ -422,12 +459,24 @@ struct sysfs_class_device *sysfs_open_class_device_by_name */ struct dlist *sysfs_get_classdev_attributes(struct sysfs_class_device *cdev) { - if (cdev == NULL || cdev->directory == NULL) + if (cdev == NULL) return NULL; + if (cdev->directory == NULL) { + /* + * class devices have attributes in subdirs too.. so read + * the directory before reading the attributes + */ + cdev->directory = open_class_dir(cdev->path); + if (cdev->directory == NULL) + return NULL; + } if (cdev->directory->attributes == NULL) { - if ((sysfs_read_dir_attributes(cdev->directory)) != 0) + if ((sysfs_read_dir_attributes(cdev->directory)) != 0) { + dprintf("Error reading attributes for directory %s\n", + cdev->directory->path); return NULL; + } } return (cdev->directory->attributes); } @@ -442,13 +491,20 @@ struct sysfs_attribute *sysfs_get_classdev_attr (struct sysfs_class_device *clsdev, const unsigned char *name) { struct sysfs_attribute *cur = NULL; - - if (clsdev == NULL || clsdev->directory == NULL || name == NULL) { + struct dlist *attrlist = NULL; + + if (clsdev == NULL || name == NULL) { errno = EINVAL; return NULL; } - if (clsdev->directory->attributes == NULL) { - if ((sysfs_read_dir_attributes(clsdev->directory)) != 0) + + if (clsdev->directory == NULL) { + /* + * Class devices can have attributes in their subdirs + * and hence we read_directory here + */ + clsdev->directory = open_class_dir(clsdev->path); + if (clsdev->directory == NULL) return NULL; } cur = sysfs_get_directory_attribute(clsdev->directory, diff --git a/lib/sysfs_device.c b/lib/sysfs_device.c index 01a7fc1..2d1fb9d 100644 --- a/lib/sysfs_device.c +++ b/lib/sysfs_device.c @@ -155,32 +155,32 @@ static struct sysfs_device *alloc_device(void) } /** - * sysfs_get_device_attr: searches dev's attributes by name - * @dev: device to look through - * @name: attribute name to get - * returns sysfs_attribute reference with success or NULL with error. + * open_device_dir: opens up sysfs_directory for specific root dev + * @name: name of root + * returns struct sysfs_directory with success and NULL with error */ -struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev, - const unsigned char *name) +static struct sysfs_directory *open_device_dir(const unsigned char *path) { - struct sysfs_attribute *cur = NULL; + struct sysfs_directory *rdir = NULL; - if (dev == NULL || dev->directory == NULL || name == NULL) { + if (path == 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) - return cur; - return NULL; + rdir = sysfs_open_directory(path); + if (rdir == NULL) { + errno = EINVAL; + dprintf ("Device %s not supported on this system\n", path); + return NULL; + } + if ((sysfs_read_directory(rdir)) != 0) { + dprintf ("Error reading device at dir %s\n", path); + sysfs_close_directory(rdir); + return NULL; + } + + return rdir; } /** @@ -191,40 +191,34 @@ struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev, struct sysfs_device *sysfs_open_device(const unsigned char *path) { struct sysfs_device *dev = NULL; - struct sysfs_directory *sdir = NULL; if (path == NULL) { errno = EINVAL; return NULL; } + if ((sysfs_path_is_dir(path)) != 0) { + dprintf("Incorrect path to device: %s\n", path); + return NULL; + } dev = alloc_device(); if (dev == NULL) { dprintf("Error allocating device at %s\n", path); return NULL; } - sdir = sysfs_open_directory(path); - if (sdir == NULL) { - dprintf("Invalid device at %s\n", path); + if ((sysfs_get_name_from_path(path, dev->bus_id, + SYSFS_NAME_LEN)) != 0) { errno = EINVAL; + dprintf("Error getting device bus_id\n"); sysfs_close_device(dev); return NULL; } - if ((sysfs_read_directory(sdir)) != 0) { - dprintf("Error reading device directory at %s\n", path); - sysfs_close_directory(sdir); - sysfs_close_device(dev); - return NULL; - } - dev->directory = sdir; - strcpy(dev->bus_id, sdir->name); - strcpy(dev->path, sdir->path); - + strcpy(dev->path, path); /* * The "name" attribute no longer exists... return the device's * sysfs representation instead, in the "dev->name" field, which * implies that the dev->name and dev->bus_id contain same data. */ - strncpy(dev->name, sdir->name, SYSFS_NAME_LEN); + strncpy(dev->name, dev->bus_id, SYSFS_NAME_LEN); if (get_device_bus(dev) != 0) strcpy(dev->bus, SYSFS_UNKNOWN); @@ -253,6 +247,11 @@ static struct sysfs_device *sysfs_open_device_tree(const unsigned char *path) dprintf("Error opening root device at %s\n", path); return NULL; } + if (rootdev->directory == NULL) { + rootdev->directory = open_device_dir(rootdev->path); + if (rootdev->directory == NULL) + return NULL; + } if (rootdev->directory->subdirs != NULL) { dlist_for_each_data(rootdev->directory->subdirs, cur, struct sysfs_directory) { @@ -290,60 +289,25 @@ void sysfs_close_root_device(struct sysfs_root_device *root) } /** - * open_root_device_dir: opens up sysfs_directory for specific root dev - * @name: name of root - * returns struct sysfs_directory with success and NULL with error - */ -static struct sysfs_directory *open_root_device_dir(const unsigned char *name) -{ - struct sysfs_directory *rdir = NULL; - unsigned char rootpath[SYSFS_PATH_MAX]; - - if (name == NULL) { - errno = EINVAL; - return NULL; - } - - memset(rootpath, 0, SYSFS_PATH_MAX); - if (sysfs_get_mnt_path(rootpath, SYSFS_PATH_MAX) != 0) { - dprintf ("Sysfs not supported on this system\n"); - return NULL; - } - - strcat(rootpath, SYSFS_DEVICES_DIR); - strcat(rootpath, "/"); - strcat(rootpath, name); - rdir = sysfs_open_directory(rootpath); - if (rdir == NULL) { - errno = EINVAL; - dprintf ("Root device %s not supported on this system\n", - name); - return NULL; - } - if ((sysfs_read_directory(rdir)) != 0) { - dprintf ("Error reading %s root device at dir %s\n", name, - rootpath); - sysfs_close_directory(rdir); - return NULL; - } - - return rdir; -} - -/** - * get_all_root_devices: opens up all the devices under this root device + * sysfs_get_root_devices: opens up all the devices under this root device * @root: root device to open devices for - * returns 0 with success and -1 with error + * returns dlist of devices with success and NULL with error */ -static int get_all_root_devices(struct sysfs_root_device *root) +struct dlist *sysfs_get_root_devices(struct sysfs_root_device *root) { struct sysfs_device *dev = NULL; struct sysfs_directory *cur = NULL; - if (root == NULL || root->directory == NULL) { + if (root == NULL) { errno = EINVAL; - return -1; + return NULL; } + if (root->directory == NULL) { + root->directory = open_device_dir(root->path); + if (root->directory == NULL) + return NULL; + } + if (root->directory->subdirs == NULL) return 0; @@ -361,7 +325,7 @@ static int get_all_root_devices(struct sysfs_root_device *root) dlist_unshift(root->devices, dev); } - return 0; + return root->devices; } /** @@ -373,33 +337,34 @@ static int get_all_root_devices(struct sysfs_root_device *root) struct sysfs_root_device *sysfs_open_root_device(const unsigned char *name) { struct sysfs_root_device *root = NULL; - struct sysfs_directory *rootdir = NULL; + unsigned char rootpath[SYSFS_PATH_MAX]; if (name == NULL) { errno = EINVAL; return NULL; } - root = (struct sysfs_root_device *)calloc - (1, sizeof(struct sysfs_root_device)); - if (root == NULL) { - dprintf("calloc failure\n"); + memset(rootpath, 0, SYSFS_PATH_MAX); + if (sysfs_get_mnt_path(rootpath, SYSFS_PATH_MAX) != 0) { + dprintf ("Sysfs not supported on this system\n"); return NULL; } - rootdir = open_root_device_dir(name); - if (rootdir == NULL) { - dprintf ("Invalid root device, %s not supported\n", name); - sysfs_close_root_device(root); + + strcat(rootpath, SYSFS_DEVICES_DIR); + strcat(rootpath, "/"); + strcat(rootpath, name); + if ((sysfs_path_is_dir(rootpath)) != 0) { + errno = EINVAL; + dprintf("Invalid root device: %s\n", name); return NULL; } - strcpy(root->path, rootdir->path); - root->directory = rootdir; - if (get_all_root_devices(root) != 0) { - dprintf ("Error retrieving devices for root %s\n", name); - sysfs_close_root_device(root); + root = (struct sysfs_root_device *)calloc + (1, sizeof(struct sysfs_root_device)); + if (root == NULL) { + dprintf("calloc failure\n"); return NULL; } - + strcpy(root->path, rootpath); return root; } @@ -410,9 +375,14 @@ struct sysfs_root_device *sysfs_open_root_device(const unsigned char *name) */ struct dlist *sysfs_get_device_attributes(struct sysfs_device *device) { - if (device == NULL || device->directory == NULL) + if (device == NULL) return NULL; + if (device->directory == NULL) { + device->directory = sysfs_open_directory(device->path); + if (device->directory == NULL) + return NULL; + } if (device->directory->attributes == NULL) { if ((sysfs_read_dir_attributes(device->directory)) != 0) return NULL; @@ -420,6 +390,39 @@ struct dlist *sysfs_get_device_attributes(struct sysfs_device *device) return (device->directory->attributes); } +/** + * sysfs_get_device_attr: searches dev's attributes by name + * @dev: device to look through + * @name: attribute name to get + * returns sysfs_attribute reference with success or NULL with error. + */ +struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev, + const unsigned char *name) +{ + struct sysfs_attribute *cur = NULL; + + if (dev == NULL || name == NULL) { + errno = EINVAL; + return NULL; + } + + if (dev->directory == NULL) { + dev->directory = sysfs_open_directory(dev->path); + if (dev->directory == NULL) + return NULL; + } + dev->directory->attributes = sysfs_get_device_attributes(dev); + if (dev->directory->attributes == NULL) + return NULL; + + cur = sysfs_get_directory_attribute(dev->directory, + (unsigned char *)name); + if (cur != NULL) + return cur; + + return NULL; +} + /** * get_device_absolute_path: looks up the bus the device is on, gets * absolute path to the device diff --git a/lib/sysfs_dir.c b/lib/sysfs_dir.c index fabb695..beed52a 100644 --- a/lib/sysfs_dir.c +++ b/lib/sysfs_dir.c @@ -385,6 +385,7 @@ void sysfs_close_directory(struct sysfs_directory *sysdir) if (sysdir->attributes != NULL) dlist_destroy(sysdir->attributes); free(sysdir); + sysdir = NULL; } } diff --git a/lib/sysfs_driver.c b/lib/sysfs_driver.c index 15eb239..2842c0f 100644 --- a/lib/sysfs_driver.c +++ b/lib/sysfs_driver.c @@ -28,26 +28,6 @@ static void sysfs_close_driver_device(void *device) sysfs_close_device((struct sysfs_device *)device); } -/** - * 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_bus_driver(struct sysfs_driver *driver) -{ - if (driver != NULL) { - if (driver->devices != NULL) { - dlist_for_each(driver->devices) - dlist_shift(driver->devices); - free(driver->devices); - driver->devices = NULL; - } - if (driver->directory != NULL) - sysfs_close_directory(driver->directory); - free(driver); - } -} - /** * sysfs_close_driver: closes driver and deletes device lists too * @driver: driver to close @@ -63,6 +43,51 @@ void sysfs_close_driver(struct sysfs_driver *driver) } } +/** + * open_driver_dir: Open the sysfs_directory for this driver + * @driver: Driver whose directory to be opened + * Returns 0 on success and 1 on failure + */ +static int open_driver_dir(struct sysfs_driver *driver) +{ + if (driver == NULL) { + errno = EINVAL; + return 1; + } + if (driver->directory == NULL) { + driver->directory = sysfs_open_directory(driver->path); + if (driver->directory == NULL) { + dprintf("Error opening driver directory at %s\n", + driver->path); + return 1; + } + } + return 0; +} + +/** + * read_driver_dir: Read driver directory's subdirs and links + * @driver: Driver to read + * Returns 0 on success and 1 on failure + */ +static int read_driver_dir(struct sysfs_driver *driver) +{ + if (driver == NULL) { + errno = EINVAL; + return 1; + } + if (driver->directory == NULL) { + if ((open_driver_dir(driver)) == 1) + return 1; + } + if ((sysfs_read_directory(driver->directory)) != 0) { + dprintf("Error reading driver directory at %s\n", + driver->path); + return 1; + } + return 0; +} + /** * alloc_driver: allocates and initializes driver * returns struct sysfs_driver with success and NULL with error. @@ -73,11 +98,11 @@ static struct sysfs_driver *alloc_driver(void) } /** - * sysfs_open_bus_driver: opens and initializes driver structure + * sysfs_open_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_bus_driver(const unsigned char *path) +struct sysfs_driver *sysfs_open_driver(const unsigned char *path) { struct sysfs_driver *driver = NULL; struct sysfs_directory *sdir = NULL; @@ -86,25 +111,22 @@ struct sysfs_driver *sysfs_open_bus_driver(const unsigned char *path) errno = EINVAL; return NULL; } - sdir = sysfs_open_directory(path); - if (sdir == NULL) { - dprintf("Error opening directory %s\n", path); - return NULL; - } - if ((sysfs_read_directory(sdir)) != 0) { - dprintf("Error reading directory %s\n", path); - sysfs_close_directory(sdir); + if ((sysfs_path_is_dir(path)) != 0) { + dprintf("Invalid path to driver: %s\n", path); return NULL; } driver = alloc_driver(); if (driver == NULL) { dprintf("Error allocating driver at %s\n", path); - sysfs_close_directory(sdir); return NULL; } - strcpy(driver->name, sdir->name); - driver->directory = sdir; - strcpy(driver->path, sdir->path); + if ((sysfs_get_name_from_path(path, driver->name, + SYSFS_NAME_LEN)) != 0) { + dprintf("Error getting driver name from path\n"); + free(driver); + return NULL; + } + strcpy(driver->path, path); return driver; } @@ -117,12 +139,20 @@ struct sysfs_driver *sysfs_open_bus_driver(const unsigned char *path) */ struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *driver) { - if (driver == NULL || driver->directory == NULL) + if (driver == NULL) { + errno = EINVAL; return NULL; + } + if (driver->directory == NULL) { + if ((open_driver_dir(driver)) == 1) + return NULL; + } if (driver->directory->attributes == NULL) { - if ((sysfs_read_dir_attributes(driver->directory)) != 0) + if ((sysfs_read_dir_attributes(driver->directory)) != 0) { + dprintf("Error reading driver attributes\n"); return NULL; + } } return(driver->directory->attributes); } @@ -137,21 +167,20 @@ struct sysfs_attribute *sysfs_get_driver_attr(struct sysfs_driver *drv, const unsigned char *name) { struct sysfs_attribute *cur = NULL; + struct dlist *attrlist = NULL; - if (drv == NULL || drv->directory == NULL || name == NULL) { + if (drv == NULL) { errno = EINVAL; return NULL; } - - if (drv->directory->attributes == NULL) { - if ((sysfs_read_dir_attributes(drv->directory)) != 0) - return NULL; + + attrlist = sysfs_get_driver_attributes(drv); + if (attrlist != NULL) { + cur = sysfs_get_directory_attribute(drv->directory, + (unsigned char *)name); + if (cur != NULL) + return cur; } - cur = sysfs_get_directory_attribute(drv->directory, - (unsigned char *)name); - if (cur != NULL) - return cur; - return NULL; } @@ -163,31 +192,43 @@ struct sysfs_attribute *sysfs_get_driver_attr(struct sysfs_driver *drv, */ struct dlist *sysfs_get_driver_links(struct sysfs_driver *driver) { - if (driver == NULL || driver->directory == NULL) + if (driver == NULL) { + errno = EINVAL; return NULL; - + } + if (driver->directory == NULL) { + if ((open_driver_dir(driver)) == 1) + return NULL; + if ((read_driver_dir(driver)) != 0) + return NULL; + } return(driver->directory->links); } - /** - * sysfs_open_driver_devices: open up the list of devices this driver supports + * sysfs_get_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 + * Returns dlist of devices on SUCCESS or NULL with ERROR */ -static int sysfs_open_driver_devices(struct sysfs_driver *driver) +struct dlist *sysfs_get_driver_devices(struct sysfs_driver *driver) { struct sysfs_link *curlink = NULL; struct sysfs_device *device = NULL; if (driver == NULL) { errno = EINVAL; - return -1; + return NULL; } if (driver->devices != NULL) - return 0; - + return (driver->devices); + + if (driver->directory == NULL) { + if ((open_driver_dir(driver)) == 1) + return NULL; + if ((read_driver_dir(driver)) != 0) + return NULL; + } if (driver->directory->links != NULL) { dlist_for_each_data(driver->directory->links, curlink, struct sysfs_link) { @@ -195,7 +236,7 @@ static int sysfs_open_driver_devices(struct sysfs_driver *driver) if (device == NULL) { dprintf("Error opening device at %s\n", curlink->target); - return -1; + return NULL; } strcpy(device->driver_name, driver->name); if (driver->devices == NULL) @@ -205,37 +246,7 @@ static int sysfs_open_driver_devices(struct sysfs_driver *driver) dlist_unshift(driver->devices, device); } } - return 0; -} -/** - * 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 to free up memory - */ -struct sysfs_driver *sysfs_open_driver(const unsigned char *path) -{ - struct sysfs_driver *driver = NULL; - - if (path == NULL) { - errno = EINVAL; - return NULL; - } - - 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) { - if ((sysfs_open_driver_devices(driver)) != 0) { - dprintf("Error reading driver devices\n"); - sysfs_close_driver(driver); - return NULL; - } - } - return driver; + return (driver->devices); } /** @@ -249,6 +260,7 @@ struct sysfs_device *sysfs_get_driver_device(struct sysfs_driver *driver, const unsigned char *name) { struct sysfs_device *device = NULL; + struct dlist *devlist = NULL; if (driver == NULL || name == NULL) { errno = EINVAL; @@ -256,13 +268,10 @@ struct sysfs_device *sysfs_get_driver_device(struct sysfs_driver *driver, } if (driver->devices == NULL) { - if (driver->directory->links == NULL) { + devlist = sysfs_get_driver_devices(driver); + if (devlist == NULL) { + dprintf("Error getting driver devices\n"); return NULL; - } else { - if ((sysfs_open_driver_devices(driver)) != 0) { - dprintf("Error getting driver devices\n"); - return NULL; - } } } dlist_for_each_data(driver->devices, device, struct sysfs_device) { diff --git a/lib/sysfs_utils.c b/lib/sysfs_utils.c index ede4058..7e6b221 100644 --- a/lib/sysfs_utils.c +++ b/lib/sysfs_utils.c @@ -179,7 +179,7 @@ int sysfs_get_link(const unsigned char *path, unsigned char *target, size_t len) * sysfs_del_name: free function for sysfs_open_subsystem_list * @name: memory area to be freed */ -void sysfs_del_name(void *name) +static void sysfs_del_name(void *name) { free(name); } @@ -329,3 +329,25 @@ struct dlist *sysfs_open_bus_devices_list(unsigned char *name) return list; } +/** + * sysfs_path_is_dir: Check if the path supplied points to a directory + * @path: path to validate + * Returns 0 if path points to dir, 1 otherwise + */ +int sysfs_path_is_dir(const unsigned char *path) +{ + struct stat astats; + + if (path == NULL) { + errno = EINVAL; + return 1; + } + if ((lstat(path, &astats)) != 0) { + dprintf("stat() failed\n"); + return 1; + } + if (S_ISDIR(astats.st_mode)) + return 0; + + return 1; +} diff --git a/test/get_class_dev.c b/test/get_class_dev.c index 7d20686..d42732d 100644 --- a/test/get_class_dev.c +++ b/test/get_class_dev.c @@ -35,6 +35,8 @@ int main(int argc, char *argv[]) struct sysfs_class_device *cdev = NULL; struct sysfs_attribute *attr = NULL; struct dlist *attrlist = NULL; + struct sysfs_device *device = NULL; + struct sysfs_driver *driver = NULL; if (argc != 3) { print_usage(); @@ -56,9 +58,11 @@ int main(int argc, char *argv[]) } fprintf(stdout, "\n"); - if (cdev->sysdevice) + device = sysfs_get_classdev_device(cdev); + if (device) fprintf(stdout, "\tDevice : %s\n", cdev->sysdevice->bus_id); - if (cdev->driver) + driver = sysfs_get_classdev_driver(cdev); + if (driver) fprintf(stdout, "\tDriver : %s\n", cdev->driver->name); sysfs_close_class_device(cdev); diff --git a/test/get_driver.c b/test/get_driver.c index 107c9bf..5f2ff93 100644 --- a/test/get_driver.c +++ b/test/get_driver.c @@ -35,6 +35,7 @@ int main(int argc, char *argv[]) char *bus = NULL, path[SYSFS_PATH_MAX]; struct sysfs_driver *driver = NULL; struct sysfs_device *device = NULL; + struct dlist *devlist = NULL; if (argc != 2) { print_usage(); @@ -66,9 +67,10 @@ int main(int argc, char *argv[]) free(bus); return 1; } - if (driver->devices != NULL) { + devlist = sysfs_get_driver_devices(driver); + if (devlist != NULL) { fprintf(stdout, "%s is used by:\n", argv[1]); - dlist_for_each_data(driver->devices, device, struct sysfs_device) + dlist_for_each_data(devlist, device, struct sysfs_device) fprintf(stdout, "\t\t%s\n", device->bus_id); } else fprintf(stdout, "%s is presently not used by any device\n", argv[1]); -- cgit v1.2.1