summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormananth <mananth>2003-12-10 08:51:02 +0000
committermananth <mananth>2003-12-10 08:51:02 +0000
commitfcaccb01f807270bf8ef8a1b8ca436288148e4db (patch)
treeb268361bbca486d05c6cf0215c6b99ce9173eb51
parent0e8e83bce5c375ca3739462bfd6ac61611492511 (diff)
downloadsysfsutils-fcaccb01f807270bf8ef8a1b8ca436288148e4db.tar.gz
Changes for directory/attribute read optimization
-rw-r--r--ChangeLog3
-rw-r--r--lib/sysfs_bus.c130
-rw-r--r--lib/sysfs_class.c110
-rw-r--r--lib/sysfs_device.c6
-rw-r--r--lib/sysfs_dir.c327
-rw-r--r--lib/sysfs_driver.c6
6 files changed, 363 insertions, 219 deletions
diff --git a/ChangeLog b/ChangeLog
index 7c27d69..7969c4f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,7 @@
+12/08/2003 - Daniel Stekloff <dsteklof@us.ibm.com>
+ * Patched code for directory/attribute read optimization
+
12/05/2003 - Daniel Stekloff <dsteklof@us.ibm.com>
* Remove unused argument from sysfs_get_device_by_id()
diff --git a/lib/sysfs_bus.c b/lib/sysfs_bus.c
index 5ed3904..615407e 100644
--- a/lib/sysfs_bus.c
+++ b/lib/sysfs_bus.c
@@ -93,35 +93,6 @@ 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 *buspath)
-{
- struct sysfs_directory *busdir = NULL;
-
- if (buspath == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- busdir = sysfs_open_directory(buspath);
- if (busdir == NULL) {
- dprintf("Error opening directory at path %s\n", buspath);
- return NULL;
- }
- if ((sysfs_read_directory(busdir)) != 0) {
- dprintf("Error reading bus dir %s\n", buspath);
- sysfs_close_directory(busdir);
- return NULL;
- }
- /* read in devices and drivers subdirs */
- sysfs_read_all_subdirs(busdir);
-
- return busdir;
-}
-
-/**
* sysfs_get_bus_devices: gets all devices for bus
* @bus: bus to get devices for
* returns dlist of devices with success and NULL with failure
@@ -129,42 +100,40 @@ static struct sysfs_directory *open_bus_dir(const unsigned char *buspath)
struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus)
{
struct sysfs_device *bdev = NULL;
- struct sysfs_directory *cur = NULL;
+ struct sysfs_directory *devdir = NULL;
struct sysfs_link *curl = NULL;
+ unsigned char path[SYSFS_PATH_MAX];
if (bus == NULL) {
errno = EINVAL;
return NULL;
}
- if (bus->directory == NULL) {
- bus->directory = open_bus_dir(bus->path);
- if (bus->directory == NULL)
- return NULL;
- }
- if (bus->directory->subdirs == NULL)
+ memset(path, 0, SYSFS_PATH_MAX);
+ strcpy(path, bus->path);
+ strcat(path, "/");
+ strcat(path, SYSFS_DEVICES_NAME);
+ devdir = sysfs_open_directory(path);
+ if (devdir == NULL)
return NULL;
- dlist_for_each_data(bus->directory->subdirs, cur,
- struct sysfs_directory) {
- if (strcmp(cur->name, SYSFS_DEVICES_NAME) != 0)
- continue;
- if (cur->links == NULL)
+ if (sysfs_read_dir_links(devdir) != 0) {
+ sysfs_close_directory(devdir);
+ return NULL;
+ }
+
+ dlist_for_each_data(devdir->links, curl, struct sysfs_link) {
+ bdev = sysfs_open_device(curl->target);
+ if (bdev == NULL) {
+ dprintf("Error opening device at %s\n", curl->target);
continue;
- dlist_for_each_data(cur->links, curl, struct sysfs_link) {
- bdev = sysfs_open_device(curl->target);
- if (bdev == NULL) {
- dprintf("Error opening device at %s\n",
- curl->target);
- continue;
- }
- if (bus->devices == NULL)
- bus->devices = dlist_new_with_delete
- (sizeof(struct sysfs_device),
- sysfs_close_dev);
- dlist_unshift(bus->devices, bdev);
}
+ if (bus->devices == NULL)
+ bus->devices = dlist_new_with_delete
+ (sizeof(struct sysfs_device), sysfs_close_dev);
+ dlist_unshift(bus->devices, bdev);
}
-
+ sysfs_close_directory(devdir);
+
return (bus->devices);
}
@@ -176,42 +145,38 @@ struct dlist *sysfs_get_bus_devices(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 *drvdir = NULL;
struct sysfs_directory *cursub = NULL;
+ unsigned char path[SYSFS_PATH_MAX];
if (bus == NULL) {
errno = EINVAL;
return NULL;
}
- if (bus->directory == NULL) {
- bus->directory = open_bus_dir(bus->path);
- if (bus->directory == NULL)
- return NULL;
- }
- if (bus->directory->subdirs == NULL)
+ memset(path, 0, SYSFS_PATH_MAX);
+ strcpy(path, bus->path);
+ strcat(path, "/");
+ strcat(path, SYSFS_DRIVERS_NAME);
+ drvdir = sysfs_open_directory(path);
+ if (drvdir == NULL)
return NULL;
- dlist_for_each_data(bus->directory->subdirs, cur,
- struct sysfs_directory) {
- if (strcmp(cur->name, SYSFS_DRIVERS_NAME) != 0)
- continue;
- if (cur->subdirs == NULL)
+ if (sysfs_read_dir_subdirs(drvdir) != 0) {
+ sysfs_close_directory(drvdir);
+ return NULL;
+ }
+ dlist_for_each_data(drvdir->subdirs, cursub, struct sysfs_directory) {
+ driver = sysfs_open_driver(cursub->path);
+ if (driver == NULL) {
+ dprintf("Error opening driver at %s\n", cursub->path);
continue;
- dlist_for_each_data(cur->subdirs, cursub,
- struct sysfs_directory) {
- driver = sysfs_open_driver(cursub->path);
- if (driver == NULL) {
- dprintf("Error opening driver at %s\n",
- cursub->path);
- continue;
- }
- if (bus->drivers == NULL)
- bus->drivers = dlist_new_with_delete
- (sizeof(struct sysfs_driver),
- sysfs_close_drv);
- dlist_unshift(bus->drivers, driver);
}
+ if (bus->drivers == NULL)
+ bus->drivers = dlist_new_with_delete
+ (sizeof(struct sysfs_driver), sysfs_close_drv);
+ dlist_unshift(bus->drivers, driver);
}
+ sysfs_close_directory(drvdir);
return (bus->drivers);
}
@@ -378,6 +343,12 @@ struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus)
if (bus->directory->attributes == NULL) {
if ((sysfs_read_dir_attributes(bus->directory)) != 0)
return NULL;
+ } else {
+ if ((sysfs_refresh_attributes
+ (bus->directory->attributes)) != 0) {
+ dprintf("Error refreshing bus attributes\n");
+ return NULL;
+ }
}
return bus->directory->attributes;
}
@@ -496,4 +467,3 @@ int sysfs_find_driver_bus(const unsigned char *driver, unsigned char *busname,
}
return -1;
}
-
diff --git a/lib/sysfs_class.c b/lib/sysfs_class.c
index 6501ac5..5d4da33 100644
--- a/lib/sysfs_class.c
+++ b/lib/sysfs_class.c
@@ -98,33 +98,6 @@ static struct sysfs_class *alloc_class(void)
return (struct sysfs_class *)calloc(1, sizeof(struct sysfs_class));
}
-/**
- * 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 *path)
-{
- struct sysfs_directory *classdir = NULL;
-
- if (path == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- classdir = sysfs_open_directory(path);
- if (classdir == NULL) {
- errno = EINVAL;
- return NULL;
- }
- if ((sysfs_read_directory(classdir)) != 0) {
- dprintf("Error reading class dir %s\n", path);
- sysfs_close_directory(classdir);
- return NULL;
- }
-
- return classdir;
-}
-
/**
* set_classdev_classname: Grabs classname from path
* @cdev: class device to set
@@ -206,13 +179,15 @@ struct dlist *sysfs_get_class_devices(struct sysfs_class *cls)
return NULL;
}
if (cls->directory == NULL) {
- cls->directory = open_class_dir(cls->path);
+ cls->directory = sysfs_open_directory(cls->path);
if (cls->directory == NULL)
return NULL;
}
-
- if (cls->directory->subdirs == NULL)
+
+ if ((sysfs_read_dir_subdirs(cls->directory) != 0)
+ || cls->directory->subdirs == NULL)
return NULL;
+
dlist_for_each_data(cls->directory->subdirs, cur,
struct sysfs_directory) {
dev = sysfs_open_class_device(cur->path);
@@ -323,22 +298,20 @@ struct sysfs_device *sysfs_get_classdev_device
return (clsdev->sysdevice);
if (clsdev->directory == NULL) {
- clsdev->directory = open_class_dir(clsdev->path);
+ clsdev->directory = sysfs_open_directory(clsdev->path);
if (clsdev->directory == NULL)
return NULL;
}
- if (clsdev->directory->links != NULL) {
- devlink = sysfs_get_directory_link(clsdev->directory, "device");
- if (devlink != NULL) {
- clsdev->sysdevice = sysfs_open_device
- (devlink->target);
- if (clsdev->sysdevice == NULL)
- return NULL;
- if (clsdev->driver != NULL)
- strcpy(clsdev->sysdevice->driver_name,
- clsdev->driver->name);
- }
- }
+ devlink = sysfs_get_directory_link(clsdev->directory, "device");
+ if (devlink == NULL)
+ return NULL;
+
+ clsdev->sysdevice = sysfs_open_device(devlink->target);
+ if (clsdev->sysdevice == NULL)
+ return NULL;
+ if (clsdev->driver != NULL)
+ strcpy(clsdev->sysdevice->driver_name, clsdev->driver->name);
+
return (clsdev->sysdevice);
}
@@ -363,19 +336,16 @@ struct sysfs_driver *sysfs_get_classdev_driver
return (clsdev->driver);
if (clsdev->directory == NULL) {
- clsdev->directory = open_class_dir(clsdev->path);
+ clsdev->directory = sysfs_open_directory(clsdev->path);
if (clsdev->directory == NULL)
return NULL;
}
- if (clsdev->directory->links != NULL) {
- drvlink = sysfs_get_directory_link(clsdev->directory, "driver");
- if (drvlink != NULL) {
- clsdev->driver = sysfs_open_driver
- (drvlink->target);
- if (clsdev->driver == NULL)
- return NULL;
+ drvlink = sysfs_get_directory_link(clsdev->directory, "driver");
+ if (drvlink != NULL) {
+ clsdev->driver = sysfs_open_driver(drvlink->target);
+ if (clsdev->driver == NULL)
+ return NULL;
- }
}
return (clsdev->driver);
}
@@ -557,11 +527,7 @@ struct dlist *sysfs_get_classdev_attributes(struct sysfs_class_device *cdev)
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);
+ cdev->directory = sysfs_open_directory(cdev->path);
if (cdev->directory == NULL)
return NULL;
}
@@ -571,6 +537,12 @@ struct dlist *sysfs_get_classdev_attributes(struct sysfs_class_device *cdev)
cdev->directory->path);
return NULL;
}
+ } else {
+ if ((sysfs_refresh_attributes
+ (cdev->directory->attributes)) != 0) {
+ dprintf("Error refreshing classdev attributes\n");
+ return NULL;
+ }
}
return (cdev->directory->attributes);
}
@@ -585,6 +557,7 @@ struct sysfs_attribute *sysfs_get_classdev_attr
(struct sysfs_class_device *clsdev, const unsigned char *name)
{
struct sysfs_attribute *cur = NULL;
+ struct sysfs_directory *sdir = NULL;
struct dlist *attrlist = NULL;
if (clsdev == NULL || name == NULL) {
@@ -593,19 +566,32 @@ struct sysfs_attribute *sysfs_get_classdev_attr
}
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);
+ clsdev->directory = sysfs_open_directory(clsdev->path);
if (clsdev->directory == NULL)
return NULL;
}
+ /*
+ * First, see if it's in the current directory. Then look at
+ * subdirs since class devices can have subdirs of attributes.
+ */
cur = sysfs_get_directory_attribute(clsdev->directory,
(unsigned char *)name);
if (cur != NULL)
return cur;
+ if (clsdev->directory->subdirs == NULL)
+ if ((sysfs_read_dir_subdirs(clsdev->directory)) != 0 ||
+ clsdev->directory->subdirs == NULL)
+ return NULL;
+
+ dlist_for_each_data(clsdev->directory->subdirs, sdir,
+ struct sysfs_directory) {
+ cur = sysfs_get_directory_attribute(sdir,
+ (unsigned char *)name);
+ if (cur != NULL)
+ return cur;
+ }
+
return NULL;
}
diff --git a/lib/sysfs_device.c b/lib/sysfs_device.c
index 91ce150..e5540dd 100644
--- a/lib/sysfs_device.c
+++ b/lib/sysfs_device.c
@@ -377,6 +377,12 @@ struct dlist *sysfs_get_device_attributes(struct sysfs_device *device)
if (device->directory->attributes == NULL) {
if ((sysfs_read_dir_attributes(device->directory)) != 0)
return NULL;
+ } else {
+ if ((sysfs_refresh_attributes
+ (device->directory->attributes)) != 0) {
+ dprintf("Error refreshing device attributes\n");
+ return NULL;
+ }
}
return (device->directory->attributes);
}
diff --git a/lib/sysfs_dir.c b/lib/sysfs_dir.c
index f3c683d..7046d20 100644
--- a/lib/sysfs_dir.c
+++ b/lib/sysfs_dir.c
@@ -187,6 +187,13 @@ int sysfs_write_attribute(struct sysfs_attribute *sysattr,
return -1;
}
if (sysattr->method & SYSFS_METHOD_SHOW) {
+ /*
+ * read attribute again to see if we can get an updated value
+ */
+ if ((sysfs_read_attribute(sysattr)) != 0) {
+ dprintf("Error reading attribute\n");
+ return -1;
+ }
if ((strncmp(sysattr->value, new_value, sysattr->len)) == 0) {
dprintf("Attribute %s already has the requested value %s\n",
sysattr->name, new_value);
@@ -284,6 +291,14 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr)
free(fbuf);
return -1;
}
+ if (sysattr->len > 0) {
+ if ((sysattr->len == length) &&
+ (!(strncmp(sysattr->value, fbuf, length)))) {
+ close(fd);
+ return 0;
+ }
+ free(sysattr->value);
+ }
sysattr->len = length;
close(fd);
vbuf = (unsigned char *)realloc(fbuf, length+1);
@@ -421,8 +436,10 @@ int sysfs_read_all_subdirs(struct sysfs_directory *sysdir)
errno = EINVAL;
return -1;
}
- if (sysdir->subdirs == NULL)
- return 0;
+ if (sysdir->subdirs == NULL)
+ if ((sysfs_read_dir_subdirs(sysdir) != 0)
+ || sysdir->subdirs == NULL)
+ return 0;
dlist_for_each_data(sysdir->subdirs, cursub, struct sysfs_directory) {
if ((sysfs_read_directory(cursub)) != 0)
dprintf ("Error reading subdirectory %s\n",
@@ -491,6 +508,108 @@ struct sysfs_link *sysfs_open_link(const unsigned char *linkpath)
}
/**
+ * sysfs_refresh_attributes: Refresh attributes list
+ * @attrlist: list of attributes to refresh
+ * Returns 0 on success, 1 on failure
+ */
+int sysfs_refresh_attributes(struct dlist *attrlist)
+{
+ struct sysfs_attribute *attr = NULL;
+
+ if (attrlist == NULL) {
+ errno = EINVAL;
+ return 1;
+ }
+ dlist_for_each_data(attrlist, attr, struct sysfs_attribute) {
+ if (attr->method & SYSFS_METHOD_SHOW) {
+ if ((sysfs_read_attribute(attr)) != 0) {
+ dprintf("Error reading attribute %s\n", path);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * add_attribute: open and add attribute at path to given directory
+ * @sysdir: directory to add attribute to
+ * @path: path to attribute
+ * returns 0 with success and -1 with error.
+ */
+static int add_attribute(struct sysfs_directory *sysdir,
+ const unsigned char *path)
+{
+ struct sysfs_attribute *attr = NULL;
+
+ attr = sysfs_open_attribute(path);
+ if (attr == NULL) {
+ dprintf("Error opening attribute %s\n", path);
+ return -1;
+ }
+ if (attr->method & SYSFS_METHOD_SHOW) {
+ if ((sysfs_read_attribute(attr)) != 0) {
+ dprintf("Error reading attribute %s\n", path);
+ sysfs_close_attribute(attr);
+ return 0;
+ }
+ }
+
+ if (sysdir->attributes == NULL) {
+ sysdir->attributes = dlist_new_with_delete
+ (sizeof(struct sysfs_attribute), sysfs_del_attribute);
+ }
+ dlist_unshift(sysdir->attributes, attr);
+
+ return 0;
+}
+
+/**
+ * add_subdirectory: open and add subdirectory at path to given directory
+ * @sysdir: directory to add subdir to
+ * @path: path to subdirectory
+ * returns 0 with success and -1 with error.
+ */
+static int add_subdirectory(struct sysfs_directory *sysdir,
+ const unsigned char *path)
+{
+ struct sysfs_directory *subdir = NULL;
+
+ subdir = sysfs_open_directory(path);
+ if (subdir == NULL) {
+ dprintf("Error opening directory %s\n", path);
+ return -1;
+ }
+ if (sysdir->subdirs == NULL)
+ sysdir->subdirs = dlist_new_with_delete
+ (sizeof(struct sysfs_directory), sysfs_del_directory);
+ dlist_unshift(sysdir->subdirs, subdir);
+ return 0;
+}
+
+/**
+ * add_link: open and add link at path to given directory
+ * @sysdir: directory to add link to
+ * @path: path to link
+ * returns 0 with success and -1 with error.
+ */
+static int add_link(struct sysfs_directory *sysdir, const unsigned char *path)
+{
+ struct sysfs_link *ln = NULL;
+
+ ln = sysfs_open_link(path);
+ if (ln == NULL) {
+ dprintf("Error opening link %s\n", path);
+ return -1;
+ }
+ if (sysdir->links == NULL)
+ sysdir->links = dlist_new_with_delete
+ (sizeof(struct sysfs_link), sysfs_del_link);
+ dlist_unshift(sysdir->links, ln);
+ return 0;
+}
+
+/**
* sysfs_read_dir_attributes: grabs attributes for the given directory
* @sysdir: sysfs directory to open
* returns 0 with success and -1 with error.
@@ -500,7 +619,6 @@ int sysfs_read_dir_attributes(struct sysfs_directory *sysdir)
DIR *dir = NULL;
struct dirent *dirent = NULL;
struct stat astats;
- struct sysfs_attribute *attr = NULL;
unsigned char file_path[SYSFS_PATH_MAX];
int retval = 0;
@@ -526,29 +644,52 @@ int sysfs_read_dir_attributes(struct sysfs_directory *sysdir)
dprintf("stat failed\n");
continue;
}
- if (S_ISREG(astats.st_mode)) {
- attr = sysfs_open_attribute(file_path);
- if (attr == NULL) {
- dprintf("Error opening attribute %s\n",
- file_path);
- retval = -1;
+ if (S_ISREG(astats.st_mode))
+ retval = add_attribute(sysdir, file_path);
+ }
+ closedir(dir);
+ return(retval);
+}
+
+/**
+ * sysfs_read_dir_links: grabs links in a specific directory
+ * @sysdir: sysfs directory to read links
+ * returns 0 with success and -1 with error.
+ */
+int sysfs_read_dir_links(struct sysfs_directory *sysdir)
+{
+ DIR *dir = NULL;
+ struct dirent *dirent = NULL;
+ struct stat astats;
+ unsigned char file_path[SYSFS_PATH_MAX];
+ int retval = 0;
+
+ if (sysdir == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ dir = opendir(sysdir->path);
+ if (dir == NULL) {
+ dprintf("Error opening directory %s\n", sysdir->path);
+ return -1;
+ }
+ while(((dirent = readdir(dir)) != NULL) && retval == 0) {
+ if (0 == strcmp(dirent->d_name, "."))
+ continue;
+ if (0 == strcmp(dirent->d_name, ".."))
+ continue;
+ memset(file_path, 0, SYSFS_PATH_MAX);
+ strncpy(file_path, sysdir->path, sizeof(file_path));
+ strncat(file_path, "/", sizeof(file_path));
+ strncat(file_path, dirent->d_name, sizeof(file_path));
+ if ((lstat(file_path, &astats)) != 0) {
+ dprintf("stat failed\n");
+ continue;
+ }
+ if (S_ISLNK(astats.st_mode)) {
+ retval = add_link(sysdir, file_path);
+ if (retval != 0)
break;
- }
- if (attr->method & SYSFS_METHOD_SHOW) {
- if ((sysfs_read_attribute(attr)) != 0) {
- dprintf("Error reading attribute %s\n",
- file_path);
- sysfs_close_attribute(attr);
- continue;
- }
- }
-
- if (sysdir->attributes == NULL) {
- sysdir->attributes = dlist_new_with_delete
- (sizeof(struct sysfs_attribute),
- sysfs_del_attribute);
- }
- dlist_unshift(sysdir->attributes, attr);
}
}
closedir(dir);
@@ -556,6 +697,48 @@ int sysfs_read_dir_attributes(struct sysfs_directory *sysdir)
}
/**
+ * sysfs_read_dir_subdirs: grabs subdirs in a specific directory
+ * @sysdir: sysfs directory to read links
+ * returns 0 with success and -1 with error.
+ */
+int sysfs_read_dir_subdirs(struct sysfs_directory *sysdir)
+{
+ DIR *dir = NULL;
+ struct dirent *dirent = NULL;
+ struct stat astats;
+ unsigned char file_path[SYSFS_PATH_MAX];
+ int retval = 0;
+
+ if (sysdir == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ dir = opendir(sysdir->path);
+ if (dir == NULL) {
+ dprintf("Error opening directory %s\n", sysdir->path);
+ return -1;
+ }
+ while(((dirent = readdir(dir)) != NULL) && retval == 0) {
+ if (0 == strcmp(dirent->d_name, "."))
+ continue;
+ if (0 == strcmp(dirent->d_name, ".."))
+ continue;
+ memset(file_path, 0, SYSFS_PATH_MAX);
+ strncpy(file_path, sysdir->path, sizeof(file_path));
+ strncat(file_path, "/", sizeof(file_path));
+ strncat(file_path, dirent->d_name, sizeof(file_path));
+ if ((lstat(file_path, &astats)) != 0) {
+ dprintf("stat failed\n");
+ continue;
+ }
+ if (S_ISDIR(astats.st_mode))
+ retval = add_subdirectory(sysdir, file_path);
+ }
+ closedir(dir);
+ return(retval);
+}
+
+/**
* sysfs_read_directory: grabs attributes, links, and subdirectories
* @sysdir: sysfs directory to open
* returns 0 with success and -1 with error.
@@ -565,8 +748,6 @@ int sysfs_read_directory(struct sysfs_directory *sysdir)
DIR *dir = NULL;
struct dirent *dirent = NULL;
struct stat astats;
- struct sysfs_attribute *attr = NULL;
- struct sysfs_directory *subdir = NULL;
struct sysfs_link *ln = NULL;
unsigned char file_path[SYSFS_PATH_MAX];
int retval = 0;
@@ -593,39 +774,22 @@ int sysfs_read_directory(struct sysfs_directory *sysdir)
dprintf("stat failed\n");
continue;
}
- if (S_ISDIR(astats.st_mode)) {
- subdir = sysfs_open_directory(file_path);
- if (subdir == NULL) {
- dprintf("Error opening directory %s\n",
- file_path);
- retval = -1;
- break;
- }
- if (sysdir->subdirs == NULL)
- sysdir->subdirs = dlist_new_with_delete
- (sizeof(struct sysfs_directory),
- sysfs_del_directory);
- dlist_unshift(sysdir->subdirs, subdir);
- } else if (S_ISLNK(astats.st_mode)) {
- ln = sysfs_open_link(file_path);
- if (ln == NULL) {
- dprintf("Error opening link %s\n", file_path);
- retval = -1;
- break;
- }
- if (sysdir->links == NULL)
- sysdir->links = dlist_new_with_delete
- (sizeof(struct sysfs_link),
- sysfs_del_link);
- dlist_unshift(sysdir->links, ln);
- }
+ if (S_ISDIR(astats.st_mode))
+ retval = add_subdirectory(sysdir, file_path);
+
+ else if (S_ISLNK(astats.st_mode))
+ retval = add_link(sysdir, file_path);
+
+ else if (S_ISREG(astats.st_mode))
+ retval = add_attribute(sysdir, file_path);
}
closedir(dir);
return(retval);
}
/**
- * sysfs_get_directory_attribute: retrieves attribute attrname
+ * sysfs_get_directory_attribute: retrieves attribute attrname from current
+ * directory only
* @dir: directory to retrieve attribute from
* @attrname: name of attribute to look for
* returns sysfs_attribute if found and NULL if not found
@@ -633,7 +797,6 @@ int sysfs_read_directory(struct sysfs_directory *sysdir)
struct sysfs_attribute *sysfs_get_directory_attribute
(struct sysfs_directory *dir, unsigned char *attrname)
{
- struct sysfs_directory *sdir = NULL;
struct sysfs_attribute *attr = NULL;
if (dir == NULL || attrname == NULL) {
@@ -641,24 +804,22 @@ struct sysfs_attribute *sysfs_get_directory_attribute
return NULL;
}
- if (dir->attributes == NULL) {
- if ((sysfs_read_dir_attributes(dir)) != 0)
+ if (dir->attributes == NULL)
+ if ((sysfs_read_dir_attributes(dir) != 0)
+ || (dir->attributes == NULL))
return NULL;
- }
attr = (struct sysfs_attribute *)dlist_find_custom
- (dir->attributes, attrname, dir_attribute_name_equal);
- if (attr != NULL)
- return attr;
-
- if (dir->subdirs != NULL) {
- dlist_for_each_data(dir->subdirs, sdir,
- struct sysfs_directory) {
- attr = sysfs_get_directory_attribute(sdir, attrname);
- if (attr != NULL)
- return attr;
- }
+ (dir->attributes, attrname, dir_attribute_name_equal);
+ if (attr != NULL) {
+ if ((sysfs_read_attribute(attr)) != 0) {
+ dprintf("Attribute at %s no longer exists?\n",
+ attr->path);
+ return NULL;
+ } else
+ return attr;
}
+
return NULL;
}
@@ -675,6 +836,10 @@ struct sysfs_link *sysfs_get_directory_link
errno = EINVAL;
return NULL;
}
+ if (dir->links == NULL)
+ if ((sysfs_read_dir_links(dir) != 0) || (dir->links == NULL))
+ return NULL;
+
return (struct sysfs_link *)dlist_find_custom(dir->links,
linkname, dir_link_name_equal);
}
@@ -690,10 +855,15 @@ struct sysfs_directory *sysfs_get_subdirectory(struct sysfs_directory *dir,
{
struct sysfs_directory *sub = NULL, *cursub = NULL;
- if (dir == NULL || dir->subdirs == NULL || subname == NULL) {
+ if (dir == NULL || subname == NULL) {
errno = EINVAL;
return NULL;
}
+
+ if (dir->subdirs == NULL)
+ if (sysfs_read_dir_subdirs(dir) != 0)
+ return NULL;
+
sub = (struct sysfs_directory *)dlist_find_custom(dir->subdirs,
subname, dir_subdir_name_equal);
if (sub != NULL)
@@ -702,8 +872,12 @@ struct sysfs_directory *sysfs_get_subdirectory(struct sysfs_directory *dir,
if (dir->subdirs != NULL) {
dlist_for_each_data(dir->subdirs, cursub,
struct sysfs_directory) {
- if (cursub->subdirs == NULL)
- continue;
+ if (cursub->subdirs == NULL) {
+ if (sysfs_read_dir_subdirs(cursub) != 0)
+ continue;
+ if (cursub->subdirs == NULL)
+ continue;
+ }
sub = sysfs_get_subdirectory(cursub, subname);
if (sub != NULL)
return sub;
@@ -724,7 +898,7 @@ struct sysfs_link *sysfs_get_subdirectory_link(struct sysfs_directory *dir,
struct sysfs_directory *cursub = NULL;
struct sysfs_link *ln = NULL;
- if (dir == NULL || dir->links == NULL || linkname == NULL) {
+ if (dir == NULL || linkname == NULL) {
errno = EINVAL;
return NULL;
}
@@ -733,14 +907,13 @@ struct sysfs_link *sysfs_get_subdirectory_link(struct sysfs_directory *dir,
if (ln != NULL)
return ln;
- if (dir->subdirs == NULL)
- return NULL;
+ if (dir->subdirs == NULL)
+ if (sysfs_read_dir_subdirs(dir) != 0)
+ return NULL;
if (dir->subdirs != NULL) {
dlist_for_each_data(dir->subdirs, cursub,
struct sysfs_directory) {
- if (cursub->subdirs == NULL)
- continue;
ln = sysfs_get_subdirectory_link(cursub, linkname);
if (ln != NULL)
return ln;
diff --git a/lib/sysfs_driver.c b/lib/sysfs_driver.c
index 6857b6f..b243fc7 100644
--- a/lib/sysfs_driver.c
+++ b/lib/sysfs_driver.c
@@ -153,6 +153,12 @@ struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *driver)
dprintf("Error reading driver attributes\n");
return NULL;
}
+ } else {
+ if ((sysfs_refresh_attributes
+ (driver->directory->attributes)) != 0) {
+ dprintf("Error refreshing driver attributes\n");
+ return NULL;
+ }
}
return(driver->directory->attributes);
}