diff options
author | mananth <mananth> | 2003-08-29 10:22:34 +0000 |
---|---|---|
committer | mananth <mananth> | 2003-08-29 10:22:34 +0000 |
commit | d842e8ef5b56187ff4fc4dcec5269fe137c8fc74 (patch) | |
tree | 995919c525e92d012bd8859d92613450f95a22bc | |
parent | 20585df476dda252c5c31f80b977c41461a8a4b4 (diff) | |
download | sysfsutils-d842e8ef5b56187ff4fc4dcec5269fe137c8fc74.tar.gz |
Integrated Eric J Bohm's dlist stuff
Modified library to use dlists
Added few "find" functions
-rw-r--r-- | CREDITS | 3 | ||||
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | cmd/lsbus.c | 100 | ||||
-rw-r--r-- | cmd/systool.c | 144 | ||||
-rwxr-xr-x | configure | 3 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | include/dlist.h | 195 | ||||
-rw-r--r-- | include/libsysfs.h | 136 | ||||
-rw-r--r-- | lib/Makefile.am | 2 | ||||
-rw-r--r-- | lib/Makefile.in | 7 | ||||
-rw-r--r-- | lib/dlist.c | 343 | ||||
-rw-r--r-- | lib/sysfs_bus.c | 353 | ||||
-rw-r--r-- | lib/sysfs_class.c | 94 | ||||
-rw-r--r-- | lib/sysfs_device.c | 82 | ||||
-rw-r--r-- | lib/sysfs_dir.c | 350 | ||||
-rw-r--r-- | lib/sysfs_driver.c | 12 | ||||
-rw-r--r-- | lib/sysfs_utils.c | 19 | ||||
-rw-r--r-- | test/Makefile.am | 4 | ||||
-rw-r--r-- | test/Makefile.in | 316 | ||||
-rw-r--r-- | test/dlist_test.c | 273 |
22 files changed, 1947 insertions, 505 deletions
@@ -6,3 +6,6 @@ have made contributions: - Supplied libsysfs code cleanup including code simplification, read-only strings, and C++ compatibility. + o Eric J Bohm <bohm@gate.csgeeks.org>: + - Supplied dlist generic linked list implementation. + - Added dlist_for_each* functionality. @@ -1,4 +1,13 @@ +08/19/2003 - Daniel Stekloff <dsteklof@us.ibm.com> + * Integrated Eric Bohm's dlist patch + * Integrated Eric Bohm's follow on patch adding dlist_for_each + * Changed chars to unsigned chars + * Reworked structures to be neater and to contain + sysfs_directories as private structures + * Added more functions for retrieving data like attributes + * Added some find functions + 08/06/2003 - Ananth Mavinakayanahalli <ananth@in.ibm.com> * Patch to correct dprintf usage diff --git a/Makefile.am b/Makefile.am index 9ccb34f..ead8a23 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ EXTRA_DIST = docs include -SUBDIRS = lib cmd +SUBDIRS = lib cmd test dist-hook: rm -rf `find $(distdir)/docs -name CVS` diff --git a/Makefile.in b/Makefile.in index 48b8a7b..27391fd 100644 --- a/Makefile.in +++ b/Makefile.in @@ -76,7 +76,7 @@ am__include = @am__include@ am__quote = @am__quote@ install_sh = @install_sh@ EXTRA_DIST = docs include -SUBDIRS = lib cmd +SUBDIRS = lib cmd test subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs diff --git a/cmd/lsbus.c b/cmd/lsbus.c index c709e31..2a98150 100644 --- a/cmd/lsbus.c +++ b/cmd/lsbus.c @@ -34,8 +34,8 @@ /* Command Options */ static int show_options = 0; /* bitmask of show options */ -static char *attr_to_show = NULL; /* print value for this attribute */ -static char *bus_device = NULL; /* print only this bus device */ +static unsigned char *attr_to_show = NULL; /* print value for this attribute*/ +static unsigned char *bus_device = NULL; /* print only this bus device */ #define SHOW_ATTRIBUTES 0x01 /* show attributes command option */ #define SHOW_ATTRIBUTE_VALUE 0x02 /* show an attribute value option */ @@ -45,13 +45,13 @@ static char *bus_device = NULL; /* print only this bus device */ #define SHOW_ALL 0xff -static char cmd_options[] = "aA:dDhv"; +static unsigned char cmd_options[] = "aA:dDhv"; /* * binary_files - defines existing sysfs binary files that should be printed * in hex. */ -static char *binary_files[] = { +static unsigned char *binary_files[] = { "config", "data" }; @@ -76,9 +76,9 @@ void usage(void) * remove_end_newline: removes newline on the end of an attribute value * @value: string to remove newline from */ -void remove_end_newline(char *value) +void remove_end_newline(unsigned char *value) { - char *p = value + (strlen(value) - 1); + unsigned char *p = value + (strlen(value) - 1); if (p != NULL && *p == '\n') *p = '\0'; @@ -93,24 +93,19 @@ void print_device_children(struct sysfs_directory *sdir) if (sdir != NULL) { fprintf(stdout, "\tChildren:\n"); if (sdir->subdirs != NULL) { - char dirname[SYSFS_NAME_LEN]; - struct sysfs_directory *cur = sdir->subdirs; - - while (cur != NULL) { - if ((sysfs_get_name_from_path(cur->path, - dirname, SYSFS_NAME_LEN)) == 0) - fprintf(stdout, "\t\t%s\n", dirname); - else - fprintf(stdout, "\t\t%s\n", cur->path); - cur = cur->next; + struct sysfs_directory *cur; + + dlist_for_each_data(sdir->subdirs, cur, + struct sysfs_directory) { + fprintf(stdout, "\t\t%s\n", cur->name); } } if (sdir->links != NULL) { - struct sysfs_link *curl = sdir->links; - - while(curl != NULL) { + struct sysfs_link *curl = NULL; + + dlist_for_each_data(sdir->links, curl, + struct sysfs_link) { fprintf(stdout, "\t\t%s\n", curl->name); - curl = curl->next; } } } @@ -123,17 +118,13 @@ void print_device_children(struct sysfs_directory *sdir) */ int isbinaryvalue(struct sysfs_attribute *attr) { - char attrname[SYSFS_NAME_LEN]; int i; if (attr == NULL || attr->value == NULL) return 0; - if ((sysfs_get_name_from_path(attr->path, attrname, SYSFS_NAME_LEN)) - != 0) - return 0; for (i = 0; i < binfiles; i++) - if ((strcmp(attrname, binary_files[i])) == 0) + if ((strcmp(attr->name, binary_files[i])) == 0) return 1; return 0; @@ -178,25 +169,19 @@ void print_attribute_value(struct sysfs_attribute *attr) */ void print_attribute(struct sysfs_attribute *attr) { - char attrname[SYSFS_NAME_LEN]; - if (attr == NULL) return; - if ((sysfs_get_name_from_path(attr->path, attrname, SYSFS_NAME_LEN)) - != 0) - return; - if (show_options & SHOW_ALL_ATTRIB_VALUES) { - fprintf(stdout, "\t\t%s", attrname); + fprintf(stdout, "\t\t%s", attr->name); print_attribute_value(attr); } else if ((show_options & SHOW_ATTRIBUTES) || ((show_options - & SHOW_ATTRIBUTE_VALUE) && (strcmp(attrname, attr_to_show) + & SHOW_ATTRIBUTE_VALUE) && (strcmp(attr->name, attr_to_show) == 0))) { - fprintf (stdout, "\t\t%s", attrname); + fprintf (stdout, "\t\t%s", attr->name); if (show_options & SHOW_ATTRIBUTE_VALUE && attr->value != NULL - && (strcmp(attrname, attr_to_show)) == 0) { + && (strcmp(attr->name, attr_to_show)) == 0) { print_attribute_value(attr); } else { fprintf(stdout, "\n"); @@ -211,12 +196,12 @@ void print_attribute(struct sysfs_attribute *attr) void print_device_attributes(struct sysfs_directory *sdir) { if (sdir != NULL && sdir->attributes != NULL) { - struct sysfs_attribute *cur = sdir->attributes; + struct sysfs_attribute *cur = NULL;; fprintf (stdout, "\tAttributes:\n"); - while (cur != NULL) { + dlist_for_each_data(sdir->attributes, cur, + struct sysfs_attribute) { print_attribute(cur); - cur = cur->next; } } } @@ -252,12 +237,12 @@ void print_driver_attributes(struct sysfs_driver *driver) struct sysfs_directory *sdir = driver->directory; if (sdir->attributes != NULL) { - struct sysfs_attribute *cur = sdir->attributes; + struct sysfs_attribute *cur = NULL; fprintf (stdout, "\t%s Attributes:\n", driver->name); - while (cur != NULL) { + dlist_for_each_data(sdir->attributes, cur, + struct sysfs_attribute) { print_attribute(cur); - cur = cur->next; } } } @@ -273,12 +258,12 @@ void print_driver_devices(struct sysfs_driver *driver) struct sysfs_directory *sdir = driver->directory; if (sdir->links != NULL) { - struct sysfs_link *cur = sdir->links; + struct sysfs_link *cur = NULL; fprintf (stdout, "\tDevices:\n"); - while (cur != NULL) { + dlist_for_each_data(sdir->links, cur, + struct sysfs_link) { fprintf(stdout, "\t\t%s\n", cur->name); - cur = cur->next; } } } @@ -311,7 +296,7 @@ void print_driver(struct sysfs_driver *driver) * @busname: bus to print. * returns 0 with success or 1 with error. */ -int print_sysfs_bus(char *busname) +int print_sysfs_bus(unsigned char *busname) { struct sysfs_bus *bus = NULL; struct sysfs_device *curdev = NULL; @@ -329,22 +314,19 @@ int print_sysfs_bus(char *busname) fprintf(stdout, "Bus: %s\n", busname); if (bus->devices != NULL && (show_options & SHOW_DEVICES)) { - curdev = bus->devices; if (bus_device == NULL) fprintf(stdout, "Devices:\n"); - while (curdev != NULL) { + dlist_for_each_data(bus->devices, curdev, + struct sysfs_device) { if (bus_device == NULL || (strcmp(bus_device, curdev->bus_id) == 0)) print_device(curdev); - curdev = curdev->next; } } if (bus->drivers != NULL && (show_options & SHOW_DRIVERS)) { - curdrv = bus->drivers; fprintf(stdout, "Drivers:\n"); - while (curdrv != NULL) { + dlist_for_each_data(bus->drivers, curdrv, struct sysfs_driver) { print_driver(curdrv); - curdrv = curdrv->next; } } sysfs_close_bus(bus); @@ -359,8 +341,7 @@ int print_sysfs_bus(char *busname) int print_sysfs_buses(void) { struct sysfs_directory *busdir = NULL, *current = NULL; - char busname[SYSFS_NAME_LEN]; - char buspath[SYSFS_PATH_MAX]; + unsigned char buspath[SYSFS_PATH_MAX]; int ret = 0; /* get sysfs mount point */ @@ -384,15 +365,8 @@ int print_sysfs_buses(void) } fprintf(stdout, "Supported sysfs buses:\n"); - current = busdir->subdirs; - while (current != NULL) { - if ((sysfs_get_name_from_path(current->path, busname, - SYSFS_NAME_LEN)) != 0) { - sysfs_close_directory(busdir); - return 1; - } - fprintf(stdout, "\t%s\n", busname); - current = current->next; + dlist_for_each_data(busdir->subdirs, current, struct sysfs_directory) { + fprintf(stdout, "\t%s\n", current->name); } sysfs_close_directory(busdir); return ret; @@ -401,7 +375,7 @@ int print_sysfs_buses(void) /* MAIN */ int main(int argc, char *argv[]) { - char *bus_to_print = NULL; + unsigned char *bus_to_print = NULL; int retval = 0; int opt; extern int optind; diff --git a/cmd/systool.c b/cmd/systool.c index 6b9f41d..1f22373 100644 --- a/cmd/systool.c +++ b/cmd/systool.c @@ -34,8 +34,8 @@ /* Command Options */ static int show_options = 0; /* bitmask of show options */ -static char *attribute_to_show = NULL; /* show value for this attribute */ -static char *device_to_show = NULL; /* show only this bus device */ +static unsigned char *attribute_to_show = NULL; /* show value for this attribute */ +static unsigned char *device_to_show = NULL; /* show only this bus device */ #define SHOW_ATTRIBUTES 0x01 /* show attributes command option */ #define SHOW_ATTRIBUTE_VALUE 0x02 /* show an attribute value option */ @@ -45,13 +45,13 @@ static char *device_to_show = NULL; /* show only this bus device */ #define SHOW_ALL 0xff -static char cmd_options[] = "aA:b:c:dDhr:v"; +static unsigned char cmd_options[] = "aA:b:c:dDhr:v"; /* * binary_files - defines existing sysfs binary files. These files will be * printed in hex. */ -static char *binary_files[] = { +static unsigned char *binary_files[] = { "config", "data" }; @@ -93,9 +93,9 @@ void indent(int level) * remove_end_newline: removes newline on the end of an attribute value * @value: string to remove newline from */ -void remove_end_newline(char *value) +void remove_end_newline(unsigned char *value) { - char *p = value + (strlen(value) - 1); + unsigned char *p = value + (strlen(value) - 1); if (p != NULL && *p == '\n') *p = '\0'; @@ -111,26 +111,21 @@ void show_device_children(struct sysfs_directory *sdir, int level) indent(level); fprintf(stdout, "Children:\n"); if (sdir->subdirs != NULL) { - char dirname[SYSFS_NAME_LEN]; - struct sysfs_directory *cur = sdir->subdirs; - - while (cur != NULL) { + struct sysfs_directory *cur; + + dlist_for_each_data(sdir->subdirs, cur, + struct sysfs_directory) { indent(level+4); - if ((sysfs_get_name_from_path(cur->path, - dirname, SYSFS_NAME_LEN)) == 0) - fprintf(stdout, "%s\n", dirname); - else - fprintf(stdout, "%s\n", cur->path); - cur = cur->next; + fprintf(stdout, "%s\n", cur->name); } } if (sdir->links != NULL) { - struct sysfs_link *curl = sdir->links; - - while (curl != NULL) { + struct sysfs_link *curl = NULL; + + dlist_for_each_data(sdir->links, curl, + struct sysfs_link) { indent(level+4); fprintf(stdout, "%s\n", curl->name); - curl = curl->next; } } } @@ -143,18 +138,13 @@ void show_device_children(struct sysfs_directory *sdir, int level) */ int isbinaryvalue(struct sysfs_attribute *attr) { - char attrname[SYSFS_NAME_LEN]; int i; if (attr == NULL || attr->value == NULL) return 0; - if ((sysfs_get_name_from_path(attr->path, attrname, SYSFS_NAME_LEN)) - != 0) - return 0; - for (i = 0; i < binfiles; i++) - if ((strcmp(attrname, binary_files[i])) == 0) + if ((strcmp(attr->name, binary_files[i])) == 0) return 1; return 0; @@ -200,27 +190,21 @@ void show_attribute_value(struct sysfs_attribute *attr, int level) */ void show_attribute(struct sysfs_attribute *attr, int level) { - char attrname[SYSFS_NAME_LEN]; - if (attr == NULL) return; - if ((sysfs_get_name_from_path(attr->path, attrname, SYSFS_NAME_LEN)) - != 0) - return; - if (show_options & SHOW_ALL_ATTRIB_VALUES) { indent(level); - fprintf(stdout, "%s", attrname); + fprintf(stdout, "%s", attr->name); show_attribute_value(attr, level); } else if ((show_options & SHOW_ATTRIBUTES) || ((show_options - & SHOW_ATTRIBUTE_VALUE) && (strcmp(attrname, attribute_to_show) + & SHOW_ATTRIBUTE_VALUE) && (strcmp(attr->name, attribute_to_show) == 0))) { indent(level); - fprintf (stdout, "%s", attrname); + fprintf (stdout, "%s", attr->name); if (show_options & SHOW_ATTRIBUTE_VALUE && attr->value - != NULL && (strcmp(attrname, attribute_to_show)) == 0) + != NULL && (strcmp(attr->name, attribute_to_show)) == 0) show_attribute_value(attr, level); else @@ -235,13 +219,13 @@ void show_attribute(struct sysfs_attribute *attr, int level) void show_attributes(struct sysfs_directory *sdir, int level) { if (sdir != NULL && sdir->attributes != NULL) { - struct sysfs_attribute *cur = sdir->attributes; + struct sysfs_attribute *cur = NULL; indent(level); fprintf (stdout, "Attributes:\n"); - while (cur != NULL) { + dlist_for_each_data(sdir->attributes, cur, + struct sysfs_attribute) { show_attribute(cur, (level+4)); - cur = cur->next; } } } @@ -296,13 +280,13 @@ void show_driver_attributes(struct sysfs_driver *driver, int level) struct sysfs_directory *sdir = driver->directory; if (sdir->attributes != NULL) { - struct sysfs_attribute *cur = sdir->attributes; + struct sysfs_attribute *cur = NULL; indent(level); fprintf (stdout, "%s Attributes:\n", driver->name); - while (cur != NULL) { + dlist_for_each_data(sdir->attributes, cur, + struct sysfs_attribute) { show_attribute(cur, (level+4)); - cur = cur->next; } } } @@ -318,14 +302,14 @@ void show_driver_devices(struct sysfs_driver *driver, int level) struct sysfs_directory *sdir = driver->directory; if (sdir->links != NULL) { - struct sysfs_link *cur = sdir->links; + struct sysfs_link *cur = NULL; indent(level); fprintf (stdout, "Devices:\n"); - while (cur != NULL) { + dlist_for_each_data(sdir->links, cur, + struct sysfs_link) { indent(level+4); fprintf (stdout, "%s\n", cur->name); - cur = cur->next; } } } @@ -367,10 +351,11 @@ void show_device_tree(struct sysfs_device *root, int level) root->bus_id) == 0)) { show_root_device(root, level); } - cur = root->children; - while (cur != NULL) { - show_device_tree(cur, (level+6)); - cur = cur->next; + if (root->children != NULL) { + dlist_for_each_data(root->children, cur, + struct sysfs_device) { + show_device_tree(cur, (level+6)); + } } } } @@ -380,7 +365,7 @@ void show_device_tree(struct sysfs_device *root, int level) * @busname: bus to print. * returns 0 with success or 1 with error. */ -int show_sysfs_bus(char *busname) +int show_sysfs_bus(unsigned char *busname) { struct sysfs_bus *bus = NULL; struct sysfs_device *curdev = NULL; @@ -398,22 +383,18 @@ int show_sysfs_bus(char *busname) fprintf(stdout, "Bus: %s\n", busname); if (bus->devices != NULL && (show_options & SHOW_DEVICES)) { - curdev = bus->devices; if (device_to_show == NULL) fprintf(stdout, "Devices:\n"); - while (curdev != NULL) { + 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); - curdev = curdev->next; } } if (bus->drivers != NULL && (show_options & SHOW_DRIVERS)) { - curdrv = bus->drivers; fprintf(stdout, "Drivers:\n"); - while (curdrv != NULL) { + dlist_for_each_data(bus->drivers, curdrv, struct sysfs_driver) { show_driver(curdrv, 2); - curdrv = curdrv->next; } } sysfs_close_bus(bus); @@ -427,7 +408,6 @@ int show_sysfs_bus(char *busname) void show_class_device(struct sysfs_class_device *dev, int level) { struct sysfs_directory *cur = NULL; - char dirname[SYSFS_NAME_LEN]; if (dev != NULL) { indent(level); @@ -436,15 +416,11 @@ void show_class_device(struct sysfs_class_device *dev, int level) & (SHOW_ATTRIBUTES | SHOW_ATTRIBUTE_VALUE | SHOW_ALL_ATTRIB_VALUES))) { show_attributes(dev->directory, (level+4)); - cur = dev->directory->subdirs; - while (cur != NULL) { - if ((sysfs_get_name_from_path(cur->path, - dirname, SYSFS_NAME_LEN)) == 0) { - indent(level+4); - fprintf(stdout, "%s\n", dirname); - } + dlist_for_each_data(dev->directory->subdirs, cur, + struct sysfs_directory) { + indent(level+4); + fprintf(stdout, "%s\n", cur->name); show_attributes(cur, (level+4)); - cur = cur->next; } } if (dev->sysdevice != NULL && (show_options & SHOW_DEVICES)) @@ -459,7 +435,7 @@ void show_class_device(struct sysfs_class_device *dev, int level) * @classname: class to print. * returns 0 with success and 1 with error. */ -int show_sysfs_class(char *classname) +int show_sysfs_class(unsigned char *classname) { struct sysfs_class *cls = NULL; struct sysfs_class_device *cur = NULL; @@ -475,14 +451,13 @@ int show_sysfs_class(char *classname) } fprintf(stdout, "Class: %s\n", classname); if (cls->devices != NULL) { - cur = cls->devices; if (device_to_show == NULL) fprintf(stdout, "Class Devices:\n"); - while (cur != NULL) { + dlist_for_each_data(cls->devices, cur, + struct sysfs_class_device) { if (device_to_show == NULL || (strcmp(device_to_show, cur->name) == 0)) show_class_device(cur, 2); - cur = cur->next; } } @@ -495,10 +470,10 @@ int show_sysfs_class(char *classname) * @rootname: device root to print. * returns 0 with success and 1 with error. */ -int show_sysfs_root(char *rootname) +int show_sysfs_root(unsigned char *rootname) { struct sysfs_device *root = NULL; - char path[SYSFS_PATH_MAX]; + unsigned char path[SYSFS_PATH_MAX]; if (rootname == NULL) { errno = EINVAL; @@ -530,10 +505,9 @@ int show_sysfs_root(char *rootname) * @path: sysfs path where subdirs are. * returns 0 with success or 1 with error. */ -int show_subdirectories(char *path, int level) +int show_subdirectories(unsigned char *path, int level) { struct sysfs_directory *dir = NULL, *current = NULL; - char name[SYSFS_NAME_LEN]; int ret = 0; dir = sysfs_open_directory(path); @@ -547,16 +521,12 @@ int show_subdirectories(char *path, int level) return 1; } - current = dir->subdirs; - while (current != NULL) { - if ((sysfs_get_name_from_path(current->path, name, - SYSFS_NAME_LEN)) != 0) { - sysfs_close_directory(dir); - return 1; + if (dir->subdirs != NULL) { + dlist_for_each_data(dir->subdirs, current, + struct sysfs_directory) { + indent(level); + fprintf(stdout, "%s\n", current->name); } - indent(level); - fprintf(stdout, "%s\n", name); - current = current->next; } sysfs_close_directory(dir); return ret; @@ -569,8 +539,8 @@ int show_subdirectories(char *path, int level) */ int show_default_info(void) { - char sysfs_root[SYSFS_PATH_MAX]; - char path_to_print[SYSFS_PATH_MAX]; + unsigned char sysfs_root[SYSFS_PATH_MAX]; + unsigned char path_to_print[SYSFS_PATH_MAX]; int retval = 0; /* get sysfs mount point */ @@ -608,9 +578,9 @@ int show_default_info(void) /* MAIN */ int main(int argc, char *argv[]) { - char *show_bus = NULL; - char *show_class = NULL; - char *show_root = NULL; + unsigned char *show_bus = NULL; + unsigned char *show_class = NULL; + unsigned char *show_root = NULL; int retval = 0; int opt; extern int optind; @@ -3979,7 +3979,7 @@ fi done -ac_config_files="$ac_config_files Makefile cmd/Makefile lib/Makefile" +ac_config_files="$ac_config_files Makefile cmd/Makefile lib/Makefile test/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -4472,6 +4472,7 @@ do "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "cmd/Makefile" ) CONFIG_FILES="$CONFIG_FILES cmd/Makefile" ;; "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; + "test/Makefile" ) CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 diff --git a/configure.ac b/configure.ac index a7bce4d..83d62df 100644 --- a/configure.ac +++ b/configure.ac @@ -28,5 +28,6 @@ AC_CHECK_FUNCS([getmntent getpagesize isascii memset strrchr]) AC_CONFIG_FILES([Makefile cmd/Makefile - lib/Makefile]) + lib/Makefile + test/Makefile]) AC_OUTPUT diff --git a/include/dlist.h b/include/dlist.h new file mode 100644 index 0000000..5da79f9 --- /dev/null +++ b/include/dlist.h @@ -0,0 +1,195 @@ +/* + * dlist.h + * + * Copyright (C) 2003 Eric J Bohm + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef _DLIST_H_ +#define _DLIST_H_ + +/* Double linked list header. + +* navigate your list with DLIST_PREV and DLIST_NEXT. These are macros +* so function call overhead is minimized. + +* Supports perl style push, pop, shift, unshift list semantics. + +* You allocate the data and give dlist the pointer. If your data is +* complex set the dlist->del_func to a an appropriate delete using +* dlist_new_with_delete. Your delete function must match +(void * )(del(void *) +*Otherwise dlist will just use free. + +* NOTE: The small amount of pain involved in doing that allows us to +* avoid copy in copy out semantics. + +* Dlist uses an internal mark pointer to keep track of where you are +* in the list. + +* insert and delete take a directional parameter. Where direction +* corresponds to the direction in which you want the list to go. +* true direction corresponded to progressing forward in the last +* false to regressing in the list. +* so a dlist_insert(yourlist,item,1) will insert it after the mark +* so a dlist_insert(yourlist,item,0) will insert it before the mark +* any insert will move the mark to the new node regardless of the direction. + +* Just use the dlist_(insert|delete)_(before|after) macros if you do not want +* to think about it. + +*/ +#include <malloc.h> +typedef struct dl_node { + struct dl_node *prev; + struct dl_node *next; + void *data; +} DL_node; + +typedef struct dlist { + DL_node *marker; + unsigned long count; + size_t data_size; + void (*del_func)(void *); + DL_node headnode; + DL_node *head; +} Dlist; + +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); +void *dlist_mark(Dlist *); +void dlist_start(Dlist *); +void dlist_end(Dlist *); + +void *dlist_insert(Dlist *,void *,int) ; + +void *dlist_insert_sorted(struct dlist *list, void *new, int (*sorter)(void *, void *)); + +void dlist_delete(Dlist *,int); + +void dlist_push(Dlist *,void *); + +void dlist_unshift(Dlist *,void *); + +void *dlist_pop(Dlist *); + +void *dlist_shift(Dlist *); + +void dlist_destroy(Dlist *); + +void *dlist_find_custom(struct dlist *list, void *target, int (*comp)(void *, void *)); +void dlist_transform(struct dlist *list, void (*node_operation)(void *)); + + +/* + * _dlist_remove is for internal use only + * _dlist_mark_move is for internal use only + */ +void *_dlist_remove(struct dlist *,struct dl_node *,int ); + +#define dlist_prev(A) _dlist_mark_move((A),0) +#define dlist_next(A) _dlist_mark_move((A),1) + +#define dlist_insert_before(A,B) dlist_insert((A),(B),0) +#define dlist_insert_after(A,B) dlist_insert((A),(B),1) + +#define dlist_delete_before(A) dlist_delete((A),0) +#define dlist_delete_after(A) dlist_delete((A),1) + +/** + * provide for loop header which iterates the mark from start to end + * list: the dlist pointer, use dlist_mark(list) to get iterator + */ +#define dlist_for_each(list) \ + for(dlist_start(list),dlist_next(list); \ + (list)->marker!=(list)->head;dlist_next(list)) + +/** + * provide for loop header which iterates the mark from end to start + * list: the dlist pointer, use dlist_mark(list) to get iterator + */ +#define dlist_for_each_rev(list) \ + for(dlist_end(list),dlist_prev(list); \ + (list)->marker!=(list)->head;dlist_prev(list)) + +/** + * provide for loop header which iterates through the list without moving mark + * list: the dlist_pointer + * iterator: dl_node pointer to iterate + */ +#define dlist_for_each_nomark(list,iterator) \ + for((iterator)=(list)->head->next; (iterator)!=(list)->head; \ + (iterator)=(iterator)->next) + +/** + * provide for loop header which iterates through the list without moving mark + * in reverse + * list: the dlist_pointer + * iterator: dl_node pointer to iterate + */ +#define dlist_for_each_nomark_rev(list,iterator) \ + for((iterator)=(list)->head->prev; (iterator)!=(list)->head; \ + (iterator)=(iterator)->prev) +/** + * provide for loop header which iterates through the list providing a + * data iterator + * list: the dlist pointer + * data_iterator: the pointer of type datatype to iterate + * datatype: actual type of the contents in the dl_node->data + */ + +#define dlist_for_each_data(list,data_iterator,datatype) \ + for(dlist_start(list), (data_iterator)=(datatype *) dlist_next(list); \ + (list)->marker!=(list)->head;(data_iterator)=(datatype *) dlist_next(list)) + +/** + * provide for loop header which iterates through the list providing a + * data iterator in reverse + * list: the dlist pointer + * data_iterator: the pointer of type datatype to iterate + * datatype: actual type of the contents in the dl_node->data + */ +#define dlist_for_each_data_rev(list,data_iterator,datatype) \ + for(dlist_end(list), (data_iterator)=(datatype *) dlist_prev(list); \ + (list)->marker!=(list)->head;(data_iterator)=(datatype *) dlist_prev(list)) + +/** + * provide for loop header which iterates through the list providing a + * data iterator without moving the mark + * list: the dlist pointer + * iterator: the dl_node pointer to iterate + * data_iterator: the pointer of type datatype to iterate + * datatype: actual type of the contents in the dl_node->data + */ + +#define dlist_for_each_data_nomark(list,iterator,data_iterator,datatype) \ + for((iterator)=(list)->head->next, (data_iterator)=(datatype *) (iterator)->data; \ + (iterator)!=(list)->head;(iterator)=(iterator)->next,(data_iterator)=(datatype *) (iterator)) + +/** + * provide for loop header which iterates through the list providing a + * data iterator in reverse without moving the mark + * list: the dlist pointer + * iterator: the dl_node pointer to iterate + * data_iterator: the pointer of type datatype to iterate + * datatype: actual type of the contents in the dl_node->data + */ +#define dlist_for_each_data_nomark_rev(list,iterator, data_iterator,datatype) \ + for((iterator)=(list)->head->prev, (data_iterator)=(datatype *) (iterator)->data; \ + (iterator)!=(list)->head;(iterator)=(iterator)->prev,(data_iterator)=(datatype *) (iterator)) + +#endif /* _DLIST_H_ */ diff --git a/include/libsysfs.h b/include/libsysfs.h index 93fd1a9..c8df636 100644 --- a/include/libsysfs.h +++ b/include/libsysfs.h @@ -24,6 +24,7 @@ #define _LIBSYSFS_H_ #include <sys/types.h> +#include "dlist.h" /* * Generic #defines go here.. @@ -37,6 +38,7 @@ #define SYSFS_DRIVERS_DIR "/drivers" #define SYSFS_DRIVERS_NAME "drivers" #define SYSFS_NAME_ATTRIBUTE "name" +#define SYSFS_UNKNOWN "unknown" #define SYSFS_PATH_MAX 255 #define SYSFS_NAME_LEN 50 @@ -46,65 +48,76 @@ #define SYSFS_METHOD_STORE 0x02 /* attr can be changed by user */ struct sysfs_attribute { - struct sysfs_attribute *next; - char path[SYSFS_PATH_MAX]; - char *value; + unsigned char *value; unsigned short len; /* value length */ unsigned short method; /* show and store */ + unsigned char name[SYSFS_NAME_LEN]; + unsigned char path[SYSFS_PATH_MAX]; }; struct sysfs_link { - struct sysfs_link *next; - char name[SYSFS_NAME_LEN]; - char target[SYSFS_PATH_MAX]; + unsigned char name[SYSFS_NAME_LEN]; + unsigned char path[SYSFS_PATH_MAX]; + unsigned char target[SYSFS_PATH_MAX]; }; struct sysfs_directory { - struct sysfs_directory *next; - char path[SYSFS_PATH_MAX]; - struct sysfs_directory *subdirs; - struct sysfs_link *links; - struct sysfs_attribute *attributes; + struct dlist *subdirs; + struct dlist *links; + struct dlist *attributes; + unsigned char name[SYSFS_NAME_LEN]; + unsigned char path[SYSFS_PATH_MAX]; }; struct sysfs_driver { - struct sysfs_driver *next; - char name[SYSFS_NAME_LEN]; - struct sysfs_directory *directory; - struct sysfs_device *device; + struct sysfs_device *device; + struct dlist *devices; + unsigned char name[SYSFS_NAME_LEN]; + unsigned char path[SYSFS_PATH_MAX]; + + /* for internal use only */ + struct sysfs_directory *directory; }; struct sysfs_device { - struct sysfs_device *next; - char name[SYSFS_NAME_LEN]; - char bus_id[SYSFS_NAME_LEN]; struct sysfs_driver *driver; - struct sysfs_directory *directory; - struct sysfs_device *parent; - struct sysfs_device *children; + struct sysfs_device *parent; + struct dlist *children; + unsigned char name[SYSFS_NAME_LEN]; + unsigned char bus_id[SYSFS_NAME_LEN]; + unsigned char bus_name[SYSFS_NAME_LEN]; + + /* for internal use only */ + struct sysfs_directory *directory; }; struct sysfs_bus { - struct sysfs_bus *next; - char name[SYSFS_NAME_LEN]; - struct sysfs_directory *directory; - struct sysfs_driver *drivers; - struct sysfs_device *devices; + struct dlist *drivers; + struct dlist *devices; + unsigned char name[SYSFS_NAME_LEN]; + unsigned char path[SYSFS_PATH_MAX]; + + /* internal use only */ + struct sysfs_directory *directory; }; struct sysfs_class_device { - struct sysfs_class_device *next; - char name[SYSFS_NAME_LEN]; - struct sysfs_directory *directory; struct sysfs_device *sysdevice; /* NULL if virtual */ struct sysfs_driver *driver; /* NULL if not implemented */ + unsigned char name[SYSFS_NAME_LEN]; + unsigned char path[SYSFS_PATH_MAX]; + + /* for internal use only */ + struct sysfs_directory *directory; }; struct sysfs_class { - struct sysfs_class *next; - char name[SYSFS_NAME_LEN]; - struct sysfs_directory *directory; - struct sysfs_class_device *devices; + struct dlist *devices; + unsigned char name[SYSFS_NAME_LEN]; + unsigned char path[SYSFS_PATH_MAX]; + + /* for internal use only */ + struct sysfs_directory *directory; }; #ifdef __cplusplus @@ -114,45 +127,68 @@ extern "C" { /* * Function Prototypes */ -extern int sysfs_get_mnt_path(char *mnt_path, size_t len); -extern int sysfs_get_name_from_path(const char *path, char *name, size_t len); -extern int sysfs_get_link(const char *path, char *target, size_t len); +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_get_link(const unsigned char *path, unsigned char *target, + size_t len); /* sysfs directory and file access */ extern void sysfs_close_attribute(struct sysfs_attribute *sysattr); -extern struct sysfs_attribute *sysfs_open_attribute(const char *path); +extern struct sysfs_attribute *sysfs_open_attribute(const unsigned char *path); extern int sysfs_read_attribute(struct sysfs_attribute *sysattr); -extern int sysfs_read_attribute_value(const char *attrpath, char *value, - size_t vsize); -extern char *sysfs_get_value_from_attributes(struct sysfs_attribute *attr, - const char * name); +extern int sysfs_read_attribute_value(const unsigned char *attrpath, + unsigned char *value, size_t vsize); +extern unsigned char *sysfs_get_value_from_attributes(struct dlist *attr, + const unsigned char * name); extern void sysfs_close_directory(struct sysfs_directory *sysdir); -extern struct sysfs_directory *sysfs_open_directory(const char *path); +extern struct sysfs_directory *sysfs_open_directory(const unsigned char *path); extern int sysfs_read_directory(struct sysfs_directory *sysdir); +extern int sysfs_read_all_subdirs(struct sysfs_directory *sysdir); +extern struct sysfs_directory *sysfs_get_subdirectory + (struct sysfs_directory *dir, unsigned char *subname); extern void sysfs_close_link(struct sysfs_link *ln); -extern struct sysfs_link *sysfs_open_link(const char *lnpath); +extern struct sysfs_link *sysfs_open_link(const unsigned char *lnpath); +extern struct sysfs_link *sysfs_get_directory_link(struct sysfs_directory *dir, + unsigned char *linkname); +extern struct sysfs_link *sysfs_get_subdirectory_link + (struct sysfs_directory *dir, unsigned char *linkname); +extern struct sysfs_attribute *sysfs_get_directory_attribute + (struct sysfs_directory *dir, unsigned char *attrname); /* sysfs driver access */ extern void sysfs_close_driver(struct sysfs_driver *driver); -extern struct sysfs_driver *sysfs_open_driver(const char *path); +extern struct sysfs_driver *sysfs_open_driver(const unsigned char *path); /* generic sysfs device access */ extern void sysfs_close_device(struct sysfs_device *dev); extern void sysfs_close_device_tree(struct sysfs_device *dev); -extern struct sysfs_device *sysfs_open_device(const char *path); -extern struct sysfs_device *sysfs_open_device_tree(const char *path); +extern struct sysfs_device *sysfs_open_device(const unsigned char *path); +extern struct sysfs_device *sysfs_open_device_tree(const unsigned char *path); extern struct sysfs_attribute *sysfs_get_device_attr - (struct sysfs_device *dev, const char *name); + (struct sysfs_device *dev, const unsigned char *name); /* generic sysfs bus access */ extern void sysfs_close_bus(struct sysfs_bus *bus); -extern struct sysfs_bus *sysfs_open_bus(const char *name); +extern struct sysfs_bus *sysfs_open_bus(const unsigned char *name); +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_attributes(struct sysfs_bus *bus); +extern struct sysfs_attribute *sysfs_get_bus_attribute(struct sysfs_bus *bus, + unsigned char *attrname); +extern struct sysfs_device *sysfs_open_bus_device(unsigned char *busname, + unsigned char *dev_id); +extern int sysfs_find_device_bus_name(unsigned char *dev_id, + unsigned char *busname, size_t bsize); /* generic sysfs class access */ extern void sysfs_close_class_device(struct sysfs_class_device *dev); -extern struct sysfs_class_device *sysfs_open_class_device(const char *path); +extern struct sysfs_class_device *sysfs_open_class_device + (const unsigned char *path); extern void sysfs_close_class(struct sysfs_class *cls); -extern struct sysfs_class *sysfs_open_class(const char *name); +extern struct sysfs_class *sysfs_open_class(const unsigned char *name); #ifdef __cplusplus } diff --git a/lib/Makefile.am b/lib/Makefile.am index 0be483c..d343f01 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,5 +1,5 @@ lib_LIBRARIES = libsysfs.a libsysfs_a_SOURCES = sysfs_utils.c sysfs_dir.c sysfs_bus.c sysfs_class.c \ - sysfs_device.c sysfs_driver.c sysfs.h + sysfs_device.c sysfs_driver.c sysfs.h dlist.c INCLUDES = -I../include diff --git a/lib/Makefile.in b/lib/Makefile.in index d37639a..a2e859e 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -77,7 +77,7 @@ am__quote = @am__quote@ install_sh = @install_sh@ lib_LIBRARIES = libsysfs.a libsysfs_a_SOURCES = sysfs_utils.c sysfs_dir.c sysfs_bus.c sysfs_class.c \ - sysfs_device.c sysfs_driver.c sysfs.h + sysfs_device.c sysfs_driver.c sysfs.h dlist.c INCLUDES = -I../include subdir = lib @@ -90,7 +90,7 @@ libsysfs_a_AR = $(AR) cru libsysfs_a_LIBADD = am_libsysfs_a_OBJECTS = sysfs_utils.$(OBJEXT) sysfs_dir.$(OBJEXT) \ sysfs_bus.$(OBJEXT) sysfs_class.$(OBJEXT) \ - sysfs_device.$(OBJEXT) sysfs_driver.$(OBJEXT) + sysfs_device.$(OBJEXT) sysfs_driver.$(OBJEXT) dlist.$(OBJEXT) libsysfs_a_OBJECTS = $(am_libsysfs_a_OBJECTS) DEFS = @DEFS@ @@ -100,7 +100,7 @@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles -@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/sysfs_bus.Po \ +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/dlist.Po ./$(DEPDIR)/sysfs_bus.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sysfs_class.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sysfs_device.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/sysfs_dir.Po \ @@ -167,6 +167,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysfs_bus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysfs_class.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sysfs_device.Po@am__quote@ diff --git a/lib/dlist.c b/lib/dlist.c new file mode 100644 index 0000000..6dfcf72 --- /dev/null +++ b/lib/dlist.c @@ -0,0 +1,343 @@ +/* + * dlist.c + * + * Copyright (C) 2003 Eric J Bohm + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 021110307 USA + * + */ + + +/* Double linked list implementation. + + * You allocate the data and give dlist the pointer. + * If your data is complex set the dlist->del_func to a an appropriate + * delete function. Otherwise dlist will just use free. + +*/ +#include "dlist.h" + +/* + * Return pointer to node at marker. + * else null if no nodes. + */ + +inline void *dlist_mark(Dlist *list) +{ + if(list->marker!=NULL) + return(list->marker->data); + else + return(NULL); +} + +/* + * Set marker to start. + */ + +inline void dlist_start(Dlist *list) +{ + list->marker=list->head; +} + +/* + * Set marker to end. + */ + +inline void dlist_end(Dlist *list) +{ + list->marker=list->head; +} + +/* internal use function + * quickie inline to consolidate the marker movement logic + * in one place + * + * when direction true it moves marker after + * when direction false it moves marker before. + * return pointer to data at new marker + * if nowhere to move the marker in desired direction return null + */ +inline void *_dlist_mark_move(Dlist *list,int direction) +{ + if(direction) + { + if( list->marker->next!=NULL) + list->marker=list->marker->next; + else + return(NULL); + } + else + { + if( list->marker->prev!=NULL) + list->marker=list->marker->prev; + else + return(NULL); + } + if(list->marker!=list->head) + return(list->marker->data); + else + return(NULL); +} + +/* + * Create new linked list to store nodes of datasize. + * return null if list cannot be created. + */ +Dlist *dlist_new(size_t datasize) +{ + Dlist *list=NULL; + if((list=malloc(sizeof(Dlist)))) + { + list->marker=NULL; + list->count=0L; + list->data_size=datasize; + list->del_func=free; + list->head=&(list->headnode); + list->head->prev=NULL; + list->head->next=NULL; + list->head->data=NULL; + } + return(list); +} + +/* + * Create new linked list to store nodes of datasize set list + * data node delete function to the passed in del_func + * return null if list cannot be created. + */ +Dlist *dlist_new_with_delete(size_t datasize,void (*del_func)(void*)) +{ + Dlist *list=NULL; + list=dlist_new(datasize); + if(list!=NULL) + list->del_func=del_func; + return(list); +} + + +/* + * remove marker node from list + * call data_delete function on data if registered. + * otherwise call free. + * when direction true it moves marker after + * when direction false it moves marker before. + * free marker node + * return nothing. + */ +void dlist_delete(Dlist *list,int direction) +{ + if((list->marker != list->head)&&(list->marker!=NULL)) + { + DL_node *corpse; + corpse=list->marker; + _dlist_mark_move(list,direction); + if(list->head->next==corpse) + list->head->next=corpse->next; + if(list->head->prev==corpse) + list->head->prev=corpse->prev; + if(corpse->prev!=NULL) //should be impossible + corpse->prev->next=corpse->next; + if(corpse->next!=NULL) //should be impossible + corpse->next->prev=corpse->prev; + list->del_func(corpse->data); + list->count--; + free(corpse); + } +} + +/* + * Insert node containing data at marker. + * If direction true it inserts after. + * If direction false it inserts before. + * move marker to inserted node + * return pointer to inserted node + */ +void *dlist_insert(Dlist *list,void *data,int direction) +{ + DL_node *new_node=NULL; + if(list==NULL || data==NULL) + return(NULL); + if(list->marker==NULL) //in case the marker ends up unset + list->marker=list->head; + if((new_node=malloc(sizeof(DL_node)))) + { + new_node->data=data; + new_node->prev=NULL; + new_node->next=NULL; + list->count++; + if(list->head->next==NULL) //no l + { + list->head->next=list->head->prev=new_node; + new_node->prev=list->head; + new_node->next=list->head; + } + else if(direction) + { + new_node->next=list->marker->next; + new_node->prev=list->marker; + list->marker->next->prev=new_node; + list->marker->next=new_node; + } + else + { + new_node->prev=list->marker->prev; + new_node->next=list->marker; + list->marker->prev->next=new_node; + list->marker->prev=new_node; + } + list->marker=new_node; + } + else + { + return(NULL); + } + return(list->marker->data); +} + +/* + * Remove DL_node from list without deallocating data. + * if marker == killme . + * when direction true it moves marker after + * when direction false it moves marker before. + * to previous if there is no next. + */ +void *_dlist_remove(Dlist *list,DL_node *killme,int direction) +{ + if(killme!=NULL) + { + void *killer_data=killme->data; + // take care of head and marker pointers. + if(list->marker==killme) + _dlist_mark_move(list,direction); + if(killme ==list->head->next) + list->head->next=killme->next; + if(killme==list->head->prev) + list->head->prev=killme->prev; + // remove from list + if(killme->prev !=NULL) + killme->prev->next=killme->next; + if(killme->next !=NULL) + killme->next->prev=killme->prev; + list->count--; + free(killme); + return(killer_data); + } + else + return (NULL); +} + + +/* + * Insert node containing data after end. + */ +void dlist_push(Dlist *list,void *data) +{ + list->marker=list->head->prev; + dlist_insert(list,data,1); +} + +/* + * Insert node containing data at start. + */ + +void dlist_unshift(Dlist *list,void *data) + +{ + list->marker=list->head->next; + dlist_insert(list,data,0); +} + + +/* + * Remove end node from list. + * Return pointer to data in removed node. + * Null if no nodes. + */ + +void *dlist_pop(Dlist *list) +{ + return(_dlist_remove(list,list->head->prev,0)); +} + +/* + * Remove start node from list. + * Return pointer to data in removed node. + * Null if no nodes. + */ + +void *dlist_shift(Dlist *list) +{ + return(_dlist_remove(list,list->head->next,1)); +} + + +/* + * destroy the list freeing all memory + */ + + +void dlist_destroy(Dlist *list) +{ + if(list !=NULL) + { + dlist_start(list); + dlist_next(list); + while (dlist_mark(list)) { + dlist_delete(list,1); + } + free(list); + } +} + +/** + * Return void pointer to list_data element matching comp function criteria + * else null + * Does not move the marker. + */ + +void *dlist_find_custom(struct dlist *list, void *target, int (*comp)(void *, void *)) +{ + /* test the comp function on each node */ + struct dl_node *nodepointer; + dlist_for_each_nomark(list,nodepointer) + if(comp(target,nodepointer->data)) + return(nodepointer->data); + return(NULL); +} + +/** + * Apply the node_operation function to each data node in the list + */ +void dlist_transform(struct dlist *list, void (*node_operation)(void *)) +{ + struct dl_node *nodepointer; + dlist_for_each_nomark(list,nodepointer) + node_operation(nodepointer->data); +} + +/** + * insert new into list in sorted order + * sorter function in form int sorter(new,ith) + * must return 1 for when new should go before ith + * else 0 + * return pointer to inserted node + * NOTE: assumes list is already sorted + */ +void *dlist_insert_sorted(struct dlist *list, void *new, int (*sorter)(void *, void *)) +{ + for(dlist_start(list),dlist_next(list); \ + list->marker!=list->head && !sorter(new,list->marker->data);dlist_next(list)); + return(dlist_insert_before(list,new)); +} diff --git a/lib/sysfs_bus.c b/lib/sysfs_bus.c index e61b5a8..908da5c 100644 --- a/lib/sysfs_bus.c +++ b/lib/sysfs_bus.c @@ -23,28 +23,62 @@ #include "libsysfs.h" #include "sysfs.h" +static void sysfs_close_dev(void *dev) +{ + sysfs_close_device((struct sysfs_device *)dev); +} + +static void sysfs_close_drv(void *drv) +{ + sysfs_close_driver((struct sysfs_driver *)drv); +} + +/* + * compares devices' bus ids. + * @a: device id looking for + * @b: sysfs_device comparing being compared + * returns 1 if a==b->bus_id or 0 not equal + */ +static int bus_device_id_equal(void *a, void *b) +{ + if (a == NULL || b == NULL) + return 0; + + if (strcmp(((unsigned char *)a), ((struct sysfs_device *)b)->bus_id) + == 0) + return 1; + return 0; +} + +/* + * compares drivers' names. + * @a: driver name looking for + * @b: sysfs_driver comparing being compared + * returns 1 if a==b->name or 0 not equal + */ +static int bus_driver_name_equal(void *a, void *b) +{ + if (a == NULL || b == NULL) + return 0; + + if (strcmp(((unsigned char *)a), ((struct sysfs_driver *)b)->name) == 0) + return 1; + return 0; +} + /** * sysfs_close_bus: close single bus * @bus: bus structure */ void sysfs_close_bus(struct sysfs_bus *bus) { - struct sysfs_device *curdev = NULL, *nextdev = NULL; - struct sysfs_driver *curdrv = NULL, *nextdrv = NULL; - if (bus != NULL) { if (bus->directory != NULL) sysfs_close_directory(bus->directory); - for (curdev = bus->devices; curdev != NULL; - curdev = nextdev) { - nextdev = curdev->next; - sysfs_close_device(curdev); - } - for (curdrv = bus->drivers; curdrv != NULL; - curdrv = nextdrv) { - nextdrv = curdrv->next; - sysfs_close_driver(curdrv); - } + if (bus->devices) + dlist_destroy(bus->devices); + if (bus->drivers) + dlist_destroy(bus->drivers); free(bus); } } @@ -62,10 +96,10 @@ 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 char *name) +static struct sysfs_directory *open_bus_dir(const unsigned char *name) { - struct sysfs_directory *busdir = NULL, *cur = NULL, *next = NULL; - char buspath[SYSFS_PATH_MAX]; + struct sysfs_directory *busdir = NULL; + unsigned char buspath[SYSFS_PATH_MAX]; if (name == NULL) { errno = EINVAL; @@ -95,43 +129,12 @@ static struct sysfs_directory *open_bus_dir(const char *name) return NULL; } /* read in devices and drivers subdirs */ - for (cur = busdir->subdirs; cur != NULL; cur = next) { - next = cur->next; - if ((sysfs_read_directory(cur)) != 0) - continue; - } + sysfs_read_all_subdirs(busdir); return busdir; } /** - * add_dev_to_bus: adds a bus device to bus device list - * @bus: bus to add the device - * @dev: device to add - */ -static void add_dev_to_bus(struct sysfs_bus *bus, struct sysfs_device *dev) -{ - if (bus != NULL && dev != NULL) { - dev->next = bus->devices; - bus->devices = dev; - } -} - -/** - * add_driver_to_bus: adds a bus driver to bus driver list - * @bus: bus to add driver to - * @driver: driver to add - */ -static void add_driver_to_bus(struct sysfs_bus *bus, - struct sysfs_driver *driver) -{ - if (bus != NULL && driver != NULL) { - driver->next = bus->drivers; - bus->drivers = driver; - } -} - -/** * get_all_bus_devices: gets all devices for bus * @bus: bus to get devices for * returns 0 with success and -1 with failure @@ -140,29 +143,33 @@ static int get_all_bus_devices(struct sysfs_bus *bus) { struct sysfs_device *bdev = NULL; struct sysfs_directory *cur = NULL; - struct sysfs_link *curl = NULL, *nextl = NULL; - char dirname[SYSFS_NAME_LEN]; + struct sysfs_link *curl = NULL; if (bus == NULL || bus->directory == NULL) { errno = EINVAL; return -1; } - for (cur = bus->directory->subdirs; cur != NULL; cur = cur->next) { - memset(dirname, 0, SYSFS_NAME_LEN); - if ((sysfs_get_name_from_path(cur->path, dirname, - SYSFS_NAME_LEN)) != 0) + if (bus->directory->subdirs == NULL) + return 0; + + dlist_for_each_data(bus->directory->subdirs, cur, + struct sysfs_directory) { + if (strcmp(cur->name, SYSFS_DEVICES_NAME) != 0) continue; - if (strcmp(dirname, SYSFS_DEVICES_NAME) != 0) + if (cur->links == NULL) continue; - for (curl = cur->links; curl != NULL; curl = nextl) { - nextl = curl->next; + 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; } - add_dev_to_bus(bus, bdev); + if (bus->devices == NULL) + bus->devices = dlist_new_with_delete + (sizeof(struct sysfs_device), + sysfs_close_dev); + dlist_unshift(bus->devices, bdev); } } @@ -177,31 +184,35 @@ static int get_all_bus_devices(struct sysfs_bus *bus) static int get_all_bus_drivers(struct sysfs_bus *bus) { struct sysfs_driver *driver = NULL; - struct sysfs_directory *cur = NULL, *next = NULL; - struct sysfs_directory *cursub = NULL, *nextsub = NULL; - char dirname[SYSFS_NAME_LEN]; + struct sysfs_directory *cur = NULL; + struct sysfs_directory *cursub = NULL; if (bus == NULL || bus->directory == NULL) { errno = EINVAL; return -1; } - for (cur = bus->directory->subdirs; cur != NULL; cur = next) { - next = cur->next; - memset(dirname, 0, SYSFS_NAME_LEN); - if ((sysfs_get_name_from_path(cur->path, dirname, - SYSFS_NAME_LEN)) != 0) + if (bus->directory->subdirs == NULL) + return 0; + + dlist_for_each_data(bus->directory->subdirs, cur, + struct sysfs_directory) { + if (strcmp(cur->name, SYSFS_DRIVERS_NAME) != 0) continue; - if (strcmp(dirname, SYSFS_DRIVERS_NAME) != 0) + if (cur->subdirs == NULL) continue; - for (cursub = cur->subdirs; cursub != NULL; cursub = nextsub) { - nextsub = cursub->next; + 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; } - add_driver_to_bus(bus, driver); + if (bus->drivers == NULL) + bus->drivers = dlist_new_with_delete + (sizeof(struct sysfs_driver), + sysfs_close_drv); + dlist_unshift(bus->drivers, driver); } } @@ -214,20 +225,22 @@ static int get_all_bus_drivers(struct sysfs_bus *bus) * @busid: busid of device to match * returns 1 if found and 0 if not found */ -static int match_bus_device_to_driver(struct sysfs_driver *driver, char *busid) +static int match_bus_device_to_driver(struct sysfs_driver *driver, + unsigned char *busid) { - struct sysfs_link *cur = NULL, *next = NULL; + struct sysfs_link *cur = NULL; int found = 0; if (driver == NULL || driver->directory == NULL || busid == NULL) { errno = EINVAL; return found; } - for (cur = driver->directory->links; cur != NULL && found == 0; - cur = next) { - next = cur->next; - if ((strcmp(cur->name, busid)) == 0) - found++; + if (driver->directory->links != NULL) { + dlist_for_each_data(driver->directory->links, cur, + struct sysfs_link) { + if ((strcmp(cur->name, busid)) == 0) + found++; + } } return found; } @@ -238,17 +251,15 @@ static int match_bus_device_to_driver(struct sysfs_driver *driver, char *busid) */ static void link_bus_devices_to_drivers(struct sysfs_bus *bus) { - struct sysfs_device *dev = NULL, *nextdev = NULL; - struct sysfs_driver *drv = NULL, *nextdrv = NULL; + struct sysfs_device *dev = NULL; + struct sysfs_driver *drv = NULL; if (bus != NULL && bus->devices != NULL && bus->drivers != NULL) { - for (dev = bus->devices; dev != NULL; dev = nextdev) { - nextdev = dev->next; - - for (drv = bus->drivers; drv != NULL; drv = nextdrv) { - nextdrv = drv->next; + dlist_for_each_data(bus->devices, dev, struct sysfs_device) { + dlist_for_each_data(bus->drivers, drv, + struct sysfs_driver) { if ((match_bus_device_to_driver(drv, - dev->bus_id)) != 0) { + dev->bus_id)) != 0) { dev->driver = drv; drv->device = dev; } @@ -261,7 +272,7 @@ static void link_bus_devices_to_drivers(struct sysfs_bus *bus) * sysfs_open_bus: opens specific bus and all its devices on system * returns sysfs_bus structure with success or NULL with error. */ -struct sysfs_bus *sysfs_open_bus(const char *name) +struct sysfs_bus *sysfs_open_bus(const unsigned char *name) { struct sysfs_bus *bus = NULL; struct sysfs_directory *busdir = NULL; @@ -284,6 +295,7 @@ struct sysfs_bus *sysfs_open_bus(const char *name) sysfs_close_bus(bus); 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); @@ -299,3 +311,172 @@ struct sysfs_bus *sysfs_open_bus(const char *name) return bus; } + +/** + * sysfs_get_bus_device: Get specific device on bus using device's id + * @bus: bus to find device on + * @id: bus_id for device + * returns struct sysfs_device reference or NULL if not found. + */ +struct sysfs_device *sysfs_get_bus_device(struct sysfs_bus *bus, + unsigned char *id) +{ + if (bus == NULL || id == NULL) { + errno = EINVAL; + return NULL; + } + + return (struct sysfs_device *)dlist_find_custom(bus->devices, id, + bus_device_id_equal); +} + +/** + * sysfs_get_bus_driver: Get specific driver on bus using driver name + * @bus: bus to find driver on + * @drvname: name of driver + * returns struct sysfs_driver reference or NULL if not found. + */ +struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus, + unsigned char *drvname) +{ + if (bus == NULL || drvname == NULL) { + errno = EINVAL; + return NULL; + } + + return (struct sysfs_driver *)dlist_find_custom(bus->drivers, drvname, + bus_driver_name_equal); +} + +/** + * sysfs_get_bus_attributes: returns bus' dlist of attributes + * @bus: bus to get attributes for. + * returns dlist of attributes or NULL if there aren't any. + */ +struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus) +{ + if (bus == NULL || bus->directory == NULL) + return NULL; + return bus->directory->attributes; +} + +/** + * sysfs_get_bus_attribute: gets a specific bus attribute, if buses had + * attributes. + * @bus: bus to retrieve attribute from + * @attrname: attribute name to retrieve + * returns reference to sysfs_attribute if found or NULL if not found + */ +struct sysfs_attribute *sysfs_get_bus_attribute(struct sysfs_bus *bus, + unsigned char *attrname) +{ + if (bus == NULL || bus->directory == NULL || attrname == NULL) { + errno = EINVAL; + return NULL; + } + return sysfs_get_directory_attribute(bus->directory, attrname); +} + +/** + * sysfs_open_bus_device: locates a device on a bus and returns it. Device + * must be closed using sysfs_close_device. + * @busname: Name of bus to search + * @dev_id: Id of device on bus. + * returns sysfs_device if found or NULL if not. + */ +struct sysfs_device *sysfs_open_bus_device(unsigned char *busname, + unsigned char *dev_id) +{ + struct sysfs_bus *bus = NULL; + struct sysfs_device *dev = NULL, *rdev = NULL; + + if (busname == NULL || dev_id == NULL) { + errno = EINVAL; + return NULL; + } + + bus = sysfs_open_bus(busname); + if (bus == NULL) { + dprintf("Error opening bus %s\n", busname); + return NULL; + } + + dev = sysfs_get_bus_device(bus, dev_id); + if (dev == NULL) { + dprintf("Error getting device %s on bus %s\n", dev_id, + busname); + sysfs_close_bus(bus); + return NULL; + } + rdev = sysfs_open_device(dev->directory->path); + if (rdev == NULL) { + dprintf("Error getting device %s on bus %s\n", dev_id, + busname); + sysfs_close_bus(bus); + return NULL; + } + sysfs_close_bus(bus); + + return rdev; +} + +/** + * sysfs_find_device_bus: locates the bus a device is on. + * @dev_id: device id. + * @busname: buffer to copy name to + * @bsize: buffer size + * returns 0 with success or -1 with error + */ +int sysfs_find_device_bus_name(unsigned char *dev_id, unsigned char *busname, + size_t bsize) +{ + struct sysfs_directory *busdir = NULL, *cur = NULL, *devdir = NULL; + struct sysfs_link *ln = NULL; + unsigned char path[SYSFS_PATH_MAX]; + unsigned char devpath[SYSFS_PATH_MAX]; + + if (dev_id == NULL || busname == NULL) { + errno = EINVAL; + return -1; + } + if (sysfs_get_mnt_path(path, SYSFS_PATH_MAX) != 0) { + dprintf ("Error finding sysfs root\n"); + return -1; + } + strcat(path, SYSFS_BUS_DIR); + busdir = sysfs_open_directory(path); + if (busdir == NULL) { + dprintf ("Error retrieving bus directory %s\n", path); + return -1; + } + if (sysfs_read_directory(busdir) != 0) { + dprintf ("Error reading directory %s\n", path); + sysfs_close_directory(busdir); + return -1; + } + if (busdir->subdirs != NULL) { + dlist_for_each_data(busdir->subdirs, cur, + struct sysfs_directory) { + memset(devpath, 0, SYSFS_PATH_MAX); + strcpy(devpath, cur->path); + strcat(devpath, SYSFS_DEVICES_DIR); + devdir = sysfs_open_directory(devpath); + if (devdir == NULL) + continue; + if (sysfs_read_directory(devdir) != 0) { + sysfs_close_directory(devdir); + continue; + } + ln = sysfs_get_subdirectory_link(devdir, dev_id); + if (ln != NULL) { + strcpy(busname, cur->name); + sysfs_close_directory(devdir); + return 0; + } + sysfs_close_directory(devdir); + } + } + strcpy(busname, SYSFS_UNKNOWN); + sysfs_close_directory(busdir); + return 0; +} diff --git a/lib/sysfs_class.c b/lib/sysfs_class.c index 704fe44..211d41f 100644 --- a/lib/sysfs_class.c +++ b/lib/sysfs_class.c @@ -23,6 +23,11 @@ #include "libsysfs.h" #include "sysfs.h" +void sysfs_close_cls_dev(void *dev) +{ + sysfs_close_class_device((struct sysfs_class_device *)dev); +} + /** * sysfs_close_class_device: closes a single class device. * @dev: class device to close. @@ -46,15 +51,11 @@ void sysfs_close_class_device(struct sysfs_class_device *dev) */ void sysfs_close_class(struct sysfs_class *cls) { - struct sysfs_class_device *cur = NULL, *next = NULL; - if (cls != NULL) { if (cls->directory != NULL) sysfs_close_directory(cls->directory); - for (cur = cls->devices; cur != NULL; cur = next) { - next = cur->next; - sysfs_close_class_device(cur); - } + if (cls->devices != NULL) + dlist_destroy(cls->devices); free(cls); } } @@ -82,10 +83,10 @@ 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 char *name) +static struct sysfs_directory *open_class_dir(const unsigned char *name) { struct sysfs_directory *classdir = NULL; - char classpath[SYSFS_PATH_MAX]; + unsigned char classpath[SYSFS_PATH_MAX]; if (name == NULL) { errno = EINVAL; @@ -121,10 +122,10 @@ static struct sysfs_directory *open_class_dir(const char *name) * @path: path to class device. * returns struct sysfs_class_device with success and NULL with error. */ -struct sysfs_class_device *sysfs_open_class_device(const char *path) +struct sysfs_class_device *sysfs_open_class_device(const unsigned char *path) { struct sysfs_class_device *cdev = NULL; - struct sysfs_directory *dir = NULL, *cur = NULL; + struct sysfs_directory *dir = NULL; struct sysfs_link *curl = NULL; struct sysfs_device *sdev = NULL; struct sysfs_driver *drv = NULL; @@ -157,51 +158,36 @@ struct sysfs_class_device *sysfs_open_class_device(const char *path) sysfs_close_class_device(cdev); return NULL; } + sysfs_read_all_subdirs(dir); cdev->directory = dir; + strcpy(cdev->path, dir->path); - cur = cdev->directory->subdirs; - while(cur != NULL) { - sysfs_read_directory(cur); - cur = cur->next; - } /* get driver and device, if implemented */ - curl = cdev->directory->links; - while (curl != NULL) { - 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) - sdev->driver = cdev->driver; - } - } else if (strncmp(curl->name, SYSFS_DRIVERS_NAME, 6) == 0) { - drv = sysfs_open_driver(curl->target); - if (drv != NULL) { - cdev->driver = drv; - if (cdev->sysdevice != NULL) - drv->device = cdev->sysdevice; + 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) + sdev->driver = cdev->driver; + } + } else if (strncmp(curl->name, + SYSFS_DRIVERS_NAME, 6) == 0) { + drv = sysfs_open_driver(curl->target); + if (drv != NULL) { + cdev->driver = drv; + if (cdev->sysdevice != NULL) + drv->device = cdev->sysdevice; + } } } - curl = curl->next; } return cdev; } /** - * add_dev_to_class: adds a class device to class list - * @class: class to add the device - * @dev: device to add - */ -static void add_dev_to_class(struct sysfs_class *cls, - struct sysfs_class_device *dev) -{ - if (cls != NULL && dev != NULL) { - dev->next = cls->devices; - cls->devices = dev; - } -} - -/** * get_all_class_devices: gets all devices for class * @class: class to get devices for * returns 0 with success and -1 with failure @@ -209,22 +195,27 @@ static void add_dev_to_class(struct sysfs_class *cls, static int get_all_class_devices(struct sysfs_class *cls) { struct sysfs_class_device *dev = NULL; - struct sysfs_directory *cur = NULL, *next = NULL; + struct sysfs_directory *cur = NULL; if (cls == NULL || cls->directory == NULL) { errno = EINVAL; return -1; } - for (cur = cls->directory->subdirs; cur != NULL; cur = next) { - next = cur->next; + if (cls->directory->subdirs == NULL) + return 0; + dlist_for_each_data(cls->directory->subdirs, cur, + struct sysfs_directory) { dev = sysfs_open_class_device(cur->path); if (dev == NULL) { dprintf("Error opening device at %s\n", cur->path); continue; } - add_dev_to_class(cls, dev); + if (cls->devices == NULL) + cls->devices = dlist_new_with_delete + (sizeof(struct sysfs_class_device), + sysfs_close_cls_dev); + dlist_unshift(cls->devices, dev); } - return 0; } @@ -232,7 +223,7 @@ static int get_all_class_devices(struct sysfs_class *cls) * sysfs_open_class: opens specific class and all its devices on system * returns sysfs_class structure with success or NULL with error. */ -struct sysfs_class *sysfs_open_class(const char *name) +struct sysfs_class *sysfs_open_class(const unsigned char *name) { struct sysfs_class *cls = NULL; struct sysfs_directory *classdir = NULL; @@ -256,6 +247,7 @@ struct sysfs_class *sysfs_open_class(const char *name) 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); diff --git a/lib/sysfs_device.c b/lib/sysfs_device.c index 4756c05..abdbd69 100644 --- a/lib/sysfs_device.c +++ b/lib/sysfs_device.c @@ -24,17 +24,24 @@ #include "sysfs.h" /** + * sysfs_del_device: routine for dlist integration + */ +static void sysfs_del_device(void *dev) +{ + sysfs_close_device((struct sysfs_device *)dev); +} + +/** * sysfs_close_device: closes and cleans up a device * @dev = device to clean up */ void sysfs_close_device(struct sysfs_device *dev) { if (dev != NULL) { - dev->next = NULL; - dev->driver = NULL; if (dev->directory != NULL) sysfs_close_directory(dev->directory); - dev->children = NULL; + if (dev->children != NULL && dev->children->count == 0) + dlist_destroy(dev->children); free(dev); } } @@ -55,16 +62,18 @@ static struct sysfs_device *alloc_device(void) * returns sysfs_attribute reference with success or NULL with error. */ struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev, - const char *name) + const unsigned char *name) { struct sysfs_attribute *cur = NULL; - char attrname[SYSFS_NAME_LEN]; + unsigned char attrname[SYSFS_NAME_LEN]; - if (dev == NULL || dev->directory == NULL || name == NULL) { + if (dev == NULL || dev->directory == NULL + || dev->directory->attributes == NULL || name == NULL) { errno = EINVAL; return NULL; } - for (cur = dev->directory->attributes; cur != NULL; cur = cur->next) { + dlist_for_each_data(dev->directory->attributes, cur, + struct sysfs_attribute) { if ((sysfs_get_name_from_path(cur->path, attrname, SYSFS_NAME_LEN)) != 0) continue; @@ -82,11 +91,11 @@ struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev, * @path: path to device, this is the /sys/devices/ path * returns sysfs_device structure with success or NULL with error */ -struct sysfs_device *sysfs_open_device(const char *path) +struct sysfs_device *sysfs_open_device(const unsigned char *path) { struct sysfs_device *dev = NULL; struct sysfs_directory *sdir = NULL; - char *p = NULL; + unsigned char *p = NULL; if (path == NULL) { errno = EINVAL; @@ -111,7 +120,9 @@ struct sysfs_device *sysfs_open_device(const char *path) return NULL; } dev->directory = sdir; - sysfs_get_name_from_path(sdir->path, dev->bus_id, SYSFS_NAME_LEN); + strcpy(dev->bus_id, sdir->name); + sysfs_find_device_bus_name(dev->bus_id, dev->bus_name, SYSFS_NAME_LEN); + /* get device name */ p = sysfs_get_value_from_attributes(sdir->attributes, SYSFS_NAME_ATTRIBUTE); @@ -134,11 +145,10 @@ void sysfs_close_device_tree(struct sysfs_device *devroot) { if (devroot != NULL) { if (devroot->children != NULL) { - struct sysfs_device *child = NULL, *next = NULL; - - for (child = devroot->children; child != NULL; - child = next) { - next = child->next; + struct sysfs_device *child = NULL; + + dlist_for_each_data(devroot->children, child, + struct sysfs_device) { sysfs_close_device_tree(child); } } @@ -147,28 +157,13 @@ void sysfs_close_device_tree(struct sysfs_device *devroot) } /** - * add_device_child_to_parent: adds child device to parent - * @parent: parent device. - * @child: child device to add. - */ -static void add_device_child_to_parent(struct sysfs_device *parent, - struct sysfs_device *child) -{ - if (parent != NULL && child != NULL) { - child->next = parent->children; - parent->children = child; - child->parent = parent; - } -} - -/** * 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 *sysfs_open_device_tree(const unsigned char *path) { struct sysfs_device *rootdev = NULL, *new = NULL; struct sysfs_directory *cur = NULL; @@ -182,17 +177,22 @@ struct sysfs_device *sysfs_open_device_tree(const char *path) dprintf("Error opening root device at %s\n", path); return NULL; } - cur = rootdev->directory->subdirs; - while (cur != NULL) { - 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->directory->subdirs != NULL) { + dlist_for_each_data(rootdev->directory->subdirs, cur, + struct sysfs_directory) { + 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_del_device); + dlist_unshift(rootdev->children, new); } - add_device_child_to_parent(rootdev, new); - cur = cur->next; } return rootdev; diff --git a/lib/sysfs_dir.c b/lib/sysfs_dir.c index b089d81..1b365d7 100644 --- a/lib/sysfs_dir.c +++ b/lib/sysfs_dir.c @@ -24,6 +24,81 @@ #include "sysfs.h" /** + * sysfs_del_attribute: routine for dlist integration + */ +static void sysfs_del_attribute(void *attr) +{ + sysfs_close_attribute((struct sysfs_attribute *)attr); +} + +/** + * sysfs_del_link: routine for dlist integration + */ +static void sysfs_del_link(void *ln) +{ + sysfs_close_link((struct sysfs_link *)ln); +} + +/** + * sysfs_del_dir: routine for dlist integration + */ +static void sysfs_del_directory(void *dir) +{ + sysfs_close_directory((struct sysfs_directory *)dir); +} + +/** + * dir_attribute_name_equal: compares dir attributes by name + * @a: attribute name for comparison + * @b: sysfs_attribute to be compared. + * returns 1 if a==b->name or 0 if not equal + */ +static int dir_attribute_name_equal(void *a, void *b) +{ + if (a == NULL || b == NULL) + return 0; + + if (strcmp(((unsigned char *)a), ((struct sysfs_attribute *)b)->name) + == 0) + return 1; + return 0; +} + +/** + * dir_link_name_equal: compares dir links by name + * @a: link name for comparison + * @b: sysfs_link to be compared. + * returns 1 if a==b->name or 0 if not equal + */ +static int dir_link_name_equal(void *a, void *b) +{ + if (a == NULL || b == NULL) + return 0; + + if (strcmp(((unsigned char *)a), ((struct sysfs_link *)b)->name) + == 0) + return 1; + return 0; +} + +/** + * dir_subdir_name_equal: compares subdirs by name + * @a: name of subdirectory to compare + * @b: sysfs_directory subdirectory to be compared + * returns 1 if a==b->name or 0 if not equal + */ +static int dir_subdir_name_equal(void *a, void *b) +{ + if (a == NULL || b == NULL) + return 0; + + if (strcmp(((unsigned char *)a), ((struct sysfs_directory *)b)->name) + == 0) + return 1; + return 0; +} + +/** * sysfs_close_attribute: closes and cleans up attribute * @sysattr: attribute to close. */ @@ -51,7 +126,7 @@ static struct sysfs_attribute *alloc_attribute(void) * @path: path to attribute. * returns sysfs_attribute struct with success and NULL with error. */ -struct sysfs_attribute *sysfs_open_attribute(const char *path) +struct sysfs_attribute *sysfs_open_attribute(const unsigned char *path) { struct sysfs_attribute *sysattr = NULL; struct stat fileinfo; @@ -65,6 +140,13 @@ struct sysfs_attribute *sysfs_open_attribute(const char *path) dprintf("Error allocating attribute at %s\n", path); return NULL; } + if (sysfs_get_name_from_path(path, sysattr->name, SYSFS_NAME_LEN) + != 0) { + dprintf("Error retrieving attribute name from path: %s\n", + path); + sysfs_close_attribute(sysattr); + return NULL; + } strncpy(sysattr->path, path, sizeof(sysattr->path)); if ((stat(sysattr->path, &fileinfo)) != 0) { perror("stat"); @@ -86,8 +168,8 @@ struct sysfs_attribute *sysfs_open_attribute(const char *path) */ int sysfs_read_attribute(struct sysfs_attribute *sysattr) { - char *fbuf = NULL; - char *vbuf = NULL; + unsigned char *fbuf = NULL; + unsigned char *vbuf = NULL; size_t length = 0; int pgsize = 0; int fd; @@ -102,7 +184,7 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr) return -1; } pgsize = getpagesize(); - fbuf = (char *)calloc(1, pgsize+1); + fbuf = (unsigned char *)calloc(1, pgsize+1); if (fbuf == NULL) { perror("calloc"); return -1; @@ -121,7 +203,7 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr) } sysattr->len = length; close(fd); - vbuf = (char *)realloc(fbuf, length+1); + vbuf = (unsigned char *)realloc(fbuf, length+1); if (vbuf == NULL) { perror("realloc"); free(fbuf); @@ -141,7 +223,8 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr) * @vsize: size of value buffer * returns 0 with success and -1 with error. */ -int sysfs_read_attribute_value(const char *attrpath, char *value, size_t vsize) +int sysfs_read_attribute_value(const unsigned char *attrpath, + unsigned char *value, size_t vsize) { struct sysfs_attribute *attr = NULL; size_t length = 0; @@ -177,85 +260,32 @@ int sysfs_read_attribute_value(const char *attrpath, char *value, size_t vsize) * attribute name, return its value * @attr: attribute to search * @name: name to look for - * returns char * value - could be NULL + * returns unsigned char * value - could be NULL */ -char *sysfs_get_value_from_attributes(struct sysfs_attribute *attr, - const char *name) +unsigned char *sysfs_get_value_from_attributes(struct dlist *attr, + const unsigned char *name) { struct sysfs_attribute *cur = NULL; - char tmpname[SYSFS_NAME_LEN]; if (attr == NULL || name == NULL) { errno = EINVAL; return NULL; - } - cur = attr; - while (cur != NULL) { - memset(tmpname, 0, SYSFS_NAME_LEN); - if ((sysfs_get_name_from_path(cur->path, tmpname, - SYSFS_NAME_LEN)) != 0) { - cur = cur->next; - continue; - } - if (strcmp(tmpname, name) == 0) + } + dlist_for_each_data(attr, cur, struct sysfs_attribute) { + if (strcmp(cur->name, name) == 0) return cur->value; - cur = cur->next; } return NULL; } /** - * add_subdir_to_dir: adds subdirectory to directory's subdirs - * @sysdir: directory to add subdir to - * @subdir: subdirectory to add. - */ -static void add_subdir_to_dir(struct sysfs_directory *sysdir, - struct sysfs_directory *subdir) -{ - if (sysdir != NULL && subdir != NULL) { - subdir->next = sysdir->subdirs; - sysdir->subdirs = subdir; - } -} - -/** - * add_attr_to_dir: adds attribute to directory's attributes - * @sysdir: directory to add attribute to - * @sysattr: attribute to add. - */ -static void add_attr_to_dir(struct sysfs_directory *sysdir, - struct sysfs_attribute *sysattr) -{ - if (sysdir != NULL && sysattr != NULL) { - sysattr->next = sysdir->attributes; - sysdir->attributes = sysattr; - } -} - -/** * sysfs_close_link: closes and cleans up link. * @ln: link to close. */ void sysfs_close_link(struct sysfs_link *ln) { - if (ln != NULL) { - ln->next = NULL; + if (ln != NULL) free(ln); - } -} - -/** - * add_link_to_dir: adds link to directory's links list. - * @sysdir: directory to add it to. - * @ln: link to add. - */ -static void add_link_to_dir(struct sysfs_directory *sysdir, - struct sysfs_link *ln) -{ - if (sysdir != NULL && ln != NULL) { - ln->next = sysdir->links; - sysdir->links = ln; - } } /** @@ -264,35 +294,13 @@ static void add_link_to_dir(struct sysfs_directory *sysdir, */ void sysfs_close_directory(struct sysfs_directory *sysdir) { - struct sysfs_directory *sdir = NULL, *dnext = NULL; - struct sysfs_link *dlink = NULL, *nextl = NULL; - struct sysfs_attribute *attr = NULL, *anext = NULL; - if (sysdir != NULL) { - if (sysdir->subdirs != NULL) { - for (sdir = sysdir->subdirs; sdir != NULL; - sdir = dnext) { - dnext = sdir->next; - sysfs_close_directory(sdir); - } - } - if (sysdir->links != NULL) { - for (dlink = sysdir->links; dlink != NULL; - dlink = nextl) { - nextl = dlink->next; - sysfs_close_link(dlink); - } - } - if (sysdir->attributes != NULL) { - for (attr = sysdir->attributes; attr != NULL; - attr = anext) { - anext = attr->next; - /* sysfs_close_attribute(attr); */ - if (attr->value != NULL) - free(attr->value); - free(attr); - } - } + if (sysdir->subdirs != NULL) + dlist_destroy(sysdir->subdirs); + if (sysdir->links != NULL) + dlist_destroy(sysdir->links); + if (sysdir->attributes != NULL) + dlist_destroy(sysdir->attributes); free(sysdir); } } @@ -317,12 +325,35 @@ static struct sysfs_link *alloc_link(void) } /** + * sysfs_read_all_subdirs: calls sysfs_read_directory for all subdirs + * @sysdir: directory whose subdirs need reading. + * returns 0 with success and -1 with error. + */ +int sysfs_read_all_subdirs(struct sysfs_directory *sysdir) +{ + struct sysfs_directory *cursub = NULL; + + if (sysdir == NULL) { + errno = EINVAL; + return -1; + } + if (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", + cursub->name); + } + return 0; +} + +/** * sysfs_open_directory: opens a sysfs directory, creates dir struct, and * returns. * @path: path of directory to open. * returns: struct sysfs_directory * with success and NULL on error. */ -struct sysfs_directory *sysfs_open_directory(const char *path) +struct sysfs_directory *sysfs_open_directory(const unsigned char *path) { struct sysfs_directory *sdir = NULL; @@ -335,6 +366,11 @@ struct sysfs_directory *sysfs_open_directory(const char *path) dprintf("Error allocating directory %s\n", path); return NULL; } + if (sysfs_get_name_from_path(path, sdir->name, SYSFS_NAME_LEN) != 0) { + dprintf("Error getting directory name from path: %s\n", path); + sysfs_close_directory(sdir); + return NULL; + } strncpy(sdir->path, path, sizeof(sdir->path)); return sdir; @@ -345,11 +381,11 @@ struct sysfs_directory *sysfs_open_directory(const char *path) * @path: path of link to open. * returns: struct sysfs_link * with success and NULL on error. */ -struct sysfs_link *sysfs_open_link(const char *linkpath) +struct sysfs_link *sysfs_open_link(const unsigned char *linkpath) { struct sysfs_link *ln = NULL; - if (linkpath == NULL) { + if (linkpath == NULL || strlen(linkpath) > SYSFS_PATH_MAX) { errno = EINVAL; return NULL; } @@ -359,6 +395,7 @@ struct sysfs_link *sysfs_open_link(const char *linkpath) dprintf("Error allocating link %s\n", linkpath); return NULL; } + strcpy(ln->path, linkpath); if ((sysfs_get_name_from_path(linkpath, ln->name, SYSFS_NAME_LEN)) != 0 || (sysfs_get_link(linkpath, ln->target, SYSFS_PATH_MAX)) != 0) { errno = EINVAL; @@ -382,7 +419,7 @@ int sysfs_read_directory(struct sysfs_directory *sysdir) struct sysfs_attribute *attr = NULL; struct sysfs_directory *subdir = NULL; struct sysfs_link *ln = NULL; - char file_path[SYSFS_PATH_MAX]; + unsigned char file_path[SYSFS_PATH_MAX]; int retval = 0; if (sysdir == NULL) { @@ -423,7 +460,12 @@ int sysfs_read_directory(struct sysfs_directory *sysdir) continue; } } - add_attr_to_dir(sysdir, attr); + + if (sysdir->attributes == NULL) + sysdir->attributes = dlist_new_with_delete + (sizeof(struct sysfs_attribute), + sysfs_del_attribute); + dlist_unshift(sysdir->attributes, attr); } else if (S_ISDIR(astats.st_mode)) { subdir = sysfs_open_directory(file_path); if (subdir == NULL) { @@ -432,7 +474,11 @@ int sysfs_read_directory(struct sysfs_directory *sysdir) retval = -1; break; } - add_subdir_to_dir(sysdir, subdir); + 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) { @@ -440,9 +486,111 @@ int sysfs_read_directory(struct sysfs_directory *sysdir) retval = -1; break; } - add_link_to_dir(sysdir, ln); + if (sysdir->links == NULL) + sysdir->links = dlist_new_with_delete + (sizeof(struct sysfs_link), + sysfs_del_link); + dlist_unshift(sysdir->links, ln); } } closedir(dir); return(retval); } + +/** + * sysfs_get_directory_attribute: retrieves attribute attrname + * @dir: directory to retrieve attribute from + * @attrname: name of attribute to look for + * returns sysfs_attribute if found and NULL if not found + */ +struct sysfs_attribute *sysfs_get_directory_attribute + (struct sysfs_directory *dir, unsigned char *attrname) +{ + if (dir == NULL || attrname == NULL) { + errno = EINVAL; + return NULL; + } + return (struct sysfs_attribute *)dlist_find_custom(dir->attributes, + attrname, dir_attribute_name_equal); +} + +/** + * sysfs_get_directory_link: retrieves link from one directory list + * @dir: directory to retrieve link from + * @linkname: name of link to look for + * returns reference to sysfs_link if found and NULL if not found + */ +struct sysfs_link *sysfs_get_directory_link + (struct sysfs_directory *dir, unsigned char *linkname) +{ + if (dir == NULL || linkname == NULL) { + errno = EINVAL; + return NULL; + } + return (struct sysfs_link *)dlist_find_custom(dir->links, + linkname, dir_link_name_equal); +} + +/** + * sysfs_get_subdirectory: retrieves subdirectory by name. + * @dir: directory to search for subdirectory. + * @subname: subdirectory name to get. + * returns reference to subdirectory or NULL if not found + */ +struct sysfs_directory *sysfs_get_subdirectory(struct sysfs_directory *dir, + unsigned char *subname) +{ + struct sysfs_directory *sub = NULL, *cursub = NULL; + + if (dir == NULL || dir->subdirs == NULL || subname == NULL) { + errno = EINVAL; + return NULL; + } + sub = (struct sysfs_directory *)dlist_find_custom(dir->subdirs, + subname, dir_subdir_name_equal); + if (sub != NULL) + return sub; + + dlist_for_each_data(dir->subdirs, cursub, struct sysfs_directory) { + if (cursub->subdirs == NULL) + continue; + sub = sysfs_get_subdirectory(cursub, subname); + if (sub != NULL) + return sub; + } + return NULL; +} + +/** + * sysfs_get_subdirectory_link: looks through all subdirs for specific link. + * @dir: directory and subdirectories to search for link. + * @linkname: link name to get. + * returns reference to link or NULL if not found + */ +struct sysfs_link *sysfs_get_subdirectory_link(struct sysfs_directory *dir, + unsigned char *linkname) +{ + struct sysfs_directory *cursub = NULL; + struct sysfs_link *ln = NULL; + + if (dir == NULL || dir->links == NULL || linkname == NULL) { + errno = EINVAL; + return NULL; + } + + ln = sysfs_get_directory_link(dir, linkname); + if (ln != NULL) + return ln; + + if (dir->subdirs == NULL) + return 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; + } + return NULL; +} diff --git a/lib/sysfs_driver.c b/lib/sysfs_driver.c index 5558c03..f890b22 100644 --- a/lib/sysfs_driver.c +++ b/lib/sysfs_driver.c @@ -50,11 +50,10 @@ static struct sysfs_driver *alloc_driver(void) * @path: path to driver directory * returns struct sysfs_driver with success and NULL with error */ -struct sysfs_driver *sysfs_open_driver(const char *path) +struct sysfs_driver *sysfs_open_driver(const unsigned char *path) { struct sysfs_driver *driver = NULL; struct sysfs_directory *sdir = NULL; - char devname[SYSFS_NAME_LEN]; if (path == NULL) { errno = EINVAL; @@ -76,14 +75,9 @@ struct sysfs_driver *sysfs_open_driver(const char *path) sysfs_close_directory(sdir); return NULL; } - if ((sysfs_get_name_from_path(path, devname, SYSFS_NAME_LEN)) != 0) { - dprintf("Error reading directory %s\n", path); - sysfs_close_directory(sdir); - free(driver); - return NULL; - } - strncpy(driver->name, devname, sizeof(driver->name)); + strcpy(driver->name, sdir->name); driver->directory = sdir; + strcpy(driver->path, sdir->path); return driver; } diff --git a/lib/sysfs_utils.c b/lib/sysfs_utils.c index def955e..d4c085b 100644 --- a/lib/sysfs_utils.c +++ b/lib/sysfs_utils.c @@ -30,8 +30,8 @@ * @len: size of mnt_path * returns 0 with success and -1 with error. */ -static int sysfs_get_fs_mnt_path(const char *fs_type, char *mnt_path, - size_t len) +static int sysfs_get_fs_mnt_path(const unsigned char *fs_type, + unsigned char *mnt_path, size_t len) { FILE *mnt; struct mntent *mntent; @@ -74,7 +74,7 @@ static int sysfs_get_fs_mnt_path(const char *fs_type, char *mnt_path, * @len: size of mnt_path * returns 0 with success and -1 with error. */ -int sysfs_get_mnt_path(char *mnt_path, size_t len) +int sysfs_get_mnt_path(unsigned char *mnt_path, size_t len) { int ret = -1; @@ -92,9 +92,10 @@ int sysfs_get_mnt_path(char *mnt_path, size_t len) * @name: where to put name * @len: size of name */ -int sysfs_get_name_from_path(const char *path, char *name, size_t len) +int sysfs_get_name_from_path(const unsigned char *path, unsigned char *name, + size_t len) { - char *n = NULL; + unsigned char *n = NULL; if (path == NULL || name == NULL) { errno = EINVAL; @@ -117,11 +118,11 @@ int sysfs_get_name_from_path(const char *path, char *name, size_t len) * @target: where to put name * @len: size of name */ -int sysfs_get_link(const char *path, char *target, size_t len) +int sysfs_get_link(const unsigned char *path, unsigned char *target, size_t len) { - char devdir[SYSFS_PATH_MAX]; - char linkpath[SYSFS_PATH_MAX]; - char *d = NULL; + unsigned char devdir[SYSFS_PATH_MAX]; + unsigned char linkpath[SYSFS_PATH_MAX]; + unsigned char *d = NULL; if (path == NULL || target == NULL) { errno = EINVAL; diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100644 index 0000000..25a4881 --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,4 @@ +bin_PROGRAMS = dlist_test +dlist_test_SOURCES = dlist_test.c +INCLUDES = -I../include +LDADD = ../lib/libsysfs.a diff --git a/test/Makefile.in b/test/Makefile.in new file mode 100644 index 0000000..fb046a8 --- /dev/null +++ b/test/Makefile.in @@ -0,0 +1,316 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AWK = @AWK@ +CC = @CC@ +DEPDIR = @DEPDIR@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ +bin_PROGRAMS = dlist_test +dlist_test_SOURCES = dlist_test.c +INCLUDES = -I../include +LDADD = ../lib/libsysfs.a +subdir = test +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +bin_PROGRAMS = dlist_test$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) + +am_dlist_test_OBJECTS = dlist_test.$(OBJEXT) +dlist_test_OBJECTS = $(am_dlist_test_OBJECTS) +dlist_test_LDADD = $(LDADD) +dlist_test_DEPENDENCIES = ../lib/libsysfs.a +dlist_test_LDFLAGS = + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/dlist_test.Po +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +CFLAGS = @CFLAGS@ +DIST_SOURCES = $(dlist_test_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(dlist_test_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu test/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \ + $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ + rm -f $(DESTDIR)$(bindir)/$$f; \ + done + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) +dlist_test$(EXEEXT): $(dlist_test_OBJECTS) $(dlist_test_DEPENDENCIES) + @rm -f dlist_test$(EXEEXT) + $(LINK) $(dlist_test_LDFLAGS) $(dlist_test_OBJECTS) $(dlist_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dlist_test.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.c.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< + +.c.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `cygpath -w $<` +CCDEPMODE = @CCDEPMODE@ +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) + +installdirs: + $(mkinstalldirs) $(DESTDIR)$(bindir) + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-binPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic distclean distclean-compile distclean-depend \ + distclean-generic distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-binPROGRAMS install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic tags uninstall uninstall-am \ + uninstall-binPROGRAMS uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/test/dlist_test.c b/test/dlist_test.c new file mode 100644 index 0000000..787df80 --- /dev/null +++ b/test/dlist_test.c @@ -0,0 +1,273 @@ +/* + * dlist_test.c + * + * Copyright (C) 2003 Eric J Bohm + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + + +/* Double linked list implementation tester. + */ +#include "dlist.h" +#include <stdio.h> +#include <string.h> +// create some dlists put nodes in and out +// use dump +// try list with del_func and without +// use insert, unshift, push +// use pop push mark +// use prev next + +typedef struct simple { + char label[80]; + int number; +} Simple; + + +typedef struct complex { + int cnumber; + Simple *sthing; +} Complex; + +void complex_silly_multiply_by_two( void *a); +int complex_equal(void *a, void *b); +int complex_less(void *a, void *b); +int complex_greater(void *a, void *b); +void simple_dump(Dlist *); +void simple_dump_rev(Dlist *); +void complex_dump(Dlist *); +void complex_out(void *); +void complex_del(void *); +Complex *complex_maker(int,int,char *); + +Simple *simple_maker(int ,char *); + +int main (int argc,char *argv[]) +{ + Dlist *list; + Simple *s1,*s2,*s3,*stemp; + Complex *c1,*c2,*c3, *ctemp, *cfound; + while(1) + { + s1=simple_maker(1,"one"); + s2=simple_maker(2,"two"); + s3=simple_maker(3,"three"); + if((list=dlist_new(sizeof(Simple)))==NULL) + { + fprintf(stderr,"ERR dlist_new fail\n"); + return(2); + } + dlist_push(list,s1); + dlist_push(list,s2); + dlist_push(list,s3); + printf("count is %ld\n",list->count); + simple_dump(list); + simple_dump_rev(list); + stemp=dlist_pop(list); + printf("popped %s\n",stemp->label); + simple_dump(list); + printf("pushed\n"); + dlist_push(list,s3); + simple_dump(list); + stemp=dlist_shift(list); + printf("shifted %s\n",stemp->label); + simple_dump(list); + printf("unshifted\n"); + dlist_unshift(list,stemp); + simple_dump(list); + dlist_destroy(list); + c1=complex_maker(1,1,"one"); + c2=complex_maker(2,2,"two"); + c3=complex_maker(3,3,"three"); + if((list=dlist_new_with_delete(sizeof(Complex),complex_del))==NULL) + { + fprintf(stderr,"ERR dlist_new fail\n"); + return(2); + } + if(dlist_insert_sorted(list,c1,complex_less)==NULL) + { + fprintf(stderr,"ERR dlist_insert fail\n"); + return(2); + } + printf("sorted insert 1\n"); + if(dlist_insert_sorted(list,c3,complex_less)==NULL) + { + fprintf(stderr,"ERR dlist_insert fail\n"); + return(2); + } + if(dlist_insert_sorted(list,c2,complex_less)==NULL) + { + fprintf(stderr,"ERR dlist_insert fail\n"); + return(2); + } + printf("sorted insert 2\n"); + printf("ascending sorted output\n"); + complex_dump(list); + dlist_transform(list,complex_silly_multiply_by_two); + printf("transform multi by 2 output\n"); + complex_dump(list); + ctemp=complex_maker(6,6,"three"); + if((cfound=(Complex *) dlist_find_custom(list,ctemp,complex_equal))!=NULL) + + { + printf("found %d as %d in list\n",ctemp->cnumber,cfound->cnumber); + } else { + printf("ERROR find failed on %d \n",ctemp->cnumber); + return(3); + } + complex_del(ctemp); + dlist_destroy(list); + c1=complex_maker(1,1,"one"); + c2=complex_maker(2,2,"two"); + c3=complex_maker(3,3,"three"); + if((list=dlist_new_with_delete(sizeof(Complex),complex_del))==NULL) + { + fprintf(stderr,"ERR dlist_new fail\n"); + return(2); + } + if(dlist_insert_sorted(list,c1,complex_greater)==NULL) + { + fprintf(stderr,"ERR dlist_insert fail\n"); + return(2); + } + printf("greater sorted insert 1\n"); + if(dlist_insert_sorted(list,c3,complex_greater)==NULL) + { + fprintf(stderr,"ERR dlist_insert fail\n"); + return(2); + } + printf("greater sorted insert 3\n"); + if(dlist_insert_sorted(list,c2,complex_greater)==NULL) + { + fprintf(stderr,"ERR dlist_insert fail\n"); + return(2); + } + printf("greater sorted insert 2\n"); + printf("descending sorted output using transform\n"); + dlist_transform(list,complex_out); + dlist_destroy(list); + } + return(0); +} + +void simple_dump (Dlist *list) +{ + Simple *thisone; + printf("count %ld \n",list->count); + dlist_for_each_data(list,thisone,Simple) + { + printf("label %s number %d \n",thisone->label,thisone->number); + } + +} +void simple_dump_rev (Dlist *list) +{ + Simple *thisone; + printf("rev count %ld \n",list->count); + dlist_for_each_data_rev(list,thisone,Simple) + { + printf("label %s number %d \n",thisone->label,thisone->number); + } +} + +Simple * simple_maker(int snumber,char *label) +{ + Simple *stemp; + if((stemp=malloc(sizeof(Simple)))==NULL) + { + fprintf(stderr,"ERR malloc fail\n"); + return(NULL); + } + stemp->number=snumber; + strcpy(stemp->label,label); + return(stemp); +} + +Complex * complex_maker(int cnumber, int snumber, char* label) +{ + Complex *ctemp; + if((ctemp=malloc(sizeof(Complex)))==NULL) + { + fprintf(stderr,"ERR malloc fail\n"); + return(NULL); + } + ctemp->cnumber=cnumber; + ctemp->sthing=simple_maker(snumber,label); + return(ctemp); +} + +void complex_out(void *data) +{ + Complex *thisone=(Complex *)data; + printf("cnumber %d label %s number %d \n",thisone->cnumber,thisone->sthing->label,thisone->sthing->number); +} + +/** + * return 1 if a==b, else 0 + */ +int complex_equal(void *a, void *b) +{ + if((((Complex *)a)->cnumber==((Complex *)b)->cnumber) + && (((Complex *)a)->sthing->number== + ((Complex *)b)->sthing->number) + && strcmp(((Complex *)a)->sthing->label, + ((Complex *)b)->sthing->label)==0) + return(1); + return(0); +} + +/** for sorting + * return 1 if a<b, else 0 + */ +int complex_less(void *a, void *b) +{ + return( ((Complex *)a)->cnumber < ((Complex *)b)->cnumber ); +} + +/** for sorting + * return 1 if a>b, else 0 + */ +int complex_greater(void *a, void *b) +{ + return( ((Complex *)a)->cnumber > ((Complex *)b)->cnumber ); +} + +void complex_silly_multiply_by_two( void *a) +{ + ((Complex *)a)->cnumber=((Complex *)a)->cnumber*2; + ((Complex *)a)->sthing->number=((Complex *)a)->sthing->number*2; +} + +void complex_dump (Dlist *list) +{ + Complex *thisone; + dlist_start(list); + printf("count %ld \n",list->count); + dlist_for_each_data(list,thisone,Complex) + { + printf("cnumber %d label %s number %d \n",thisone->cnumber,thisone->sthing->label,thisone->sthing->number); + } + +} + +void complex_del (void *item) +{ + Complex *corpse=item; + printf("freeing complex\n"); + free(corpse->sthing); + free(corpse); +} |