summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormananth <mananth>2003-08-29 10:22:34 +0000
committermananth <mananth>2003-08-29 10:22:34 +0000
commitd842e8ef5b56187ff4fc4dcec5269fe137c8fc74 (patch)
tree995919c525e92d012bd8859d92613450f95a22bc
parent20585df476dda252c5c31f80b977c41461a8a4b4 (diff)
downloadsysfsutils-d842e8ef5b56187ff4fc4dcec5269fe137c8fc74.tar.gz
Integrated Eric J Bohm's dlist stuff
Modified library to use dlists Added few "find" functions
-rw-r--r--CREDITS3
-rw-r--r--ChangeLog9
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in2
-rw-r--r--cmd/lsbus.c100
-rw-r--r--cmd/systool.c144
-rwxr-xr-xconfigure3
-rw-r--r--configure.ac3
-rw-r--r--include/dlist.h195
-rw-r--r--include/libsysfs.h136
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/Makefile.in7
-rw-r--r--lib/dlist.c343
-rw-r--r--lib/sysfs_bus.c353
-rw-r--r--lib/sysfs_class.c94
-rw-r--r--lib/sysfs_device.c82
-rw-r--r--lib/sysfs_dir.c350
-rw-r--r--lib/sysfs_driver.c12
-rw-r--r--lib/sysfs_utils.c19
-rw-r--r--test/Makefile.am4
-rw-r--r--test/Makefile.in316
-rw-r--r--test/dlist_test.c273
22 files changed, 1947 insertions, 505 deletions
diff --git a/CREDITS b/CREDITS
index bcd0e38..7d95c13 100644
--- a/CREDITS
+++ b/CREDITS
@@ -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.
diff --git a/ChangeLog b/ChangeLog
index 10c0e53..48f19c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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;
diff --git a/configure b/configure
index 31dc60c..7f8d80e 100755
--- a/configure
+++ b/configure
@@ -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);
+}