diff options
author | mohanltc <mohanltc> | 2006-08-07 05:08:00 +0000 |
---|---|---|
committer | mohanltc <mohanltc> | 2006-08-07 05:08:00 +0000 |
commit | 797dafc33c0f121845f9fc4ad11e850a6d005678 (patch) | |
tree | d14350ef788c9ace4c56d6e6e70d8d9f446e81ab | |
parent | ebfc1f970c7393ae6a36ce9d25a748701e224cb3 (diff) | |
download | sysfsutils-797dafc33c0f121845f9fc4ad11e850a6d005678.tar.gz |
Release Candidate for 2.1.0
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | docs/libsysfs.txt | 36 | ||||
-rw-r--r-- | include/dlist.h | 9 | ||||
-rw-r--r-- | include/libsysfs.h | 5 | ||||
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/sysfs_attr.c | 61 | ||||
-rw-r--r-- | lib/sysfs_class.c | 22 | ||||
-rw-r--r-- | lib/sysfs_device.c | 84 | ||||
-rw-r--r-- | lib/sysfs_utils.c | 14 | ||||
-rw-r--r-- | test/test-defs.h | 1 | ||||
-rw-r--r-- | test/test.c | 6 | ||||
-rw-r--r-- | test/test_utils.c | 61 |
13 files changed, 297 insertions, 12 deletions
@@ -1,3 +1,9 @@ +28/06/2006 - Mohan Kumar M <mohan@in.ibm.com> + * Add sysfs_open_device_tree() + +17/04/2006 - Mohan Kumar M <mohan@in.ibm.com> + * Add sysfs_open_link_list() + 12/07/2005 - Mohan Kumar M <mohan@in.ibm.com> * Minor code cleanup in sysfs_class.c to conform to C99 diff --git a/configure.ac b/configure.ac index 2a1fc9e..ed801c0 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ # Process this file with autoconf to produce a configure script. -AC_INIT(sysfsutils, 2.0.0, linux-diag-devel@lists.sourceforge.net) +AC_INIT(sysfsutils, 2.1.0, linux-diag-devel@lists.sourceforge.net) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([config.h.in]) AM_CONFIG_HEADER([config.h]) diff --git a/docs/libsysfs.txt b/docs/libsysfs.txt index c061eb5..c54d0e6 100644 --- a/docs/libsysfs.txt +++ b/docs/libsysfs.txt @@ -466,6 +466,17 @@ Returns: Directory list on success, NULL on error Prototype: struct dlist *sysfs_open_directory_list(const char *path) ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +Name: sysfs_open_link_list + +Description: Utility function to get list of all links under path. + +Arguments: const char *path Path to read + +Returns: Links list on success, NULL on error + +Prototype: struct dlist *sysfs_open_link_list(const char *path) +------------------------------------------------------------------------------- 6.3 Attribute Functions ------------------------ @@ -873,6 +884,31 @@ Arguments: sysfs_device *dev Device structure to close Prototype: void sysfs_close_device(struct sysfs_device *dev) ------------------------------------------------------------------------------- +------------------------------------------------------------------------------- +Name: sysfs_open_device_tree + +Description: Function opens up the device tree at the specified path. + +Arguments: const char *path Path at which to open the device tree + +Returns: struct sysfs_device * with success + NULL with error, Errno will be set with error, returning + - EINVAL for invalid arguments + +Prototype: struct sysfs_device *sysfs_open_device_tree(const char *path) +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +Name: sysfs_close_device_tree + +Description: Function closes the device tree originating at the given + sysfs_device. + +Arguments: struct sysfs_device *devroot Device from which the device + tree has to be closed + +Prototype: void sysfs_close_device_tree(struct sysfs_device *devroot) +------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Name: sysfs_get_device_parent diff --git a/include/dlist.h b/include/dlist.h index 62417af..713e422 100644 --- a/include/dlist.h +++ b/include/dlist.h @@ -70,6 +70,10 @@ typedef struct dlist { DL_node *head; } Dlist; +#ifdef __cplusplus +extern "C" { +#endif + Dlist *dlist_new(size_t datasize); Dlist *dlist_new_with_delete(size_t datasize,void (*del_func)(void*)); void *_dlist_mark_move(Dlist *list,int direction); @@ -206,4 +210,9 @@ void *_dlist_insert_dlnode(struct dlist *list,struct dl_node *new_node,int direc for((iterator)=(list)->head->prev, (data_iterator)=(datatype *) (iterator)->data; \ (iterator)!=(list)->head;(iterator)=(iterator)->prev,(data_iterator)=(datatype *) (iterator)) + +#ifdef __cplusplus +} +#endif + #endif /* _DLIST_H_ */ diff --git a/include/libsysfs.h b/include/libsysfs.h index 3a0cb30..f1e8436 100644 --- a/include/libsysfs.h +++ b/include/libsysfs.h @@ -86,6 +86,7 @@ struct sysfs_device { char bus_id[SYSFS_NAME_LEN]; char bus[SYSFS_NAME_LEN]; char driver_name[SYSFS_NAME_LEN]; + char subsystem[SYSFS_NAME_LEN]; /* Private: for internal use only */ struct sysfs_device *parent; @@ -146,6 +147,7 @@ extern int sysfs_path_is_link(const char *path); extern int sysfs_path_is_file(const char *path); extern int sysfs_get_link(const char *path, char *target, size_t len); extern struct dlist *sysfs_open_directory_list(const char *path); +extern struct dlist *sysfs_open_link_list(const char *path); extern void sysfs_close_list(struct dlist *list); /* sysfs directory and file access */ @@ -154,7 +156,7 @@ extern struct sysfs_attribute *sysfs_open_attribute(const char *path); extern int sysfs_read_attribute(struct sysfs_attribute *sysattr); extern int sysfs_write_attribute(struct sysfs_attribute *sysattr, const char *new_value, size_t len); - +extern struct sysfs_device *sysfs_read_dir_subdirs(const char *path); /* sysfs driver access */ extern void sysfs_close_driver(struct sysfs_driver *driver); extern struct sysfs_driver *sysfs_open_driver @@ -168,6 +170,7 @@ extern struct sysfs_module *sysfs_get_driver_module(struct sysfs_driver *drv); /* generic sysfs device access */ extern void sysfs_close_device_tree(struct sysfs_device *device); +extern struct sysfs_device *sysfs_open_device_tree(const char *path); extern void sysfs_close_device(struct sysfs_device *dev); extern struct sysfs_device *sysfs_open_device (const char *bus, const char *bus_id); diff --git a/lib/Makefile.am b/lib/Makefile.am index e087b77..8d37bcc 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -2,6 +2,6 @@ lib_LTLIBRARIES = libsysfs.la libsysfs_la_SOURCES = sysfs_utils.c sysfs_attr.c sysfs_class.c dlist.c \ sysfs_device.c sysfs_driver.c sysfs_bus.c sysfs_module.c sysfs.h INCLUDES = -I../include -libsysfs_la_LDFLAGS = -version-info 2:0:0 +libsysfs_la_LDFLAGS = -version-info 2:1:0 EXTRA_CFLAGS = @EXTRA_CLFAGS@ libsysfs_la_CFLAGS = -Wall -W -Wstrict-prototypes $(EXTRA_CLFAGS) diff --git a/lib/sysfs_attr.c b/lib/sysfs_attr.c index 91d5e2e..8819926 100644 --- a/lib/sysfs_attr.c +++ b/lib/sysfs_attr.c @@ -424,6 +424,67 @@ struct dlist *read_dir_links(const char *path) return linklist; } +void sysfs_close_dev_tree(void *dev); + +int add_subdirectory(struct sysfs_device *dev, char *path) +{ + struct sysfs_device *newdev; + + if (!path) + return -1; + + newdev = sysfs_open_device_path(path); + if (newdev == NULL) + return -1; + + if (dev->children == NULL) + dev->children = dlist_new_with_delete( + sizeof(struct sysfs_device), sysfs_close_dev_tree); + + dlist_unshift_sorted(dev->children, newdev, sort_list); + return 0; +} + +/** + * read_dir_subdirs: grabs subdirs in a specific directory + * @sysdir: sysfs directory to read + * returns list of directory names with success and NULL with error. + */ +struct sysfs_device *sysfs_read_dir_subdirs(const char *path) +{ + DIR *dir = NULL; + struct dirent *dirent = NULL; + char file_path[SYSFS_PATH_MAX]; + struct sysfs_device *dev = NULL; + + if (!path) { + errno = EINVAL; + return NULL; + } + + dev = sysfs_open_device_path(path); + + dir = opendir(path); + if (!dir) { + dprintf("Error opening directory %s\n", path); + return NULL; + } + while ((dirent = readdir(dir)) != NULL) { + if (0 == strcmp(dirent->d_name, ".")) + continue; + if (0 == strcmp(dirent->d_name, "..")) + continue; + memset(file_path, 0, SYSFS_PATH_MAX); + safestrcpy(file_path, path); + safestrcat(file_path, "/"); + safestrcat(file_path, dirent->d_name); + if (!sysfs_path_is_dir(file_path)) + add_subdirectory(dev, file_path); + } + closedir(dir); + return dev; +} + /** * read_dir_subdirs: grabs subdirs in a specific directory * @sysdir: sysfs directory to read diff --git a/lib/sysfs_class.c b/lib/sysfs_class.c index b675a5e..4fe0b82 100644 --- a/lib/sysfs_class.c +++ b/lib/sysfs_class.c @@ -96,7 +96,8 @@ static struct sysfs_class_device *alloc_class_device(void) */ static void set_classdev_classname(struct sysfs_class_device *cdev) { - char *c, *e, name[SYSFS_NAME_LEN]; + char *c, *e, name[SYSFS_PATH_MAX], link[SYSFS_PATH_MAX]; + struct stat stats; int count = 0; /* @@ -104,7 +105,7 @@ static void set_classdev_classname(struct sysfs_class_device *cdev) * Check if this cdev belongs to the newer style subsystem and * set the classname appropriately. */ - memset(name, 0, SYSFS_NAME_LEN); + memset(name, 0, SYSFS_PATH_MAX); safestrcpy(name, cdev->name); c = strchr(name, ':'); if (c) { @@ -120,9 +121,7 @@ static void set_classdev_classname(struct sysfs_class_device *cdev) else c = strstr(c, "/"); - if (c == NULL) - safestrcpy(cdev->classname, SYSFS_UNKNOWN); - else { + if (c) { if (*c == '/') c++; e = c; @@ -131,6 +130,19 @@ static void set_classdev_classname(struct sysfs_class_device *cdev) count++; } strncpy(cdev->classname, c, count); + } else { + strcpy(link, cdev->path); + strcat(link, "/subsystem"); + sysfs_get_link(link, name, SYSFS_PATH_MAX); + if (lstat(name, &stats)) + safestrcpy(cdev->classname, SYSFS_UNKNOWN); + else { + c = strrchr(name, '/'); + if (c) + safestrcpy(cdev->classname, c+1); + else + safestrcpy(cdev->classname, SYSFS_UNKNOWN); + } } } diff --git a/lib/sysfs_device.c b/lib/sysfs_device.c index eee9178..b783ec5 100644 --- a/lib/sysfs_device.c +++ b/lib/sysfs_device.c @@ -79,6 +79,39 @@ int sysfs_get_device_bus(struct sysfs_device *dev) } /** + * get_dev_subsystem: fills in the dev->subsystem field + * Returns 0 on SUCCESS and -1 on error + */ +static int get_dev_subsystem(struct sysfs_device *dev) +{ + char path[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX]; + + if (!dev) { + errno = EINVAL; + return -1; + } + memset(path, 0, SYSFS_PATH_MAX); + memset(devpath, 0, SYSFS_PATH_MAX); + safestrcpymax(path, dev->path, SYSFS_PATH_MAX); + safestrcatmax(path, "/subsystem", SYSFS_PATH_MAX); + if (!sysfs_path_is_link(path)) { + if (!sysfs_get_link(path, devpath, SYSFS_PATH_MAX)) { + if (!sysfs_get_name_from_path(devpath, + dev->subsystem, SYSFS_NAME_LEN)) + return 0; + } + } + return -1; +} +/** + * sysfs_close_dev_tree: routine for dlist integration + */ +void sysfs_close_dev_tree(void *dev) +{ + sysfs_close_device_tree((struct sysfs_device *)dev); +} + +/** * sysfs_close_device_tree: closes every device in the supplied tree, * closing children only. * @devroot: device root of tree. @@ -93,6 +126,7 @@ void sysfs_close_device_tree(struct sysfs_device *devroot) struct sysfs_device) sysfs_close_device_tree(child); } + devroot->children = NULL; sysfs_close_device(devroot); } } @@ -171,10 +205,60 @@ struct sysfs_device *sysfs_open_device_path(const char *path) dprintf("Could not get device %s's driver\n", dev->bus_id); safestrcpy(dev->driver_name, SYSFS_UNKNOWN); } + + if (get_dev_subsystem(dev)) { + dprintf("Could not get device %s's subsystem\n", dev->bus_id); + safestrcpy(dev->subsystem, SYSFS_UNKNOWN); + } return dev; } /** + * sysfs_open_device_tree: opens root device and all of its children, + * creating a tree of devices. Only opens children. + * @path: sysfs path to devices + * returns struct sysfs_device and its children with success or NULL with + * error. + */ +struct sysfs_device *sysfs_open_device_tree(const char *path) +{ + struct sysfs_device *rootdev = NULL, *new = NULL; + struct sysfs_device *cur = NULL; + struct sysfs_device *devlist; + + if (path == NULL) { + errno = EINVAL; + return NULL; + } + rootdev = sysfs_open_device_path(path); + if (rootdev == NULL) { + dprintf("Error opening root device at %s\n", path); + return NULL; + } + + devlist = sysfs_read_dir_subdirs(path); + if (devlist->children) { + dlist_for_each_data(devlist->children, cur, + struct sysfs_device) { + new = sysfs_open_device_tree(cur->path); + if (new == NULL) { + dprintf("Error opening device tree at %s\n", + cur->path); + sysfs_close_device_tree(rootdev); + return NULL; + } + if (rootdev->children == NULL) + rootdev->children = dlist_new_with_delete + (sizeof(struct sysfs_device), + sysfs_close_dev_tree); + dlist_unshift_sorted(rootdev->children, new, sort_list); + } + } + + return rootdev; +} + +/** * sysfs_get_device_attr: searches dev's attributes by name * @dev: device to look through * @name: attribute name to get diff --git a/lib/sysfs_utils.c b/lib/sysfs_utils.c index 6397342..9ca207c 100644 --- a/lib/sysfs_utils.c +++ b/lib/sysfs_utils.c @@ -224,6 +224,20 @@ struct dlist *sysfs_open_directory_list(const char *path) } /** + * sysfs_open_link_list: gets a list of all links under "path" + * @path: path to read + * Returns a dlist of supported links or NULL no directories (errno is set + * in case of error + */ +struct dlist *sysfs_open_link_list(const char *path) +{ + if (!path) + return NULL; + + return (read_dir_links(path)); +} + +/** * 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 diff --git a/test/test-defs.h b/test/test-defs.h index 5aa9e8d..b22909a 100644 --- a/test/test-defs.h +++ b/test/test-defs.h @@ -75,6 +75,7 @@ extern int test_sysfs_path_is_link(int flag); extern int test_sysfs_path_is_file(int flag); extern int test_sysfs_get_link(int flag); extern int test_sysfs_open_directory_list(int flag); +extern int test_sysfs_open_link_list(int flag); extern int test_sysfs_close_list(int flag); extern int test_sysfs_close_attribute(int flag); extern int test_sysfs_open_attribute(int flag); diff --git a/test/test.c b/test/test.c index 4944afa..2e8f201 100644 --- a/test/test.c +++ b/test/test.c @@ -38,6 +38,7 @@ char *function_name[] = { "sysfs_get_link", "sysfs_close_list", "sysfs_open_directory_list", + "sysfs_open_link_list", "sysfs_close_attribute", "sysfs_open_attribute", "sysfs_read_attribute", @@ -48,13 +49,11 @@ char *function_name[] = { "sysfs_get_driver_attr", "sysfs_get_driver_attributes", "sysfs_get_driver_devices", -// "sysfs_get_driver_module", "sysfs_close_device", "sysfs_open_device", "sysfs_get_device_parent", "sysfs_open_device_path", "sysfs_get_device_attr", -// "sysfs_get_device_bus", "sysfs_get_device_attributes", "sysfs_close_bus", "sysfs_open_bus", @@ -94,6 +93,7 @@ int (*func_table[])(int) = { test_sysfs_get_link, test_sysfs_close_list, test_sysfs_open_directory_list, + test_sysfs_open_link_list, test_sysfs_close_attribute, test_sysfs_open_attribute, test_sysfs_read_attribute, @@ -104,13 +104,11 @@ int (*func_table[])(int) = { test_sysfs_get_driver_attr, test_sysfs_get_driver_attributes, test_sysfs_get_driver_devices, -// test_sysfs_get_driver_module, test_sysfs_close_device, test_sysfs_open_device, test_sysfs_get_device_parent, test_sysfs_open_device_path, test_sysfs_get_device_attr, -// test_sysfs_get_device_bus, test_sysfs_get_device_attributes, test_sysfs_close_bus, test_sysfs_open_bus, diff --git a/test/test_utils.c b/test/test_utils.c index b5213f5..f935140 100644 --- a/test/test_utils.c +++ b/test/test_utils.c @@ -33,6 +33,7 @@ * extern int sysfs_path_is_file(const char *path); * extern int sysfs_get_link(const char *path, char *target, size_t len); * extern struct dlist *sysfs_open_directory_list(char *name); + * extern struct dlist *sysfs_open_link_list(char *name); * extern void sysfs_close_list(struct dlist *list); ***************************************************************************** */ @@ -542,6 +543,66 @@ int test_sysfs_open_directory_list(int flag) } /** + * extern struct dlist *sysfs_open_link_list(char *name); + * + * flag: + * 0: name -> valid + * 1: name -> invalid + * 2: name -> NULL + * + */ +int test_sysfs_open_link_list(int flag) +{ + char *path = NULL; + struct dlist *list = NULL; + + switch (flag) { + case 0: + path = val_link_path; + break; + case 1: + path = inval_path; + break; + case 2: + path = NULL; + break; + default: + return -1; + } + list = sysfs_open_link_list(path); + + switch (flag) { + case 0: + if (list == NULL) + dbg_print("%s: FAILED with flag = %d errno = %d\n", + __FUNCTION__, flag, errno); + else { + dbg_print("%s: SUCCEEDED with flag = %d\n\n", + __FUNCTION__, flag); + show_list(list); + dbg_print("\n"); + } + break; + case 1: + case 2: + if (list != NULL) + dbg_print("%s: FAILED with flag = %d errno = %d\n", + __FUNCTION__, flag, errno); + else + dbg_print("%s: SUCCEEDED with flag = %d\n", + __FUNCTION__, flag); + break; + default: + break; + } + if (list != NULL) { + sysfs_close_list(list); + list = NULL; + } + + return 0; +} +/** * extern void sysfs_close_list(struct dlist *list); * * flag: |