summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormananth <mananth>2003-12-04 06:06:58 +0000
committermananth <mananth>2003-12-04 06:06:58 +0000
commite1660f07958223956f3b4fac6f66eecaa002ab92 (patch)
tree13ff1a96d39d173b9967711e2b1c447c871b3c79
parentb50c94cbad719632bea966b68c566621413019b3 (diff)
downloadsysfsutils-e1660f07958223956f3b4fac6f66eecaa002ab92.tar.gz
This is the complete optimization patch
-rw-r--r--ChangeLog3
-rw-r--r--cmd/lsbus.c62
-rw-r--r--cmd/systool.c111
-rw-r--r--include/libsysfs.h30
-rw-r--r--lib/sysfs_bus.c142
-rw-r--r--lib/sysfs_class.c272
-rw-r--r--lib/sysfs_device.c197
-rw-r--r--lib/sysfs_dir.c1
-rw-r--r--lib/sysfs_driver.c195
-rw-r--r--lib/sysfs_utils.c24
-rw-r--r--test/get_class_dev.c8
-rw-r--r--test/get_driver.c6
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 <ananth@in.ibm.com>
+ * Updated library and utilities with the optimization patch
+
11/24/2003 - Ananth Mavinakayanahalli <ananth@in.ibm.com>
* 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
@@ -259,32 +259,23 @@ 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
@@ -327,38 +327,28 @@ 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,16 +283,106 @@ 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
* @classname: name of the class
@@ -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;
@@ -421,6 +391,39 @@ struct dlist *sysfs_get_device_attributes(struct sysfs_device *device)
}
/**
+ * 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
* @device: device for which path is needed
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
@@ -64,6 +44,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]);