summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormohanltc <mohanltc>2006-08-07 05:08:00 +0000
committermohanltc <mohanltc>2006-08-07 05:08:00 +0000
commit797dafc33c0f121845f9fc4ad11e850a6d005678 (patch)
treed14350ef788c9ace4c56d6e6e70d8d9f446e81ab
parentebfc1f970c7393ae6a36ce9d25a748701e224cb3 (diff)
downloadsysfsutils-797dafc33c0f121845f9fc4ad11e850a6d005678.tar.gz
Release Candidate for 2.1.0
-rw-r--r--ChangeLog6
-rw-r--r--configure.ac2
-rw-r--r--docs/libsysfs.txt36
-rw-r--r--include/dlist.h9
-rw-r--r--include/libsysfs.h5
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/sysfs_attr.c61
-rw-r--r--lib/sysfs_class.c22
-rw-r--r--lib/sysfs_device.c84
-rw-r--r--lib/sysfs_utils.c14
-rw-r--r--test/test-defs.h1
-rw-r--r--test/test.c6
-rw-r--r--test/test_utils.c61
13 files changed, 297 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index e060c1f..fe29abc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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: