chiark / gitweb /
[PATCH] big libsysfs diet (pre 2.0 version)
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>
Wed, 23 Feb 2005 11:21:39 +0000 (12:21 +0100)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 06:36:13 +0000 (23:36 -0700)
Makefile
libsysfs/sysfs.h
libsysfs/sysfs/libsysfs.h
libsysfs/sysfs_class.c
libsysfs/sysfs_device.c
libsysfs/sysfs_dir.c
libsysfs/sysfs_driver.c
libsysfs/sysfs_utils.c
udevinfo.8
udevinfo.c

index d696b8ea3bda6e1f7c012a786f543337500d6922..c2d35f7734f0ac9762599e005b46bcb965c5769b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -129,7 +129,6 @@ HEADERS = \
        list.h
 
 SYSFS_OBJS = \
-       libsysfs/sysfs_bus.o    \
        libsysfs/sysfs_class.o  \
        libsysfs/sysfs_device.o \
        libsysfs/sysfs_dir.o    \
index 1e58e8abb4a7c52930a87a8905cd875815523a80..30bd9b408991dd432a91598c23f5baa9674ceea3 100644 (file)
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#include <ctype.h>
 #include <mntent.h>
 #include <dirent.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
 
-/* external library functions */
-extern int isascii(int c);
+#define safestrcpy(to, from)   strncpy(to, from, sizeof(to)-1)
+#define safestrcat(to, from)   strncat(to, from, sizeof(to) - strlen(to)-1)
+
+#define safestrcpymax(to, from, max) \
+do { \
+       to[max-1] = '\0'; \
+       strncpy(to, from, max-1); \
+} while (0)
+
+#define safestrcatmax(to, from, max) \
+do { \
+       to[max-1] = '\0'; \
+       strncat(to, from, max - strlen(to)-1); \
+} while (0)
+
+extern struct sysfs_attribute *get_attribute(void *dev, const char *name);
+extern struct dlist *read_dir_subdirs(const char *path);
+extern struct dlist *read_dir_links(const char *path);
+extern struct dlist *get_attributes_list(void *dev);
 
 /* Debugging */
 #ifdef DEBUG
 #include "../logging.h"
-#define dprintf(format, arg...) dbg(format, ##arg)
+#define dprintf(format, arg...) dbg(format, ## arg)
 #else
 #define dprintf(format, arg...) do { } while (0)
 #endif
index 29194f61a60ff340a5b68a0b6fb53642cd8aa33c..6140c3aecbca2de8b7493b8a93ebc937930ea7f2 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Header Definitions for libsysfs
  *
- * Copyright (C) IBM Corp. 2003
+ * Copyright (C) IBM Corp. 2004-2005
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 #include <string.h>
 #include "dlist.h"
 
-/* 
- * Defines to prevent buffer overruns
- */
-#define safestrcpy(to, from)   strncpy(to, from, sizeof(to)-1)
-#define safestrcat(to, from)   strncat(to, from, sizeof(to) - strlen(to)-1)
-
-#define safestrcpymax(to, from, max) \
-do { \
-       to[max-1] = '\0'; \
-       strncpy(to, from, max-1); \
-} while (0)
-
-#define safestrcatmax(to, from, max) \
-do { \
-       to[max-1] = '\0'; \
-       strncat(to, from, max - strlen(to)-1); \
-} while (0)
-
-/*
- * Generic #defines go here..
- */ 
 #define SYSFS_FSTYPE_NAME      "sysfs"
 #define SYSFS_PROC_MNTS                "/proc/mounts"
 #define SYSFS_BUS_NAME         "bus"
@@ -55,106 +34,92 @@ do { \
 #define SYSFS_BLOCK_NAME       "block"
 #define SYSFS_DEVICES_NAME     "devices"
 #define SYSFS_DRIVERS_NAME     "drivers"
+#define SYSFS_MODULE_NAME      "module"
 #define SYSFS_NAME_ATTRIBUTE   "name"
 #define SYSFS_UNKNOWN          "unknown"
 #define SYSFS_PATH_ENV         "SYSFS_PATH"
 
-#define SYSFS_PATH_MAX         255
-#define        SYSFS_NAME_LEN          50
-#define SYSFS_BUS_ID_SIZE      20
+#define SYSFS_PATH_MAX         256
+#define        SYSFS_NAME_LEN          64
+#define SYSFS_BUS_ID_SIZE      32
 
-#define SYSFS_METHOD_SHOW      0x01    /* attr can be read by user */
-#define SYSFS_METHOD_STORE     0x02    /* attr can be changed by user */
+enum sysfs_attribute_method {
+       SYSFS_METHOD_SHOW =     0x01,   /* attr can be read by user */
+       SYSFS_METHOD_STORE =    0x02,   /* attr can be changed by user */
+};
+
+/* NOTE: statically define mnt path for sysfs */
+#define SYSFS_MNT_PATH         "/sys"
 
 /*
- * NOTE: We have the statically allocated "name" as the first element of all 
+ * NOTE: 
+ * 1. We have the statically allocated "name" as the first element of all 
  * the structures. This feature is used in the "sorter" function for dlists
+ * 2. As is the case with attrlist
+ * 3. As is the case with path
  */
-
 struct sysfs_attribute {
        char name[SYSFS_NAME_LEN];
        char path[SYSFS_PATH_MAX];
        char *value;
-       unsigned short len;             /* value length */
-       unsigned short method;          /* show and store */
-};
-
-struct sysfs_link {
-       char name[SYSFS_NAME_LEN];
-       char path[SYSFS_PATH_MAX];
-       char target[SYSFS_PATH_MAX];
-};
-
-struct sysfs_directory {
-       char name[SYSFS_NAME_LEN];
-       char path[SYSFS_PATH_MAX];
-
-       /* Private: for internal use only */
-       struct dlist *subdirs;  
-       struct dlist *links;            
-       struct dlist *attributes;
+       unsigned short len;                     /* value length */
+       enum sysfs_attribute_method method;     /* show and store */
 };
 
 struct sysfs_driver {
        char name[SYSFS_NAME_LEN];
        char path[SYSFS_PATH_MAX];
+       struct dlist *attrlist;
+       char bus[SYSFS_NAME_LEN];
 
        /* Private: for internal use only */
        struct dlist *devices;
-       struct sysfs_directory *directory;      
 };
 
 struct sysfs_device {
        char name[SYSFS_NAME_LEN];
+       char path[SYSFS_PATH_MAX];
+       struct dlist *attrlist;
        char bus_id[SYSFS_NAME_LEN];
        char bus[SYSFS_NAME_LEN];
        char driver_name[SYSFS_NAME_LEN];
-       char path[SYSFS_PATH_MAX];
 
        /* Private: for internal use only */
        struct sysfs_device *parent;            
+       /* NOTE - we still don't populate this */
        struct dlist *children; 
-       struct sysfs_directory *directory;      
-};
-
-struct sysfs_root_device {
-       char name[SYSFS_NAME_LEN];
-       char path[SYSFS_PATH_MAX];
-
-       /* Private: for internal use only */
-       struct dlist *devices;
-       struct sysfs_directory *directory;
 };
 
+/* NOTE: not used as of now */
 struct sysfs_bus {
        char name[SYSFS_NAME_LEN];
        char path[SYSFS_PATH_MAX];
+       struct dlist *attrlist;
 
        /* Private: for internal use only */
        struct dlist *drivers;
        struct dlist *devices;
-       struct sysfs_directory *directory;      
 };
 
 struct sysfs_class_device {
        char name[SYSFS_NAME_LEN];
-       char classname[SYSFS_NAME_LEN];
        char path[SYSFS_PATH_MAX];
+       struct dlist *attrlist;
+       char classname[SYSFS_NAME_LEN];
 
        /* Private: for internal use only */
        struct sysfs_class_device *parent;      
        struct sysfs_device *sysdevice;         /* NULL if virtual */
-       struct sysfs_driver *driver;            /* NULL if not implemented */
-       struct sysfs_directory *directory;      
 };
 
+/* NOTE: not used as of now */
 struct sysfs_class {
        char name[SYSFS_NAME_LEN];
        char path[SYSFS_PATH_MAX];
+       struct dlist *attrlist;
 
        /* Private: for internal use only */
        struct dlist *devices;
-       struct sysfs_directory *directory;      
 };
 
 #ifdef __cplusplus
@@ -171,43 +136,15 @@ extern int sysfs_path_is_dir(const char *path);
 extern int sysfs_path_is_link(const char *path);
 extern int sysfs_path_is_file(const char *path);
 extern int sysfs_get_link(const char *path, char *target, size_t len);
-extern struct dlist *sysfs_open_subsystem_list(char *name);
-extern struct dlist *sysfs_open_bus_devices_list(char *name);
+extern struct dlist *sysfs_open_directory_list(const char *path);
 extern void sysfs_close_list(struct dlist *list);
 
 /* 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 int sysfs_read_attribute(struct sysfs_attribute *sysattr);
-extern int sysfs_read_attribute_value(const char *attrpath, 
-               char *value, size_t vsize);
 extern int sysfs_write_attribute(struct sysfs_attribute *sysattr,
                const char *new_value, size_t len);
-extern char *sysfs_get_value_from_attributes(struct dlist *attr, 
-               const char *name);
-extern int sysfs_refresh_dir_attributes(struct sysfs_directory *sysdir);
-extern int sysfs_refresh_dir_links(struct sysfs_directory *sysdir);
-extern int sysfs_refresh_dir_subdirs(struct sysfs_directory *sysdir);
-extern void sysfs_close_directory(struct sysfs_directory *sysdir);
-extern struct sysfs_directory *sysfs_open_directory(const char *path);
-extern int sysfs_read_dir_attributes(struct sysfs_directory *sysdir);
-extern int sysfs_read_dir_links(struct sysfs_directory *sysdir);
-extern int sysfs_read_dir_subdirs(struct sysfs_directory *sysdir);
-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, 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_get_directory_link
-       (struct sysfs_directory *dir, char *linkname);
-extern struct sysfs_link *sysfs_get_subdirectory_link
-       (struct sysfs_directory *dir, char *linkname);
-extern struct sysfs_attribute *sysfs_get_directory_attribute
-       (struct sysfs_directory *dir, char *attrname);
-extern struct dlist *sysfs_get_dir_attributes(struct sysfs_directory *dir);
-extern struct dlist *sysfs_get_dir_links(struct sysfs_directory *dir);
-extern struct dlist *sysfs_get_dir_subdirs(struct sysfs_directory *dir);
 
 /* sysfs driver access */
 extern void sysfs_close_driver(struct sysfs_driver *driver);
@@ -218,19 +155,8 @@ extern struct sysfs_attribute *sysfs_get_driver_attr
        (struct sysfs_driver *drv, const char *name);
 extern struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *driver);
 extern struct dlist *sysfs_get_driver_devices(struct sysfs_driver *driver);
-extern struct dlist *sysfs_refresh_driver_devices(struct sysfs_driver *driver);
-extern struct dlist *sysfs_get_driver_links(struct sysfs_driver *driver);
-extern struct sysfs_device *sysfs_get_driver_device
-       (struct sysfs_driver *driver, const char *name);
-extern struct dlist *sysfs_refresh_driver_attributes
-       (struct sysfs_driver *driver);
-extern struct sysfs_attribute *sysfs_open_driver_attr
-       (const char *bus, const char *drv, const char *attrib);
 
 /* generic sysfs device access */
-extern void sysfs_close_root_device(struct sysfs_root_device *root);
-extern struct sysfs_root_device *sysfs_open_root_device(const char *name);
-extern struct dlist *sysfs_get_root_devices(struct sysfs_root_device *root);
 extern void sysfs_close_device_tree(struct sysfs_device *device);
 extern struct sysfs_device *sysfs_open_device_tree(const char *path);
 extern void sysfs_close_device(struct sysfs_device *dev);
@@ -241,27 +167,8 @@ extern struct sysfs_device *sysfs_open_device_path(const char *path);
 extern int sysfs_get_device_bus(struct sysfs_device *dev);
 extern struct sysfs_attribute *sysfs_get_device_attr
        (struct sysfs_device *dev, const char *name);
-extern struct dlist *sysfs_get_device_attributes(struct sysfs_device *device);
-extern struct dlist *sysfs_refresh_device_attributes
-       (struct sysfs_device *device);
-extern struct sysfs_attribute *sysfs_open_device_attr(const char *bus, 
-               const char *bus_id, const char *attrib);
-
-/* 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_device *sysfs_get_bus_device(struct sysfs_bus *bus, 
-               char *id);
-extern struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus,
-               char *drvname);
-extern struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus);
-extern struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus);
-extern struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus);
-extern struct dlist *sysfs_refresh_bus_attributes(struct sysfs_bus *bus);
-extern struct sysfs_attribute *sysfs_get_bus_attribute
-       (struct sysfs_bus *bus, char *attrname);
-extern int sysfs_find_driver_bus(const char *driver, char *busname, 
-               size_t bsize);
+extern struct dlist *sysfs_get_device_attributes
+       (struct sysfs_device *dev);
 
 /* generic sysfs class access */
 extern void sysfs_close_class_device(struct sysfs_class_device *dev);
@@ -269,26 +176,14 @@ extern struct sysfs_class_device *sysfs_open_class_device_path
        (const char *path);
 extern struct sysfs_class_device *sysfs_open_class_device
        (const char *classname, const char *name);
-extern struct sysfs_device *sysfs_get_classdev_device
-       (struct sysfs_class_device *clsdev);
-extern struct sysfs_driver *sysfs_get_classdev_driver
-       (struct sysfs_class_device *clsdev);
 extern struct sysfs_class_device *sysfs_get_classdev_parent
        (struct sysfs_class_device *clsdev);
-extern void sysfs_close_class(struct sysfs_class *cls);
-extern struct sysfs_class *sysfs_open_class(const char *name);
-extern struct dlist *sysfs_get_class_devices(struct sysfs_class *cls);
-extern struct sysfs_class_device *sysfs_get_class_device
-       (struct sysfs_class *cls, char *name);
-extern struct dlist *sysfs_get_classdev_attributes
-       (struct sysfs_class_device *cdev);
-extern struct dlist *sysfs_refresh_classdev_attributes
-       (struct sysfs_class_device *cdev);
 extern struct sysfs_attribute *sysfs_get_classdev_attr
        (struct sysfs_class_device *clsdev, const char *name);
-extern struct sysfs_attribute *sysfs_open_classdev_attr
-       (const char *classname, const char *dev, 
-                                               const char *attrib); 
+extern struct dlist *sysfs_get_classdev_attributes
+       (struct sysfs_class_device *clsdev);
+extern struct sysfs_device *sysfs_get_classdev_device
+       (struct sysfs_class_device *clsdev);
 
 /**
  * sort_list: sorter function to keep list elements sorted in alphabetical 
index 4ea7f41c99c293410482acfed888498e47f79d27..a93de573d43b4b083db00f40537ba0c73b96a36a 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Generic class utility functions for libsysfs
  *
- * Copyright (C) IBM Corp. 2003
+ * Copyright (C) IBM Corp. 2003-2005
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 #include "libsysfs.h"
 #include "sysfs.h"
 
-static void sysfs_close_cls_dev(void *dev)
-{
-       sysfs_close_class_device((struct sysfs_class_device *)dev);
-}
-
-/**
- * class_name_equal: compares class_devices' name
- * @a: class_name looking for
- * @b: sysfs_class_device being compared
- */
-static int class_name_equal(void *a, void *b)
-{
-       if (a == NULL || b == NULL)
-               return 0;
-
-       if (strcmp(((char *)a), ((struct sysfs_class_device *)b)->name) == 0)
-               return 1;
-
-       return 0;
-}
-
 /**
  * sysfs_close_class_device: closes a single class device.
  * @dev: class device to close.
  */
 void sysfs_close_class_device(struct sysfs_class_device *dev)
 {
-       if (dev != NULL) {
-               if (dev->directory != NULL)
-                       sysfs_close_directory(dev->directory);
-               if (dev->sysdevice != NULL)
-                       sysfs_close_device(dev->sysdevice);
-               if (dev->driver != NULL)
-                       sysfs_close_driver(dev->driver);
-               if (dev->parent != NULL)
+       if (dev) {
+               if (dev->parent)
                        sysfs_close_class_device(dev->parent);
+               if (dev->sysdevice)
+                       sysfs_close_device(dev->sysdevice);
+               if (dev->attrlist)
+                       dlist_destroy(dev->attrlist);
                free(dev);
        }
 }
 
-/**
- * sysfs_close_class: close single class
- * @cls: class structure
- */
-void sysfs_close_class(struct sysfs_class *cls)
-{
-       if (cls != NULL) {
-               if (cls->directory != NULL)
-                       sysfs_close_directory(cls->directory);
-               if (cls->devices != NULL) 
-                       dlist_destroy(cls->devices);
-               free(cls);
-       }
-}
-
 /**
  * alloc_class_device: mallocs and initializes new class device struct.
  * returns sysfs_class_device or NULL.
  */
 static struct sysfs_class_device *alloc_class_device(void)
 {
-       return (struct sysfs_class_device *)
-                               calloc(1, sizeof(struct sysfs_class_device));
-}
+       struct sysfs_class_device *dev;
 
-/**
- * alloc_class: mallocs new class structure
- * returns sysfs_class struct or NULL
- */
-static struct sysfs_class *alloc_class(void)
-{
-       return (struct sysfs_class *)calloc(1, sizeof(struct sysfs_class));
+       dev = calloc(1, sizeof(struct sysfs_class_device));
+       return dev;
 }
 
-/** 
+/**
  * set_classdev_classname: Grabs classname from path
  * @cdev: class device to set
  * Returns nothing
  */
 static void set_classdev_classname(struct sysfs_class_device *cdev)
 {
-       char *c = NULL, *e = NULL;
+       char *c, *e;
        int count = 0;
 
        c = strstr(cdev->path, SYSFS_CLASS_NAME);
        if (c == NULL) {
                c = strstr(cdev->path, SYSFS_BLOCK_NAME);
        } else {
-               c = strchr(c, '/');
+               c = strstr(c, "/");
        }
 
        if (c == NULL)
@@ -135,9 +90,9 @@ static void set_classdev_classname(struct sysfs_class_device *cdev)
  */
 struct sysfs_class_device *sysfs_open_class_device_path(const char *path)
 {
-       struct sysfs_class_device *cdev = NULL;
+       struct sysfs_class_device *cdev;
 
-       if (path == NULL) {
+       if (!path) {
                errno = EINVAL;
                return NULL;
        }
@@ -146,11 +101,11 @@ struct sysfs_class_device *sysfs_open_class_device_path(const char *path)
                return NULL;
        }
        cdev = alloc_class_device();
-       if (cdev == NULL) {
+       if (!cdev) {
                dprintf("calloc failed\n");
                return NULL;
        }
-       if ((sysfs_get_name_from_path(path, cdev->name, SYSFS_NAME_LEN)) != 0) {
+       if (sysfs_get_name_from_path(path, cdev->name, SYSFS_NAME_LEN)) {
                errno = EINVAL;
                dprintf("Error getting class device name\n");
                sysfs_close_class_device(cdev);
@@ -168,245 +123,6 @@ struct sysfs_class_device *sysfs_open_class_device_path(const char *path)
        return cdev;
 }
 
-/**
- * sysfs_get_class_devices: gets all devices for class
- * @cls: class to get devices for
- * returns dlist of class_devices with success and NULL with error
- */
-struct dlist *sysfs_get_class_devices(struct sysfs_class *cls)
-{
-       struct sysfs_class_device *dev = NULL;
-       struct sysfs_directory *cur = NULL;
-
-       if (cls == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (cls->devices != NULL) 
-               return cls->devices;
-
-       if (cls->directory == NULL) {
-               cls->directory = sysfs_open_directory(cls->path);
-               if (cls->directory == NULL) 
-                       return NULL;
-       }
-
-       if ((sysfs_read_dir_subdirs(cls->directory)) != 0) 
-               return NULL;
-
-       if (cls->directory->subdirs != NULL) {
-               dlist_for_each_data(cls->directory->subdirs, cur, 
-                                               struct sysfs_directory) {
-                       dev = sysfs_open_class_device_path(cur->path);
-                       if (dev == NULL) {
-                               dprintf("Error opening device at %s\n", 
-                                                               cur->path);
-                               continue;
-                       }
-                       if (cls->devices == NULL)
-                               cls->devices = dlist_new_with_delete
-                                       (sizeof(struct sysfs_class_device),
-                                                       sysfs_close_cls_dev);
-                       dlist_unshift_sorted(cls->devices, dev, sort_list);
-               }
-       }
-       return cls->devices;
-}
-
-/**
- * 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 *cls = NULL;
-       char classpath[SYSFS_PATH_MAX];
-
-       if (name == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       memset(classpath, 0, SYSFS_PATH_MAX);
-        if ((sysfs_get_mnt_path(classpath, SYSFS_PATH_MAX)) != 0) {
-                dprintf("Sysfs not supported on this system\n");
-                return NULL;
-        }
-
-       /* 
-        * We shall now treat "block" also as a class. Hence, check here
-        * if "name" is "block" and proceed accordingly
-        */
-       if (strcmp(name, SYSFS_BLOCK_NAME) == 0) {
-               safestrcat(classpath, "/");
-               safestrcat(classpath, SYSFS_BLOCK_NAME);
-       } else {
-               safestrcat(classpath, "/");
-               safestrcat(classpath, SYSFS_CLASS_NAME);
-               safestrcat(classpath, "/");
-               safestrcat(classpath, name);
-       }
-       if ((sysfs_path_is_dir(classpath)) != 0) {
-               dprintf("Class %s not found on the system\n", name);
-               return NULL;
-       }
-
-       cls = alloc_class();
-       if (cls == NULL) {
-               dprintf("calloc failed\n");
-               return NULL;
-       }
-       safestrcpy(cls->name, name);    
-       safestrcpy(cls->path, classpath);
-       if ((sysfs_remove_trailing_slash(cls->path)) != 0) {
-               dprintf("Invalid path to class device %s\n", cls->path);
-               sysfs_close_class(cls);
-               return NULL;
-       }
-       
-       return cls;
-}
-
-/**
- * sysfs_get_class_device: Get specific class device using the device's id
- * @class: class to find device on
- * @name: class name of the device
- */ 
-struct sysfs_class_device *sysfs_get_class_device(struct sysfs_class *cls,
-                                       char *name)
-{
-       if (cls == NULL || name == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (cls->devices == NULL) {
-               cls->devices = sysfs_get_class_devices(cls);
-               if (cls->devices == NULL) 
-                       return NULL;
-       }
-       return (struct sysfs_class_device *)dlist_find_custom(cls->devices,
-                       name, class_name_equal);
-}
-
-/**
- * sysfs_get_classdev_device: returns the sysfs_device corresponding to
- *             sysfs_class_device, if present
- * @clsdev: class device whose sysfs_device is required
- * Returns sysfs_device on success, NULL on error or if device is not
- * implemented
- */ 
-struct sysfs_device *sysfs_get_classdev_device
-                       (struct sysfs_class_device *clsdev)
-{
-       struct sysfs_link *devlink = NULL;
-       char devpath[SYSFS_PATH_MAX];
-       
-       if (clsdev == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-       safestrcpy(devpath, clsdev->path);
-       safestrcat(devpath, "/device");
-       if ((sysfs_path_is_link(devpath)) != 0) {
-               if (clsdev->sysdevice != NULL) {
-                       sysfs_close_device(clsdev->sysdevice);
-                       clsdev->sysdevice = NULL;
-               }
-               return NULL;
-       }
-       
-       if (clsdev->directory == NULL) {
-               clsdev->directory = sysfs_open_directory(clsdev->path);
-               if (clsdev->directory == NULL)
-                       return NULL;
-       }
-       devlink = sysfs_get_directory_link(clsdev->directory, "device");
-       if (devlink == NULL) {
-               if (clsdev->sysdevice != NULL) {
-                       dprintf("Device link no longer exists\n");
-                       sysfs_close_device(clsdev->sysdevice);
-                       clsdev->sysdevice = NULL;
-               }
-               return NULL;
-       }
-
-       if (clsdev->sysdevice != NULL) {
-               if (!strncmp(devlink->target, clsdev->sysdevice->path,
-                                               SYSFS_PATH_MAX)) 
-                       /* sysdevice hasn't changed */
-                       return (clsdev->sysdevice);
-               else 
-                       /* come here only if the device link for has changed */
-                       sysfs_close_device(clsdev->sysdevice);
-       }
-
-       clsdev->sysdevice = sysfs_open_device_path(devlink->target);
-       if (clsdev->sysdevice == NULL)
-               return NULL;
-
-       return (clsdev->sysdevice);
-}
-                               
-/**
- * sysfs_get_classdev_driver: returns the sysfs_driver corresponding to
- *             sysfs_class_device, if present
- * @clsdev: class device whose sysfs_device is required
- * Returns sysfs_driver on success, NULL on error or if driver is not
- * implemented
- */ 
-struct sysfs_driver *sysfs_get_classdev_driver
-                       (struct sysfs_class_device *clsdev)
-{
-       struct sysfs_link *drvlink = NULL;
-       char drvpath[SYSFS_PATH_MAX];
-       
-       if (clsdev == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-       safestrcpy(drvpath, clsdev->path);
-       safestrcat(drvpath, "/driver");
-       if ((sysfs_path_is_link(drvpath)) != 0) {
-               if (clsdev->driver != NULL) {
-                       sysfs_close_driver(clsdev->driver);
-                       clsdev->driver = NULL;
-               }
-               return NULL;
-       }
-        
-       if (clsdev->directory == NULL) {
-               clsdev->directory = sysfs_open_directory(clsdev->path);
-               if (clsdev->directory == NULL)
-                       return NULL;
-       }
-       drvlink = sysfs_get_directory_link(clsdev->directory, "driver");
-       if (drvlink == NULL) {
-               if (clsdev->driver != NULL) {
-                       dprintf("Driver link no longer exists\n");
-                       sysfs_close_driver(clsdev->driver);
-                       clsdev->driver = NULL;
-               }
-               return NULL;
-       }
-       if (clsdev->driver != NULL) {
-               if (!strncmp(drvlink->target, clsdev->driver->path,
-                                                       SYSFS_PATH_MAX))
-                       /* driver hasn't changed */
-                       return (clsdev->driver);
-               else
-                       /* come here only if the device link for has changed */
-                       sysfs_close_driver(clsdev->driver);
-       }
-               
-       clsdev->driver = sysfs_open_driver_path(drvlink->target);
-       if (clsdev->driver == NULL)
-               return NULL;
-
-       return (clsdev->driver);
-}
-
 /** 
  * get_blockdev_parent: Get the parent class device for a "block" subsystem 
  *             device if present
@@ -415,7 +131,8 @@ struct sysfs_driver *sysfs_get_classdev_driver
  */
 static int get_blockdev_parent(struct sysfs_class_device *clsdev)
 {
-       char parent_path[SYSFS_PATH_MAX], *c = NULL;
+       char parent_path[SYSFS_PATH_MAX];
+       char *c;
 
        safestrcpy(parent_path, clsdev->path);
        c = strstr(parent_path, SYSFS_BLOCK_NAME);
@@ -430,20 +147,20 @@ static int get_blockdev_parent(struct sysfs_class_device *clsdev)
        else
                goto errout;
 
-       /* validate whether the given class device is a partition or not */
-        if ((strncmp(c, clsdev->name, strlen(clsdev->name))) == 0) {
-                dprintf("%s not a partition\n", clsdev->name);
-                return 1;
-        }
-                     
-       c = strchr(c, '/');
+       /* validate whether the given class device is a partition or not */
+       if ((strncmp(c, clsdev->name, strlen(clsdev->name))) == 0) {
+               dprintf("%s not a partition\n", clsdev->name);
+               return 1;
+       }
+
+       c = strchr(c, '/');
        if (c == NULL)
                goto errout;
 
        *c = '\0';
-                                       
+
        clsdev->parent = sysfs_open_class_device_path(parent_path);
-       if (clsdev->parent == NULL) {
+       if (!clsdev->parent) {
                dprintf("Error opening the parent class device at %s\n", 
                                                                parent_path);
                return 1;
@@ -466,19 +183,19 @@ errout:
 struct sysfs_class_device *sysfs_get_classdev_parent
                                (struct sysfs_class_device *clsdev)
 {
-       if (clsdev == NULL) {
+       if (!clsdev) {
                errno = EINVAL;
                return NULL;
        }
-       if (clsdev->parent != NULL)
+       if (clsdev->parent)
                return (clsdev->parent);
-       
-       /* 
+
+       /*
         * As of now, only block devices have a parent child heirarchy in sysfs
         * We do not know, if, in the future, more classes will have a similar
         * structure. Hence, we now call a specialized function for block and
         * later we can add support functions for other subsystems as required.
-        */ 
+        */
        if (!(strncmp(clsdev->classname, SYSFS_BLOCK_NAME, 
                                        sizeof(SYSFS_BLOCK_NAME)))) {
                if ((get_blockdev_parent(clsdev)) == 0) 
@@ -499,13 +216,13 @@ struct sysfs_class_device *sysfs_get_classdev_parent
 static int get_classdev_path(const char *classname, const char *clsdev, 
                char *path, size_t len)
 {
-       if (classname == NULL || clsdev == NULL || path == NULL) {
+       if (!classname || !clsdev || !path) {
                errno = EINVAL;
                return -1;
        }
-        if (sysfs_get_mnt_path(path, len) != 0) {
-                dprintf("Error getting sysfs mount path\n");
-                return -1;
+       if (sysfs_get_mnt_path(path, len) != 0) {
+               dprintf("Error getting sysfs mount path\n");
+               return -1;
        }
        if (strncmp(classname, SYSFS_BLOCK_NAME,
                                sizeof(SYSFS_BLOCK_NAME)) == 0) {
@@ -535,9 +252,9 @@ struct sysfs_class_device *sysfs_open_class_device
                (const char *classname, const char *name)
 {
        char devpath[SYSFS_PATH_MAX];
-       struct sysfs_class_device *cdev = NULL;
+       struct sysfs_class_device *cdev;
 
-       if (classname == NULL || name == NULL) {
+       if (!classname || !name) {
                errno = EINVAL;
                return NULL;
        }
@@ -549,9 +266,9 @@ struct sysfs_class_device *sysfs_open_class_device
                                                        name, classname);
                return NULL;
        }
-       
+
        cdev = sysfs_open_class_device_path(devpath);
-       if (cdev == NULL) {
+       if (!cdev) {
                dprintf("Error getting class device %s from class %s\n",
                                name, classname);
                return NULL;
@@ -559,57 +276,6 @@ struct sysfs_class_device *sysfs_open_class_device
        return cdev;
 }
 
-/**
- * sysfs_get_classdev_attributes: returns a dlist of attributes for
- *     the requested class_device
- * @cdev: sysfs_class_dev for which attributes are needed
- * returns a dlist of attributes if exists, NULL otherwise
- */
-struct dlist *sysfs_get_classdev_attributes(struct sysfs_class_device *cdev)
-{
-       if (cdev == NULL)
-               return NULL;
-
-       if (cdev->directory == NULL) {
-               cdev->directory = sysfs_open_directory(cdev->path);
-               if (cdev->directory == NULL) 
-                       return NULL;
-       }
-       if (cdev->directory->attributes == NULL) {
-               if ((sysfs_read_dir_attributes(cdev->directory)) != 0) 
-                       return NULL;
-       }
-       return (cdev->directory->attributes);
-}
-
-/**
- * sysfs_refresh_clsassdev_attributes: refreshes the driver's list of attributes
- * @clsdev: sysfs_class_device whose attributes to refresh
- *
- * NOTE: Upon return, prior references to sysfs_attributes for this classdev
- *              _may_ not be valid
- *
- * Returns list of attributes on success and NULL on failure
- */
-struct dlist *sysfs_refresh_classdev_attributes
-                       (struct sysfs_class_device *clsdev)
-{
-       if (clsdev == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (clsdev->directory == NULL)
-               return (sysfs_get_classdev_attributes(clsdev));
-
-       if ((sysfs_refresh_dir_attributes(clsdev->directory)) != 0) {
-               dprintf("Error refreshing class_device attributes\n");
-               return NULL;
-       }
-
-       return (clsdev->directory->attributes);
-}
-
 /**
  * sysfs_get_classdev_attr: searches class device's attributes by name
  * @clsdev: class device to look through
@@ -619,90 +285,53 @@ struct dlist *sysfs_refresh_classdev_attributes
 struct sysfs_attribute *sysfs_get_classdev_attr
                (struct sysfs_class_device *clsdev, const char *name)
 {
-       struct sysfs_attribute *cur = NULL;
-       struct sysfs_directory *sdir = NULL;
-       struct dlist *attrlist = NULL;
-       
-       if (clsdev == NULL || name == NULL) {
+       if (!clsdev || !name) {
                errno = EINVAL;
                return NULL;
        }
-       
-       /* 
-        * First, see if it's in the current directory. Then look at 
-        * subdirs since class devices can have subdirs of attributes.
-        */ 
-       attrlist = sysfs_get_classdev_attributes(clsdev);
-       if (attrlist != NULL) {
-               cur = sysfs_get_directory_attribute(clsdev->directory,
-                                               (char *)name);
-               if (cur != NULL)
-                       return cur;
-       }
+       return get_attribute(clsdev, (char *)name);
+}
 
-       if (clsdev->directory == NULL)
+/**
+ * sysfs_get_classdev_attributes: gets list of classdev attributes
+ * @clsdev: class device whose attributes list is needed
+ * returns dlist of attributes on success or NULL on error
+ */
+struct dlist *sysfs_get_classdev_attributes(struct sysfs_class_device *clsdev)
+{
+       if (!clsdev) {
+               errno = EINVAL;
                return NULL;
-
-       if (clsdev->directory->subdirs == NULL) 
-               if ((sysfs_read_dir_subdirs(clsdev->directory)) != 0 ||
-                   clsdev->directory->subdirs == NULL) 
-                       return NULL;
-
-       if (clsdev->directory->subdirs != NULL) {
-               dlist_for_each_data(clsdev->directory->subdirs, sdir,
-                                               struct sysfs_directory) {
-                       if ((sysfs_path_is_dir(sdir->path)) != 0) 
-                               continue;
-                       cur = sysfs_get_directory_attribute(sdir,
-                                                       (char *)name);
-                       if (cur == NULL)
-                               continue;
-               }
        }
-       return cur;
+       return get_attributes_list(clsdev);
 }
 
 /**
- * sysfs_open_classdev_attr: read an attribute for a given class device
- * @classname: name of the class on which to look
- * @dev: class device name for which the attribute has to be read
- * @attrib: attribute to read
- * Returns sysfs_attribute * on SUCCESS and NULL on error
- * 
- * NOTE:
- *     A call to sysfs_close_attribute() is required to close the
- *     attribute returned and to free memory
+ * sysfs_get_classdev_device: gets the sysfs_device associated with the
+ *     given sysfs_class_device
+ * @clsdev: class device whose associated sysfs_device is needed
+ * returns struct sysfs_device * on success or NULL on error
  */
-struct sysfs_attribute *sysfs_open_classdev_attr(const char *classname,
-               const char *dev, const char *attrib)
+struct sysfs_device *sysfs_get_classdev_device
+               (struct sysfs_class_device *clsdev)
 {
-       struct sysfs_attribute *attribute = NULL;
-       char path[SYSFS_PATH_MAX];
+       char linkpath[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX];
 
-       if (classname == NULL || dev == NULL || attrib == NULL) {
+       if (!clsdev) {
                errno = EINVAL;
                return NULL;
        }
-       memset(path, 0, SYSFS_PATH_MAX);
-       if ((get_classdev_path(classname, dev, path, SYSFS_PATH_MAX)) != 0) {
-               dprintf("Error getting to device %s on class %s\n",
-                                               dev, classname);
-               return NULL;
-       }
-       safestrcat(path, "/");
-       safestrcat(path, attrib);
-       attribute = sysfs_open_attribute(path);
-       if (attribute == NULL) {
-               dprintf("Error opening attribute %s on class device %s\n",
-                               attrib, dev);
-               return NULL;
-       }
-       if ((sysfs_read_attribute(attribute)) != 0) {
-               dprintf("Error reading attribute %s for class device %s\n",
-                               attrib, dev);
-               sysfs_close_attribute(attribute);
-               return NULL;
+
+       if (clsdev->sysdevice)
+               return clsdev->sysdevice;
+
+       memset(linkpath, 0, SYSFS_PATH_MAX);
+       safestrcpy(linkpath, clsdev->path);
+       safestrcat(linkpath, "/device");
+       if (!sysfs_path_is_link(linkpath)) {
+               memset(devpath, 0, SYSFS_PATH_MAX);
+               if (!sysfs_get_link(linkpath, devpath, SYSFS_PATH_MAX))
+                       clsdev->sysdevice = sysfs_open_device_path(devpath);
        }
-       return attribute;
+       return clsdev->sysdevice;
 }
-
index 83c3adc080cd3b81ffc29a13c03392660659fd51..7087730d5f16d7a830c658d3ef22be8b44dd9c77 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Generic device utility functions for libsysfs
  *
- * Copyright (C) IBM Corp. 2003
+ * Copyright (C) IBM Corp. 2003-2005
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 #include "sysfs.h"
 
 /**
- * get_dev_driver: fills in the dev->driver_name field, but searches by
- *     opening subsystem. Only to be used if no driver link exists in
- *     device directory.
- *
- * Returns 0 on SUCCESS and 1 on error
+ * get_dev_driver: fills in the dev->driver_name field 
+ * Returns 0 on SUCCESS and -1 on error
  */
 static int get_dev_driver(struct sysfs_device *dev)
 {
-       struct dlist *drvlist = NULL;
-       char path[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX];
-       char *drv = NULL, *c = NULL;
-       
-       if (dev == NULL) {
+       struct dlist *drvlist;
+       char path[SYSFS_PATH_MAX];
+       char devpath[SYSFS_PATH_MAX];
+       char *drv = NULL, *c;
+
+       if (!dev) {
                errno = EINVAL;
-               return 1;
+               return -1;
+       }
+
+       memset(path, 0, SYSFS_PATH_MAX);
+       memset(devpath, 0, SYSFS_PATH_MAX);
+       safestrcpymax(path, dev->path, SYSFS_PATH_MAX);
+       safestrcatmax(path, "/driver", SYSFS_PATH_MAX);
+       if (!sysfs_path_is_link(path)) {
+               if (!sysfs_get_link(path, devpath, SYSFS_PATH_MAX)) {
+                       if (sysfs_get_name_from_path(devpath, 
+                                       dev->driver_name, SYSFS_NAME_LEN))
+                               return -1;
+               }
+               return 0;
        }
+
+       /*
+        * Devices on on earlier kernels do not have the "driver" link.
+        * Look it up in the bus directory.
+        */
        if (dev->bus[0] == '\0')
-               return 1;
+               return -1;
        memset(path, 0, SYSFS_PATH_MAX);
        memset(devpath, 0, SYSFS_PATH_MAX);
-       safestrcpy(path, SYSFS_BUS_NAME);
+       safestrcpy(path, dev->path);
+       c = strstr(path, SYSFS_DEVICES_NAME);
+       if (c == NULL) {
+               dprintf("Invalid path to device - %s\n", dev->path);
+               return -1;
+       } else
+               *c = '\0';
+       safestrcat(path, SYSFS_BUS_NAME);
        safestrcat(path, "/");
        safestrcat(path, dev->bus);
        safestrcat(path, "/");
        safestrcat(path, SYSFS_DRIVERS_NAME);
 
-       safestrcpy(devpath, dev->path);
-       c = strstr(devpath, SYSFS_DEVICES_NAME);
-       if (c == NULL)
-               return 1;
-       *c = '\0';
-       safestrcatmax(c, path, (sizeof(devpath) - strlen(devpath)));
-
-       drvlist = sysfs_open_subsystem_list(path);
-       if (drvlist != NULL) {
+       drvlist = sysfs_open_directory_list(path);
+       if (drvlist) {
                dlist_for_each_data(drvlist, drv, char) {
-                       safestrcpy(path, devpath);
-                       safestrcat(path, "/");
-                       safestrcat(path, drv);
-                       safestrcat(path, "/");
-                       safestrcat(path, dev->bus_id);
-                       if (sysfs_path_is_link(path) == 0) {
+                       safestrcpy(devpath, path);
+                       safestrcat(devpath, "/");
+                       safestrcat(devpath, drv);
+                       safestrcat(devpath, "/");
+                       safestrcat(devpath, dev->bus_id);
+                       if (sysfs_path_is_link(devpath) == 0) {
                                safestrcpy(dev->driver_name, drv);
                                sysfs_close_list(drvlist);
                                return 0;
@@ -73,35 +89,9 @@ static int get_dev_driver(struct sysfs_device *dev)
                }
                sysfs_close_list(drvlist);
        }
-       return 1;
+       return -1;
 }
 
-/*
- * get_device_driver_name: gets device's driver name, searches for driver
- *     link first before going the brute force route.
- * @dev: device to retrieve driver
- * returns 0 with success and 1 with error
- */
-static int get_device_driver_name(struct sysfs_device *dev)
-{
-       char devpath[SYSFS_PATH_MAX], drvpath[SYSFS_PATH_MAX];
-
-       if (dev == NULL) {
-               errno = EINVAL;
-               return 1;
-       }
-       memset(devpath, 0, SYSFS_PATH_MAX);
-       memset(drvpath, 0, SYSFS_PATH_MAX);
-       safestrcpy(devpath, dev->path);
-       safestrcat(devpath, "/driver");
-
-       if ((sysfs_get_link(devpath, drvpath, SYSFS_PATH_MAX)) != 0) 
-               return(get_dev_driver(dev));
-
-       return (sysfs_get_name_from_path(drvpath, dev->driver_name, 
-               SYSFS_NAME_LEN));
-}
-       
 /**
  * sysfs_get_device_bus: retrieves the bus name the device is on, checks path 
  *     to bus' link to make sure it has correct device.
@@ -110,31 +100,49 @@ static int get_device_driver_name(struct sysfs_device *dev)
  */
 int sysfs_get_device_bus(struct sysfs_device *dev)
 {
-       char subsys[SYSFS_NAME_LEN], path[SYSFS_PATH_MAX];
-       char target[SYSFS_PATH_MAX], *bus = NULL, *c = NULL;
-       struct dlist *buslist = NULL;
+       char devpath[SYSFS_PATH_MAX];
+       char subsys[SYSFS_NAME_LEN];
+       char path[SYSFS_PATH_MAX];
+       char target[SYSFS_PATH_MAX];
+       char *bus = NULL, *c;
+       struct dlist *buslist;
 
-       if (dev == NULL) {
+       if (!dev) {
                errno = EINVAL;
                return -1;
        }
 
+       memset(path, 0, SYSFS_PATH_MAX);
+       memset(devpath, 0, SYSFS_PATH_MAX);
+       safestrcpymax(path, dev->path, SYSFS_PATH_MAX);
+       safestrcatmax(path, "/bus", SYSFS_PATH_MAX);
+       if (!sysfs_path_is_link(path)) {
+               if (!sysfs_get_link(path, devpath, SYSFS_PATH_MAX)) {
+                       if (sysfs_get_name_from_path(devpath, 
+                                       dev->bus, SYSFS_NAME_LEN))
+                               return -1;
+               }
+               return 0;
+       }
+
+       /*
+        * Devices on on earlier kernels do not have the "bus" link.
+        * Look it up in the bus directory.
+        */
        memset(subsys, 0, SYSFS_NAME_LEN);
-       safestrcpy(subsys, SYSFS_BUS_NAME);  /* subsys = bus */
-       buslist = sysfs_open_subsystem_list(subsys);
-       if (buslist != NULL) {
+       safestrcpy(subsys, dev->path);
+       c = strstr(subsys, SYSFS_DEVICES_NAME);
+       if (c == NULL) {
+               dprintf("Invalid path to device - %s\n", dev->path);
+               return -1;
+       } else 
+               *c = '\0';
+       safestrcat(subsys, SYSFS_BUS_NAME);
+       buslist = sysfs_open_directory_list(subsys);
+       if (buslist) {
                dlist_for_each_data(buslist, bus, char) {
                        memset(path, 0, SYSFS_PATH_MAX);
-                       safestrcpy(path, dev->path);
-                       c = strstr(path, "/devices");
-                       if (c == NULL) {
-                               dprintf("Invalid path to device %s\n", path);
-                               sysfs_close_list(buslist);
-                               return -1;
-                       }
-                       *c = '\0';
-                       safestrcat(path, "/");
-                       safestrcat(path, SYSFS_BUS_NAME);
+                       safestrcpy(path, subsys);
                        safestrcat(path, "/");
                        safestrcat(path, bus);
                        safestrcat(path, "/");
@@ -143,8 +151,8 @@ int sysfs_get_device_bus(struct sysfs_device *dev)
                        safestrcat(path, dev->bus_id);
                        if ((sysfs_path_is_link(path)) == 0) {
                                memset(target, 0, SYSFS_PATH_MAX);
-                               if ((sysfs_get_link(path, target, 
-                                               SYSFS_PATH_MAX)) != 0) {
+                               if (sysfs_get_link(path, target, 
+                                               SYSFS_PATH_MAX)) {
                                        dprintf("Error getting link target\n");
                                        sysfs_close_list(buslist);
                                        return -1;
@@ -156,10 +164,10 @@ int sysfs_get_device_bus(struct sysfs_device *dev)
                                        return 0;
                                }
                        }
-                }
-                sysfs_close_list(buslist);
-        }
-        return -1;
+               }
+               sysfs_close_list(buslist);
+       }
+       return -1;
 }
 
 /**
@@ -169,8 +177,8 @@ int sysfs_get_device_bus(struct sysfs_device *dev)
  */
 void sysfs_close_device_tree(struct sysfs_device *devroot)
 {
-       if (devroot != NULL) {
-               if (devroot->children != NULL) {
+       if (devroot) {
+               if (devroot->children) {
                        struct sysfs_device *child = NULL;
 
                        dlist_for_each_data(devroot->children, child,
@@ -182,27 +190,19 @@ void sysfs_close_device_tree(struct sysfs_device *devroot)
        }
 }
 
-/**
- * sysfs_close_dev_tree: routine for dlist integration
- */
-static void sysfs_close_dev_tree(void *dev)
-{
-       sysfs_close_device_tree((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) {
-               if (dev->parent != NULL)
+       if (dev) {
+               if (dev->parent)
                        sysfs_close_device(dev->parent);
-               if (dev->directory != NULL)
-                       sysfs_close_directory(dev->directory);
-               if (dev->children != NULL && dev->children->count == 0)
+               if (dev->children && dev->children->count)
                        dlist_destroy(dev->children);
+               if (dev->attrlist)
+                       dlist_destroy(dev->attrlist);
                free(dev);
        }
 }
@@ -213,36 +213,7 @@ void sysfs_close_device(struct sysfs_device *dev)
  */
 static struct sysfs_device *alloc_device(void)
 {
-       return (struct sysfs_device *)calloc(1, sizeof(struct sysfs_device));
-}
-
-/**
- * open_device_dir: opens up sysfs_directory for specific root dev
- * @name: name of root
- * returns struct sysfs_directory with success and NULL with error
- */
-static struct sysfs_directory *open_device_dir(const char *path)
-{
-       struct sysfs_directory *rdir = NULL;
-
-       if (path == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       rdir = sysfs_open_directory(path);
-       if (rdir == NULL) {
-               errno = EINVAL;
-               dprintf ("Device %s not supported on this system\n", path);
-               return NULL;
-       }
-       if ((sysfs_read_dir_subdirs(rdir)) != 0) {
-               dprintf ("Error reading device at dir %s\n", path);
-               sysfs_close_directory(rdir);
-               return NULL;
-       }
-       
-       return rdir;
+       return (struct sysfs_device *) calloc(1, sizeof(struct sysfs_device));
 }
 
 /**
@@ -252,45 +223,44 @@ static struct sysfs_directory *open_device_dir(const char *path)
  */
 struct sysfs_device *sysfs_open_device_path(const char *path)
 {
-       struct sysfs_device *dev = NULL;
+       struct sysfs_device *dev;
 
-       if (path == NULL) {
+       if (!path) {
                errno = EINVAL;
                return NULL;
        }
-       if ((sysfs_path_is_dir(path)) != 0) {
+       if (sysfs_path_is_dir(path)) {
                dprintf("Incorrect path to device: %s\n", path);
                return NULL;
        }
-       dev = alloc_device();   
-       if (dev == NULL) {
+       dev = alloc_device();
+       if (!dev) {
                dprintf("Error allocating device at %s\n", path);
                return NULL;
        }
-       if ((sysfs_get_name_from_path(path, dev->bus_id, 
-                                       SYSFS_NAME_LEN)) != 0) {
+       if (sysfs_get_name_from_path(path, dev->bus_id, SYSFS_NAME_LEN)) {
                errno = EINVAL;
                dprintf("Error getting device bus_id\n");
                sysfs_close_device(dev);
                return NULL;
        }
        safestrcpy(dev->path, path);
-       if ((sysfs_remove_trailing_slash(dev->path)) != 0) {
+       if (sysfs_remove_trailing_slash(dev->path)) {
                dprintf("Invalid path to device %s\n", dev->path);
                sysfs_close_device(dev);
                return NULL;
        }
-       /* 
+       /*
         * The "name" attribute no longer exists... return the device's
         * sysfs representation instead, in the "dev->name" field, which
         * implies that the dev->name and dev->bus_id contain same data.
         */
        safestrcpy(dev->name, dev->bus_id);
-       
-       if (sysfs_get_device_bus(dev) != 0)
+
+       if (sysfs_get_device_bus(dev))
                dprintf("Could not get device bus\n");
-       
-       if (get_device_driver_name(dev) != 0) {
+
+       if (get_dev_driver(dev)) {
                dprintf("Could not get device %s's driver\n", dev->bus_id);
                safestrcpy(dev->driver_name, SYSFS_UNKNOWN);
        }
@@ -299,227 +269,33 @@ struct sysfs_device *sysfs_open_device_path(const char *path)
 }
 
 /**
- * sysfs_open_device_tree: opens root device and all of its children,
- *     creating a tree of devices. Only opens children.
- * @path: sysfs path to devices
- * returns struct sysfs_device and its children with success or NULL with
- *     error.
- */
-struct sysfs_device *sysfs_open_device_tree(const char *path)
-{
-       struct sysfs_device *rootdev = NULL, *new = NULL;
-       struct sysfs_directory *cur = NULL;
-
-       if (path == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-       rootdev = sysfs_open_device_path(path);
-       if (rootdev == NULL) {
-               dprintf("Error opening root device at %s\n", path);
-               return NULL;
-       }
-       if (rootdev->directory == NULL) {
-               rootdev->directory = open_device_dir(rootdev->path);
-               if (rootdev->directory == NULL) 
-                       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_close_dev_tree);
-                       dlist_unshift_sorted(rootdev->children, 
-                                                       new, sort_list);
-               }
-       }
-
-       return rootdev;
-}
-
-/**
- * sysfs_close_root_device: closes root and all devices
- * @root: root device to close
- */
-void sysfs_close_root_device(struct sysfs_root_device *root)
-{
-       if (root != NULL) {
-               if (root->devices != NULL)
-                       dlist_destroy(root->devices);
-               if (root->directory != NULL)
-                       sysfs_close_directory(root->directory);
-               free(root);
-       }
-}
-
-/**
- * sysfs_get_root_devices: opens up all the devices under this root device
- * @root: root device to open devices for
- * returns dlist of devices with success and NULL with error
- */
-struct dlist *sysfs_get_root_devices(struct sysfs_root_device *root)
-{
-       struct sysfs_device *dev = NULL;
-       struct sysfs_directory *cur = NULL;
-
-       if (root == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-       if (root->directory == NULL) {
-               root->directory = open_device_dir(root->path);
-               if (root->directory == NULL)
-                       return NULL;
-       }
-               
-       if (root->directory->subdirs == NULL)
-               return 0;
-
-       dlist_for_each_data(root->directory->subdirs, cur,
-                       struct sysfs_directory) {
-               dev = sysfs_open_device_tree(cur->path);
-               if (dev == NULL) {
-                       dprintf ("Error opening device at %s\n", cur->path);
-                       continue;
-               }
-               if (root->devices == NULL)
-                       root->devices = dlist_new_with_delete
-                               (sizeof(struct sysfs_device), 
-                               sysfs_close_dev_tree);
-               dlist_unshift_sorted(root->devices, dev, sort_list);
-       }
-
-       return root->devices;
-}
-
-/**
- * sysfs_open_root_device: opens sysfs devices root and all of its
- *     devices.
- * @name: name of /sys/devices/root to open
- * returns struct sysfs_root_device if success and NULL with error
- */
-struct sysfs_root_device *sysfs_open_root_device(const char *name)
-{
-       struct sysfs_root_device *root = NULL;
-       char rootpath[SYSFS_PATH_MAX];
-
-       if (name == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       memset(rootpath, 0, SYSFS_PATH_MAX);
-       if (sysfs_get_mnt_path(rootpath, SYSFS_PATH_MAX) != 0) {
-               dprintf ("Sysfs not supported on this system\n");
-               return NULL;
-       }
-
-       safestrcat(rootpath, "/");
-       safestrcat(rootpath, SYSFS_DEVICES_NAME);
-       safestrcat(rootpath, "/");
-       safestrcat(rootpath, name);
-       if ((sysfs_path_is_dir(rootpath)) != 0) {
-               errno = EINVAL;
-               dprintf("Invalid root device: %s\n", name);
-               return NULL;
-       }
-       root = (struct sysfs_root_device *)calloc
-                                       (1, sizeof(struct sysfs_root_device));
-       if (root == NULL) {
-               dprintf("calloc failure\n");
-               return NULL;
-       }
-       safestrcpy(root->name, name);
-       safestrcpy(root->path, rootpath);
-       if ((sysfs_remove_trailing_slash(root->path)) != 0) {
-               dprintf("Invalid path to root device %s\n", root->path);
-               sysfs_close_root_device(root);
-               return NULL;
-       }
-       return root;
-}
-
-/**
- * sysfs_get_device_attributes: returns a dlist of attributes corresponding to
- *     the specific device
- * @device: struct sysfs_device * for which attributes are to be returned
- */
-struct dlist *sysfs_get_device_attributes(struct sysfs_device *device)
-{
-       if (device == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (device->directory == NULL) {
-               device->directory = sysfs_open_directory(device->path);
-               if (device->directory == NULL) 
-                       return NULL;
-       }
-       if (device->directory->attributes == NULL) {
-               if ((sysfs_read_dir_attributes(device->directory)) != 0)
-                       return NULL;
-       }
-       return (device->directory->attributes);
-}
-
-/**
- * sysfs_refresh_device_attributes: refreshes the device's list of attributes
- * @device: sysfs_device whose attributes to refresh
- *  
- * NOTE: Upon return, prior references to sysfs_attributes for this device
- *             _may_ not be valid
- *
- * Returns list of attributes on success and NULL on failure
+ * sysfs_get_device_attr: searches dev's attributes by name
+ * @dev: device to look through
+ * @name: attribute name to get
+ * returns sysfs_attribute reference with success or NULL with error.
  */
-struct dlist *sysfs_refresh_device_attributes(struct sysfs_device *device)
+struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev,
+                                               const char *name)
 {
-       if (device == NULL) {
+       if (!dev || !name) {
                errno = EINVAL;
                return NULL;
        }
-
-       if (device->directory == NULL)
-               return (sysfs_get_device_attributes(device));
-
-       if ((sysfs_refresh_dir_attributes(device->directory)) != 0) {
-               dprintf("Error refreshing device attributes\n");
-               return NULL;
-       }
-
-       return (device->directory->attributes);
+       return get_attribute(dev, (char *)name);
 }
 
 /**
- * sysfs_get_device_attr: searches dev's attributes by name
- * @dev: device to look through
- * @name: attribute name to get
- * returns sysfs_attribute reference with success or NULL with error.
+ * sysfs_get_device_attributes: gets list of device attributes
+ * @dev: device whose attributes list is needed
+ * returns dlist of attributes on success or NULL on error
  */
-struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev,
-                                               const char *name)
+struct dlist *sysfs_get_device_attributes(struct sysfs_device *dev)
 {
-       struct dlist *attrlist = NULL;
-
-       if (dev == NULL || name == NULL) {
+       if (!dev) {
                errno = EINVAL;
                return NULL;
        }
-       
-       attrlist = sysfs_get_device_attributes(dev);
-       if (attrlist == NULL)
-               return NULL;
-
-       return sysfs_get_directory_attribute(dev->directory, (char *)name);
+       return get_attributes_list(dev);
 }
 
 /**
@@ -535,13 +311,13 @@ static int get_device_absolute_path(const char *device,   const char *bus,
 {
        char bus_path[SYSFS_PATH_MAX];
 
-       if (device == NULL || path == NULL) {
+       if (!device || !path) {
                errno = EINVAL;
                return -1;
        }
 
        memset(bus_path, 0, SYSFS_PATH_MAX);
-       if (sysfs_get_mnt_path(bus_path, SYSFS_PATH_MAX) != 0) {
+       if (sysfs_get_mnt_path(bus_path, SYSFS_PATH_MAX)) {
                dprintf ("Sysfs not supported on this system\n");
                return -1;
        }
@@ -557,7 +333,7 @@ static int get_device_absolute_path(const char *device,     const char *bus,
         * We now are at /sys/bus/"bus_name"/devices/"device" which is a link.
         * Now read this link to reach to the device.
         */ 
-       if ((sysfs_get_link(bus_path, path, psize)) != 0) {
+       if (sysfs_get_link(bus_path, path, psize)) {
                dprintf("Error getting to device %s\n", device);
                return -1;
        }
@@ -578,21 +354,21 @@ static int get_device_absolute_path(const char *device,   const char *bus,
 struct sysfs_device *sysfs_open_device(const char *bus,        const char *bus_id)
 {
        char sysfs_path[SYSFS_PATH_MAX];
-       struct sysfs_device *device = NULL;
+       struct sysfs_device *device;
 
-       if (bus_id == NULL || bus == NULL) {
+       if (!bus_id || !bus) {
                errno = EINVAL;
                return NULL;
        }
        memset(sysfs_path, 0, SYSFS_PATH_MAX);
-       if ((get_device_absolute_path(bus_id, bus, sysfs_path, 
-                                               SYSFS_PATH_MAX)) != 0) {
+       if (get_device_absolute_path(bus_id, bus, sysfs_path, 
+                               SYSFS_PATH_MAX)) {
                dprintf("Error getting to device %s\n", bus_id);
                return NULL;
        }
        
        device = sysfs_open_device_path(sysfs_path);
-       if (device == NULL) {
+       if (!device) {
                dprintf("Error opening device %s\n", bus_id);
                return NULL;
        }
@@ -608,20 +384,20 @@ struct sysfs_device *sysfs_open_device(const char *bus,   const char *bus_id)
  */
 struct sysfs_device *sysfs_get_device_parent(struct sysfs_device *dev)
 {
-       char ppath[SYSFS_PATH_MAX], *tmp = NULL;
+       char ppath[SYSFS_PATH_MAX], *tmp;
 
-       if (dev == NULL) {
+       if (!dev) {
                errno = EINVAL;
                return NULL;
        }
 
-       if (dev->parent != NULL)
+       if (dev->parent)
                return (dev->parent);
 
        memset(ppath, 0, SYSFS_PATH_MAX);
        safestrcpy(ppath, dev->path);
        tmp = strrchr(ppath, '/');
-       if (tmp == NULL) {
+       if (!tmp) {
                dprintf("Invalid path to device %s\n", ppath);
                return NULL;
        }
@@ -634,68 +410,22 @@ struct sysfs_device *sysfs_get_device_parent(struct sysfs_device *dev)
                }
        }
        *tmp = '\0';
-       
+
        /*
         * All "devices" have the "detach_state" attribute - validate here
         */
        safestrcat(ppath, "/detach_state");
-       if ((sysfs_path_is_file(ppath)) != 0) {
+       if (sysfs_path_is_file(ppath)) {
                dprintf("Device at %s does not have a parent\n", dev->path);
                return NULL;
        }
        tmp = strrchr(ppath, '/');
        *tmp = '\0';
        dev->parent = sysfs_open_device_path(ppath);
-       if (dev->parent == NULL) {
+       if (!dev->parent) {
                dprintf("Error opening device %s's parent at %s\n", 
                                        dev->bus_id, ppath);
                return NULL;
        }
        return (dev->parent);
 }
-
-/*
- * sysfs_open_device_attr: open the given device's attribute
- * @bus: Bus on which to look
- * @dev_id: device for which attribute is required
- * @attrname: name of the attribute to look for
- * Returns struct sysfs_attribute on success and NULL on failure
- * 
- * NOTE:
- *     A call to sysfs_close_attribute() is required to close
- *     the attribute returned and free memory. 
- */
-struct sysfs_attribute *sysfs_open_device_attr(const char *bus,
-               const char *bus_id, const char *attrib)
-{
-       struct sysfs_attribute *attribute = NULL;
-       char devpath[SYSFS_PATH_MAX];
-       
-       if (bus == NULL || bus_id == NULL || attrib == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       memset(devpath, 0, SYSFS_PATH_MAX);
-       if ((get_device_absolute_path(bus_id, bus, devpath, 
-                                       SYSFS_PATH_MAX)) != 0) {
-               dprintf("Error getting to device %s\n", bus_id);
-               return NULL;
-       }
-       safestrcat(devpath, "/");
-       safestrcat(devpath, attrib);
-       attribute = sysfs_open_attribute(devpath);
-       if (attribute == NULL) {
-               dprintf("Error opening attribute %s for device %s\n",
-                               attrib, bus_id);
-               return NULL;
-       }
-       if ((sysfs_read_attribute(attribute)) != 0) {
-               dprintf("Error reading attribute %s for device %s\n",
-                               attrib, bus_id);
-               sysfs_close_attribute(attribute);
-               return NULL;
-       }
-       return attribute;
-}
-
index 52769916cc7f3cf83a93aa63cf35dad62ab797fb..c86617934bb47c37a5955e0546f9551fe009c9d1 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Directory utility functions for libsysfs
  *
- * Copyright (C) IBM Corp. 2003
+ * Copyright (C) IBM Corp. 2003-2005
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 #include "libsysfs.h"
 #include "sysfs.h"
 
-/**
- * sysfs_del_attribute: routine for dlist integration
- */
-static void sysfs_del_attribute(void *attr)
+static int sort_char(void *new, void *old)
 {
-        sysfs_close_attribute((struct sysfs_attribute *)attr);
+       return ((strncmp((char *)new, (char *)old, 
+                       strlen((char *)new))) < 0 ? 1 : 0);
 }
 
 /**
- * sysfs_del_link: routine for dlist integration
+ * sysfs_del_name: free function for sysfs_open_subsystem_list
+ * @name: memory area to be freed
  */
-static void sysfs_del_link(void *ln)
+static void sysfs_del_name(void *name)
 {
-        sysfs_close_link((struct sysfs_link *)ln);
+       free(name);
 }
 
 /**
- * sysfs_del_dir: routine for dlist integration
+ * sysfs_del_attribute: routine for dlist integration
  */
-static void sysfs_del_directory(void *dir)
+static void sysfs_del_attribute(void *attr)
 {
-        sysfs_close_directory((struct sysfs_directory *)dir);
+       sysfs_close_attribute((struct sysfs_attribute *)attr);
 }
 
 /**
- * dir_attribute_name_equal: compares dir attributes by name
+ * attr_name_equal: compares 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)
+static int attr_name_equal(void *a, void *b)
 {
-       if (a == NULL || b == NULL)
+       if (!a || !b)
                return 0;
 
        if (strcmp(((char *)a), ((struct sysfs_attribute *)b)->name) == 0)
@@ -64,48 +63,14 @@ static int dir_attribute_name_equal(void *a, void *b)
        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(((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(((char *)a), ((struct sysfs_directory *)b)->name) == 0)
-               return 1;
-
-       return 0;
-}
-
 /**
  * sysfs_close_attribute: closes and cleans up attribute
  * @sysattr: attribute to close.
  */
 void sysfs_close_attribute(struct sysfs_attribute *sysattr)
 {
-       if (sysattr != NULL) {
-               if (sysattr->value != NULL)
+       if (sysattr) {
+               if (sysattr->value)
                        free(sysattr->value);
                free(sysattr);
        }
@@ -130,13 +95,13 @@ struct sysfs_attribute *sysfs_open_attribute(const char *path)
 {
        struct sysfs_attribute *sysattr = NULL;
        struct stat fileinfo;
-       
-       if (path == NULL) {
+
+       if (!path) {
                errno = EINVAL;
                return NULL;
        }
        sysattr = alloc_attribute();
-       if (sysattr == NULL) {
+       if (!sysattr) {
                dprintf("Error allocating attribute at %s\n", path);
                return NULL;
        }
@@ -162,94 +127,6 @@ struct sysfs_attribute *sysfs_open_attribute(const char *path)
        return sysattr;
 }
 
-/**
- * sysfs_write_attribute: write value to the attribute
- * @sysattr: attribute to write
- * @new_value: value to write
- * @len: length of "new_value"
- * returns 0 with success and -1 with error.
- */
-int sysfs_write_attribute(struct sysfs_attribute *sysattr,
-               const char *new_value, size_t len)
-{
-       int fd;
-       int length;
-       
-       if (sysattr == NULL || new_value == NULL || len == 0) {
-               errno = EINVAL;
-               return -1;
-       }
-       
-       if (!(sysattr->method & SYSFS_METHOD_STORE)) {
-               dprintf ("Store method not supported for attribute %s\n",
-                       sysattr->path);
-               errno = EACCES;
-               return -1;
-       }
-       if (sysattr->method & SYSFS_METHOD_SHOW) {
-               /*
-                * read attribute again to see if we can get an updated value 
-                */
-               if ((sysfs_read_attribute(sysattr)) != 0) {
-                       dprintf("Error reading attribute\n");
-                       return -1;
-               }
-               if ((strncmp(sysattr->value, new_value, sysattr->len)) == 0) {
-                       dprintf("Attr %s already has the requested value %s\n",
-                                       sysattr->name, new_value);
-                       return 0;       
-               }
-       }
-       /* 
-        * open O_WRONLY since some attributes have no "read" but only
-        * "write" permission 
-        */ 
-       if ((fd = open(sysattr->path, O_WRONLY)) < 0) {
-               dprintf("Error reading attribute %s\n", sysattr->path);
-               return -1;
-       }
-
-       length = write(fd, new_value, len);
-       if (length < 0) {
-               dprintf("Error writing to the attribute %s - invalid value?\n",
-                       sysattr->name);
-               close(fd);
-               return -1;
-       } else if ((unsigned int)length != len) {
-               dprintf("Could not write %d bytes to attribute %s\n", 
-                                       len, sysattr->name);
-               /* 
-                * since we could not write user supplied number of bytes,
-                * restore the old value if one available
-                */
-               if (sysattr->method & SYSFS_METHOD_SHOW) {
-                       length = write(fd, sysattr->value, sysattr->len);
-                       close(fd);
-                       return -1;
-               }
-       }
-       
-       /*
-        * Validate length that has been copied. Alloc appropriate area
-        * in sysfs_attribute. Verify first if the attribute supports reading
-        * (show method). If it does not, do not bother
-        */ 
-       if (sysattr->method & SYSFS_METHOD_SHOW) {
-               if (length != sysattr->len) {
-                       sysattr->value = (char *)realloc
-                               (sysattr->value, length);
-                       sysattr->len = length;
-                       safestrcpymax(sysattr->value, new_value, length);
-               } else {
-                       /*"length" of the new value is same as old one */ 
-                       safestrcpymax(sysattr->value, new_value, length);
-               }
-       }
-                       
-       close(fd);      
-       return 0;
-}
-
 /**
  * sysfs_read_attribute: reads value from attribute
  * @sysattr: attribute to read
@@ -263,7 +140,7 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr)
        long pgsize = 0;
        int fd;
 
-       if (sysattr == NULL) {
+       if (!sysattr) {
                errno = EINVAL;
                return -1;
        }
@@ -275,7 +152,7 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr)
        }
        pgsize = sysconf(_SC_PAGESIZE);
        fbuf = (char *)calloc(1, pgsize+1);
-       if (fbuf == NULL) {
+       if (!fbuf) {
                dprintf("calloc failed\n");
                return -1;
        }
@@ -303,7 +180,7 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr)
        sysattr->len = length;
        close(fd);
        vbuf = (char *)realloc(fbuf, length+1);
-       if (vbuf == NULL) {
+       if (!vbuf) {
                dprintf("realloc failed\n");
                free(fbuf);
                return -1;
@@ -314,758 +191,301 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr)
 }
 
 /**
- * sysfs_read_attribute_value: given path to attribute, return its value.
- *     values can be up to a pagesize, if buffer is smaller the value will 
- *     be truncated. 
- * @attrpath: sysfs path to attribute
- * @value: buffer to put value
- * @vsize: size of value buffer
+ * sysfs_write_attribute: write value to the attribute
+ * @sysattr: attribute to write
+ * @new_value: value to write
+ * @len: length of "new_value"
  * returns 0 with success and -1 with error.
  */
-int sysfs_read_attribute_value(const char *attrpath, 
-                                       char *value, size_t vsize)
+int sysfs_write_attribute(struct sysfs_attribute *sysattr,
+               const char *new_value, size_t len)
 {
-       struct sysfs_attribute *attr = NULL;
-       size_t length = 0;
+       int fd;
+       int length;
 
-       if (attrpath == NULL || value == NULL || vsize == 0) {
+       if (!sysattr || !new_value || len == 0) {
                errno = EINVAL;
                return -1;
        }
 
-       attr = sysfs_open_attribute(attrpath);
-       if (attr == NULL) {
-               dprintf("Invalid attribute path %s\n", attrpath);
-               errno = EINVAL;
-               return -1;
-       }
-       if((sysfs_read_attribute(attr)) != 0 || attr->value == NULL) {
-               dprintf("Error reading from attribute %s\n", attrpath);
-               sysfs_close_attribute(attr);
+       if (!(sysattr->method & SYSFS_METHOD_STORE)) {
+               dprintf ("Store method not supported for attribute %s\n",
+                       sysattr->path);
+               errno = EACCES;
                return -1;
        }
-       length = strlen(attr->value);
-       if (length > vsize) 
-               dprintf("Value length %d is larger than supplied buffer %d\n",
-                       length, vsize);
-       safestrcpymax(value, attr->value, vsize);
-       sysfs_close_attribute(attr);
-
-       return 0;
-}
-
-/**
- * sysfs_get_value_from_attrbutes: given a linked list of attributes and an 
- *     attribute name, return its value
- * @attr: attribute to search
- * @name: name to look for
- * returns char * value - could be NULL
- */
-char *sysfs_get_value_from_attributes(struct dlist *attr, const char *name)
-{      
-       struct sysfs_attribute *cur = NULL;
-       
-       if (attr == NULL || name == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-       dlist_for_each_data(attr, cur, struct sysfs_attribute) {
-               if (strcmp(cur->name, name) == 0)
-                       return cur->value;
+       if (sysattr->method & SYSFS_METHOD_SHOW) {
+               /*
+                * read attribute again to see if we can get an updated value 
+                */
+               if ((sysfs_read_attribute(sysattr))) {
+                       dprintf("Error reading attribute\n");
+                       return -1;
+               }
+               if ((strncmp(sysattr->value, new_value, sysattr->len)) == 0) {
+                       dprintf("Attr %s already has the requested value %s\n",
+                                       sysattr->name, new_value);
+                       return 0;       
+               }
        }
-       return NULL;
-}
-
-/**
- * sysfs_close_link: closes and cleans up link.
- * @ln: link to close.
- */
-void sysfs_close_link(struct sysfs_link *ln)
-{
-       if (ln != NULL) 
-               free(ln);
-}
-
-/**
- * sysfs_close_directory: closes directory, cleans up attributes and links
- * @sysdir: sysfs_directory to close
- */
-void sysfs_close_directory(struct sysfs_directory *sysdir)
-{
-       if (sysdir != NULL) {
-               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);
-               sysdir = NULL;
+       /*
+        * open O_WRONLY since some attributes have no "read" but only
+        * "write" permission 
+        */
+       if ((fd = open(sysattr->path, O_WRONLY)) < 0) {
+               dprintf("Error reading attribute %s\n", sysattr->path);
+               return -1;
        }
-}
-
-/**
- * alloc_directory: allocates and initializes directory structure
- * returns struct sysfs_directory with success or NULL with error.
- */
-static struct sysfs_directory *alloc_directory(void)
-{
-       return (struct sysfs_directory *)
-                       calloc(1, sizeof(struct sysfs_directory));
-}
-
-/**
- * alloc_link: allocates and initializes link structure
- * returns struct sysfs_link with success or NULL with error.
- */
-static struct sysfs_link *alloc_link(void)
-{
-       return (struct sysfs_link *)calloc(1, sizeof(struct sysfs_link));
-}
-
-/**
- * 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;
-       int retval = 0;
 
-       if (sysdir == NULL) {
-               errno = EINVAL;
+       length = write(fd, new_value, len);
+       if (length < 0) {
+               dprintf("Error writing to the attribute %s - invalid value?\n",
+                       sysattr->name);
+               close(fd);
                return -1;
-       }
-       if (sysdir->subdirs == NULL) 
-               if ((sysfs_read_dir_subdirs(sysdir)) != 0) 
-                       return 0;
-       if (sysdir->subdirs != NULL) {
-               dlist_for_each_data(sysdir->subdirs, cursub, 
-                                               struct sysfs_directory) {
-                       if ((sysfs_read_dir_subdirs(cursub)) != 0) {
-                               dprintf ("Error reading subdirectory %s\n",
-                                               cursub->name);
-                               retval = -1;
-                       }
+       } else if ((unsigned int)length != len) {
+               dprintf("Could not write %d bytes to attribute %s\n", 
+                                       len, sysattr->name);
+               /* 
+                * since we could not write user supplied number of bytes,
+                * restore the old value if one available
+                */
+               if (sysattr->method & SYSFS_METHOD_SHOW) {
+                       length = write(fd, sysattr->value, sysattr->len);
+                       close(fd);
+                       return -1;
                }
        }
-       if (!retval)
-               errno = 0;
-       return retval;
-}
 
-/**
- * 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 *sdir = NULL;
-
-       if (path == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (sysfs_path_is_dir(path) != 0) {
-               dprintf("Invalid path to directory %s\n", path);
-               errno = EINVAL;
-               return NULL;
-       }
-
-       sdir = alloc_directory();
-       if (sdir == NULL) {
-               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;
-       }
-       safestrcpy(sdir->path, path);
-
-       return sdir;
-}
-
-/**
- * sysfs_open_link: opens a sysfs link, creates struct, and returns
- * @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 *ln = NULL;
-
-       if (linkpath == NULL || strlen(linkpath) > SYSFS_PATH_MAX) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       ln = alloc_link();
-       if (ln == NULL) {
-               dprintf("Error allocating link %s\n", linkpath);
-               return NULL;
-       }
-       safestrcpy(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) {
-               sysfs_close_link(ln);
-               errno = EINVAL;
-               dprintf("Invalid link path %s\n", linkpath);
-               return NULL;
+       /*
+        * Validate length that has been copied. Alloc appropriate area
+        * in sysfs_attribute. Verify first if the attribute supports reading
+        * (show method). If it does not, do not bother
+        */ 
+       if (sysattr->method & SYSFS_METHOD_SHOW) {
+               if (length != sysattr->len) {
+                       sysattr->value = (char *)realloc
+                               (sysattr->value, length);
+                       sysattr->len = length;
+                       safestrcpymax(sysattr->value, new_value, length);
+               } else {
+                       /*"length" of the new value is same as old one */ 
+                       safestrcpymax(sysattr->value, new_value, length);
+               }
        }
-
-       return ln;
+                       
+       close(fd);      
+       return 0;
 }
 
 /**
  * add_attribute: open and add attribute at path to given directory
- * @sysdir: directory to add attribute to
+ * @dev: device whose attribute is to be added
  * @path: path to attribute
- * returns 0 with success and -1 with error.
+ * returns pointer to attr added with success and NULL with error.
  */
-static int add_attribute(struct sysfs_directory *sysdir, const char *path)
+static struct sysfs_attribute *add_attribute(void *dev, const char *path)
 {
-       struct sysfs_attribute *attr = NULL;
+       struct sysfs_attribute *attr;
 
        attr = sysfs_open_attribute(path);
-       if (attr == NULL) {
+       if (!attr) {
                dprintf("Error opening attribute %s\n", path);
-               return -1;
+               return NULL;
        }
        if (attr->method & SYSFS_METHOD_SHOW) {
-               if ((sysfs_read_attribute(attr)) != 0) {
+               if (sysfs_read_attribute(attr)) {
                        dprintf("Error reading attribute %s\n", path);
                        sysfs_close_attribute(attr);
-                       return 0;
+                       return NULL;
                }
        }
-                                               
-       if (sysdir->attributes == NULL) {
-               sysdir->attributes = dlist_new_with_delete
-                       (sizeof(struct sysfs_attribute), sysfs_del_attribute);
-       }
-       dlist_unshift_sorted(sysdir->attributes, attr, sort_list);
-
-       return 0;
-}
-
-/**
- * add_subdirectory: open and add subdirectory at path to given directory
- * @sysdir: directory to add subdir to
- * @path: path to subdirectory
- * returns 0 with success and -1 with error.
- */
-static int add_subdirectory(struct sysfs_directory *sysdir, const char *path)
-{
-       struct sysfs_directory *subdir = NULL;
 
-       subdir = sysfs_open_directory(path);
-       if (subdir == NULL) {
-               dprintf("Error opening directory %s\n", path);
-               return -1;
+       if (!((struct sysfs_device *)dev)->attrlist) {
+               ((struct sysfs_device *)dev)->attrlist = dlist_new_with_delete
+                       (sizeof(struct sysfs_attribute), sysfs_del_attribute);
        }
-       if (sysdir->subdirs == NULL)
-               sysdir->subdirs = dlist_new_with_delete
-                       (sizeof(struct sysfs_directory), sysfs_del_directory);
-       dlist_unshift_sorted(sysdir->subdirs, subdir, sort_list);
-       return 0;
-}
+       dlist_unshift_sorted(((struct sysfs_device *)dev)->attrlist, 
+                       attr, sort_list);
 
-/**
- * add_link: open and add link at path to given directory
- * @sysdir: directory to add link to
- * @path: path to link
- * returns 0 with success and -1 with error.
- */
-static int add_link(struct sysfs_directory *sysdir, const char *path)
-{
-       struct sysfs_link *ln = NULL;
-
-       ln = sysfs_open_link(path);
-       if (ln == NULL) {
-               dprintf("Error opening link %s\n", path);
-               return -1;
-       }
-       if (sysdir->links == NULL)
-               sysdir->links = dlist_new_with_delete
-                               (sizeof(struct sysfs_link), sysfs_del_link);
-       dlist_unshift_sorted(sysdir->links, ln, sort_list);
-       return 0;
+       return attr;
 }
 
-/**
- * sysfs_read_dir_attributes: grabs attributes for the given directory
- * @sysdir: sysfs directory to open
- * returns 0 with success and -1 with error.
+/*
+ * get_attribute - given a sysfs_* struct and a name, return the 
+ * sysfs_attribute corresponding to "name"
+ * returns sysfs_attribute on success and NULL on error
  */
-int sysfs_read_dir_attributes(struct sysfs_directory *sysdir)
+struct sysfs_attribute *get_attribute(void *dev, const char *name)
 {
-       DIR *dir = NULL;
-       struct dirent *dirent = NULL;
-       char file_path[SYSFS_PATH_MAX];
-       int retval = 0;
+       struct sysfs_attribute *cur = NULL;
+       char path[SYSFS_PATH_MAX];
 
-       if (sysdir == NULL) {
+       if (!dev || !name) {
                errno = EINVAL;
-               return -1;
-       }
-       dir = opendir(sysdir->path);
-       if (dir == NULL) {
-               dprintf("Error opening directory %s\n", sysdir->path);
-               return -1;
+               return NULL;
        }
-       while(((dirent = readdir(dir)) != NULL) && retval == 0) {
-               if (0 == strcmp(dirent->d_name, "."))
-                        continue;
-               if (0 == strcmp(dirent->d_name, ".."))
-                       continue;
-               memset(file_path, 0, SYSFS_PATH_MAX);
-               safestrcpy(file_path, sysdir->path);
-               safestrcat(file_path, "/");
-               safestrcat(file_path, dirent->d_name);
-               if ((sysfs_path_is_file(file_path)) == 0)
-                       retval = add_attribute(sysdir, file_path);
+
+       if (((struct sysfs_device *)dev)->attrlist) {
+               /* check if attr is already in the list */
+               cur = (struct sysfs_attribute *)dlist_find_custom
+                       ((((struct sysfs_device *)dev)->attrlist), 
+                               (void *)name, attr_name_equal);
+               if (cur)
+                       return cur;
        }
-       closedir(dir);
-       if (!retval)
-               errno = 0;
-       return(retval);
+       safestrcpymax(path, ((struct sysfs_device *)dev)->path, 
+                       SYSFS_PATH_MAX);
+       safestrcatmax(path, "/", SYSFS_PATH_MAX);
+       safestrcatmax(path, name, SYSFS_PATH_MAX);
+       if (!(sysfs_path_is_file(path)))
+               cur = add_attribute((void *)dev, path);
+       return cur;
 }
 
 /**
- * sysfs_read_dir_links: grabs links in a specific directory
- * @sysdir: sysfs directory to read links
- * returns 0 with success and -1 with error.
+ * read_dir_links: grabs links in a specific directory
+ * @sysdir: sysfs directory to read
+ * returns list of link names with success and NULL with error.
  */
-int sysfs_read_dir_links(struct sysfs_directory *sysdir)
+struct dlist *read_dir_links(const char *path)
 {
        DIR *dir = NULL;
        struct dirent *dirent = NULL;
-       char file_path[SYSFS_PATH_MAX];
-       int retval = 0;
+       char file_path[SYSFS_PATH_MAX], *linkname;
+       struct dlist *linklist = NULL;
 
-       if (sysdir == NULL) {
+       if (!path) {
                errno = EINVAL;
-               return -1;
+               return NULL;
        }
-       dir = opendir(sysdir->path);
-       if (dir == NULL) {
-               dprintf("Error opening directory %s\n", sysdir->path);
-               return -1;
+       dir = opendir(path);
+       if (!dir) {
+               dprintf("Error opening directory %s\n", path);
+               return NULL;
        }
-       while(((dirent = readdir(dir)) != NULL) && retval == 0) {
+       while ((dirent = readdir(dir)) != NULL) {
                if (0 == strcmp(dirent->d_name, "."))
                         continue;
                if (0 == strcmp(dirent->d_name, ".."))
                        continue;
                memset(file_path, 0, SYSFS_PATH_MAX);
-               safestrcpy(file_path, sysdir->path);
+               safestrcpy(file_path, path);
                safestrcat(file_path, "/");
                safestrcat(file_path, dirent->d_name);
                if ((sysfs_path_is_link(file_path)) == 0) {
-                       retval = add_link(sysdir, file_path);
-                       if (retval != 0)
-                               break;
+                       if (!linklist) {
+                               linklist = dlist_new_with_delete
+                                       (SYSFS_NAME_LEN, sysfs_del_name);
+                               if (!linklist) {
+                                       dprintf("Error creating list\n");
+                                       return NULL;
+                               }
+                       }
+                       linkname = (char *)calloc(1, SYSFS_NAME_LEN);
+                       safestrcpymax(linkname, dirent->d_name, SYSFS_NAME_LEN);
+                       dlist_unshift_sorted(linklist, linkname, sort_char);
                }
        }
        closedir(dir);
-       if (!retval)
-               errno = 0;
-       return(retval);
+       return linklist;
 }
 
 /**
- * sysfs_read_dir_subdirs: grabs subdirs in a specific directory
- * @sysdir: sysfs directory to read links
- * returns 0 with success and -1 with error.
+ * read_dir_subdirs: grabs subdirs in a specific directory
+ * @sysdir: sysfs directory to read
+ * returns list of directory names with success and NULL with error.
  */
-int sysfs_read_dir_subdirs(struct sysfs_directory *sysdir)
+struct dlist *read_dir_subdirs(const char *path)
 {
        DIR *dir = NULL;
        struct dirent *dirent = NULL;
-       char file_path[SYSFS_PATH_MAX];
-       int retval = 0;
+       char file_path[SYSFS_PATH_MAX], *dir_name;
+       struct dlist *dirlist = NULL;
 
-       if (sysdir == NULL) {
+       if (!path) {
                errno = EINVAL;
-               return -1;
+               return NULL;
        }
-       dir = opendir(sysdir->path);
-       if (dir == NULL) {
-               dprintf("Error opening directory %s\n", sysdir->path);
-               return -1;
+       dir = opendir(path);
+       if (!dir) {
+               dprintf("Error opening directory %s\n", path);
+               return NULL;
        }
-       while(((dirent = readdir(dir)) != NULL) && retval == 0) {
+       while ((dirent = readdir(dir)) != NULL) {
                if (0 == strcmp(dirent->d_name, "."))
                         continue;
                if (0 == strcmp(dirent->d_name, ".."))
                        continue;
                memset(file_path, 0, SYSFS_PATH_MAX);
-               safestrcpy(file_path, sysdir->path);
+               safestrcpy(file_path, path);
                safestrcat(file_path, "/");
                safestrcat(file_path, dirent->d_name);
-               if ((sysfs_path_is_dir(file_path)) == 0)
-                       retval = add_subdirectory(sysdir, file_path);
+               if ((sysfs_path_is_dir(file_path)) == 0) {
+                       if (!dirlist) {
+                               dirlist = dlist_new_with_delete
+                                       (SYSFS_NAME_LEN, sysfs_del_name);
+                               if (!dirlist) {
+                                       dprintf("Error creating list\n");
+                                       return NULL;
+                               }
+                       }
+                       dir_name = (char *)calloc(1, SYSFS_NAME_LEN);
+                       safestrcpymax(dir_name, dirent->d_name, SYSFS_NAME_LEN);
+                       dlist_unshift_sorted(dirlist, dir_name, sort_char);
+               }
        }
        closedir(dir);
-       if (!retval)
-               errno = 0;
-       return(retval);
+       return dirlist;
 }
 
 /**
- * sysfs_read_directory: grabs attributes, links, and subdirectories
- * @sysdir: sysfs directory to open
- * returns 0 with success and -1 with error.
+ * get_attributes_list: build a list of attributes for the given device
+ * @dev: devices whose attributes list is required
+ * returns dlist of attributes on success and NULL on failure
  */
-int sysfs_read_directory(struct sysfs_directory *sysdir)
+struct dlist *get_attributes_list(void *dev)
 {
        DIR *dir = NULL;
        struct dirent *dirent = NULL;
-       struct stat astats;
-       char file_path[SYSFS_PATH_MAX];
-       int retval = 0;
+       struct sysfs_attribute *attr = NULL;
+       char file_path[SYSFS_PATH_MAX], path[SYSFS_PATH_MAX];
 
-       if (sysdir == NULL) {
+       if (!dev) {
                errno = EINVAL;
-               return -1;
+               return NULL;
        }
-       dir = opendir(sysdir->path);
-       if (dir == NULL) {
-               dprintf("Error opening directory %s\n", sysdir->path);
-               return -1;
+       memset(path, 0, SYSFS_PATH_MAX);
+       safestrcpy(path, ((struct sysfs_device *)dev)->path);
+       dir = opendir(path);
+       if (!dir) {
+               dprintf("Error opening directory %s\n", path);
+               return NULL;
        }
-       while(((dirent = readdir(dir)) != NULL) && retval == 0) {
+       while ((dirent = readdir(dir)) != NULL) {
                if (0 == strcmp(dirent->d_name, "."))
                         continue;
                if (0 == strcmp(dirent->d_name, ".."))
                        continue;
                memset(file_path, 0, SYSFS_PATH_MAX);
-               safestrcpy(file_path, sysdir->path);
+               safestrcpy(file_path, path);
                safestrcat(file_path, "/");
                safestrcat(file_path, dirent->d_name);
-               if ((lstat(file_path, &astats)) != 0) {
-                       dprintf("stat failed\n");
-                       continue;
-               }
-               if (S_ISDIR(astats.st_mode)) 
-                       retval = add_subdirectory(sysdir, file_path);
-
-               else if (S_ISLNK(astats.st_mode))
-                       retval = add_link(sysdir, file_path);
-
-               else if (S_ISREG(astats.st_mode))
-                       retval = add_attribute(sysdir, file_path);
-       }
-       closedir(dir);
-       if (!retval)
-               errno = 0;
-       return(retval);
-}
-
-/**
- * sysfs_refresh_dir_attributes: Refresh attributes list
- * @sysdir: directory whose list of attributes to refresh
- * Returns 0 on success, 1 on failure
- */
-int sysfs_refresh_dir_attributes(struct sysfs_directory *sysdir)
-{
-       if (sysdir == NULL) {
-               errno = EINVAL;
-               return 1;
-       }
-       if ((sysfs_path_is_dir(sysdir->path)) != 0) {
-               dprintf("Invalid path to directory %s\n", sysdir->path);
-               errno = EINVAL;
-               return 1;
-       }
-       if (sysdir->attributes != NULL) {
-               dlist_destroy(sysdir->attributes);
-               sysdir->attributes = NULL;
-       }
-       if ((sysfs_read_dir_attributes(sysdir)) != 0) {
-               dprintf("Error refreshing attributes for directory %s\n", 
-                                                       sysdir->path);
-               return 1;
-       }
-       errno = 0;
-       return 0;
-}
-
-/**
- * sysfs_refresh_dir_links: Refresh links list
- * @sysdir: directory whose list of links to refresh
- * Returns 0 on success, 1 on failure
- */
-int sysfs_refresh_dir_links(struct sysfs_directory *sysdir)
-{
-       if (sysdir == NULL) {
-               errno = EINVAL;
-               return 1;
-       }
-       if ((sysfs_path_is_dir(sysdir->path)) != 0) {
-               dprintf("Invalid path to directory %s\n", sysdir->path);
-               errno = EINVAL;
-               return 1;
-       }
-       if (sysdir->links != NULL) {
-               dlist_destroy(sysdir->links);
-               sysdir->links = NULL;
-       }
-       if ((sysfs_read_dir_links(sysdir)) != 0) {
-               dprintf("Error refreshing links for directory %s\n", 
-                                                       sysdir->path);
-               return 1;
-       }
-       errno = 0;
-       return 0;
-}
-
-/**
- * sysfs_refresh_dir_subdirs: Refresh subdirs list
- * @sysdir: directory whose list of subdirs to refresh
- * Returns 0 on success, 1 on failure
- */
-int sysfs_refresh_dir_subdirs(struct sysfs_directory *sysdir)
-{
-       if (sysdir == NULL) {
-               errno = EINVAL;
-               return 1;
-       }
-       if ((sysfs_path_is_dir(sysdir->path)) != 0) {
-               dprintf("Invalid path to directory %s\n", sysdir->path);
-               errno = EINVAL;
-               return 1;
-       }
-       if (sysdir->subdirs != NULL) {
-               dlist_destroy(sysdir->subdirs);
-               sysdir->subdirs = NULL;
-       }
-       if ((sysfs_read_dir_subdirs(sysdir)) != 0) {
-               dprintf("Error refreshing subdirs for directory %s\n", 
-                                                       sysdir->path);
-               return 1;
-       }
-       errno = 0;
-       return 0;
-}
-
-/**
- * sysfs_get_directory_attribute: retrieves attribute attrname from current
- *     directory only
- * @dir: directory to retrieve attribute from
- * @attrname: name of attribute to look for
- *
- * NOTE: Since we know the attribute to look for, this routine looks for the
- *     attribute if it was created _after_ the attrlist was read initially.
- *     
- * returns sysfs_attribute if found and NULL if not found
- */
-struct sysfs_attribute *sysfs_get_directory_attribute
-                       (struct sysfs_directory *dir, char *attrname)
-{
-       struct sysfs_attribute *attr = NULL;
-       char new_path[SYSFS_PATH_MAX];
-       
-       if (dir == NULL || attrname == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (dir->attributes == NULL) 
-               if ((sysfs_read_dir_attributes(dir) != 0) 
-                   || (dir->attributes == NULL))
-                       return NULL;
-
-       attr = (struct sysfs_attribute *)dlist_find_custom
-                       (dir->attributes, attrname, dir_attribute_name_equal);
-       if (attr != NULL) {
-               if ((attr->method & SYSFS_METHOD_SHOW) &&
-                       (sysfs_read_attribute(attr)) != 0) {
-                       dprintf("Error reading attribute %s\n", attr->name);
-                       return NULL;
-               }
-       } else {
-               memset(new_path, 0, SYSFS_PATH_MAX);
-               safestrcpy(new_path, dir->path);
-               safestrcat(new_path, "/");
-               safestrcat(new_path, attrname);
-               if ((sysfs_path_is_file(new_path)) == 0) {
-                       if ((add_attribute(dir, new_path)) == 0) {
+               if ((sysfs_path_is_file(file_path)) == 0) {
+                       if (((struct sysfs_device *)dev)->attrlist) {
+                               /* check if attr is already in the list */
                                attr = (struct sysfs_attribute *)
-                                       dlist_find_custom(dir->attributes,
-                                       attrname, dir_attribute_name_equal);
-                       }
-               }
-       }
-               
-       return attr;
-}
-
-/**
- * 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, char *linkname)
-{
-       if (dir == NULL || linkname == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-       if (dir->links == NULL) {
-               if ((sysfs_read_dir_links(dir) != 0) || (dir->links == NULL))
-                       return NULL;
-       } else {
-               if ((sysfs_refresh_dir_links(dir)) != 0) 
-                       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,
-                                               char *subname)
-{
-       struct sysfs_directory *sub = NULL, *cursub = NULL;
-
-       if (dir == NULL || subname == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (dir->subdirs == NULL)
-               if (sysfs_read_dir_subdirs(dir) != 0)
-                       return NULL;
-
-       sub = (struct sysfs_directory *)dlist_find_custom(dir->subdirs,
-               subname, dir_subdir_name_equal);
-       if (sub != NULL) 
-               return sub;
-
-       if (dir->subdirs != NULL) {
-               dlist_for_each_data(dir->subdirs, cursub, 
-                                       struct sysfs_directory) {
-                       if (cursub->subdirs == NULL) {
-                               if (sysfs_read_dir_subdirs(cursub) != 0)
-                                       continue;
-                               if (cursub->subdirs == NULL)
+                               dlist_find_custom
+                               ((((struct sysfs_device *)dev)->attrlist), 
+                               (void *)dirent->d_name, attr_name_equal);
+                               if (attr) 
                                        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,
-                                               char *linkname)
-{
-       struct sysfs_directory *cursub = NULL;
-       struct sysfs_link *ln = NULL;
-
-       if (dir == NULL || linkname == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       ln = sysfs_get_directory_link(dir, linkname);
-       if (ln != NULL)
-               return ln;
-
-       if (dir->subdirs == NULL) 
-               if (sysfs_read_dir_subdirs(dir) != 0)
-                       return NULL;
-
-       if (dir->subdirs != NULL) {
-               dlist_for_each_data(dir->subdirs, cursub, 
-                                               struct sysfs_directory) {
-                       ln = sysfs_get_subdirectory_link(cursub, linkname);
-                       if (ln != NULL)
-                               return ln;
+                               else 
+                                       add_attribute(dev, file_path);
+                       } else 
+                               attr = add_attribute(dev, file_path);
                }
        }
-       return NULL;
-}
-
-/**
- * sysfs_get_dir_attributes: returns dlist of directory attributes
- * @dir: directory to retrieve attributes from
- * returns dlist of attributes or NULL
- */
-struct dlist *sysfs_get_dir_attributes(struct sysfs_directory *dir)
-{
-       if (dir == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (dir->attributes == NULL) {
-               if (sysfs_read_dir_attributes(dir) != 0)
-                       return NULL;
-       }
-
-       return (dir->attributes);
-}
-
-/**
- * sysfs_get_dir_links: returns dlist of directory links
- * @dir: directory to return links for
- * returns dlist of links or NULL
- */
-struct dlist *sysfs_get_dir_links(struct sysfs_directory *dir)
-{
-       if (dir == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (dir->links == NULL) {
-               if (sysfs_read_dir_links(dir) != 0)
-                       return NULL;
-       }
-
-       return (dir->links);
-}
-
-/**
- * sysfs_get_dir_subdirs: returns dlist of directory subdirectories
- * @dir: directory to return subdirs for
- * returns dlist of subdirs or NULL
- */
-struct dlist *sysfs_get_dir_subdirs(struct sysfs_directory *dir)
-{
-       if (dir == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (dir->subdirs == NULL) {
-               if (sysfs_read_dir_subdirs(dir) != 0)
-                       return NULL;
-       }
-
-       return (dir->subdirs);
+       closedir(dir);
+       return ((struct sysfs_device *)dev)->attrlist;
 }
index 88d26b56ddee7dfb66651be20b3b1afd3c309935..c2464faa9e5a028a6a189d13b832121cc3dd5608 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Driver utility functions for libsysfs
  *
- * Copyright (C) IBM Corp. 2003
+ * Copyright (C) IBM Corp. 2003-2005
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -28,42 +28,20 @@ static void sysfs_close_driver_device(void *device)
        sysfs_close_device((struct sysfs_device *)device);
 }
 
-/** 
+/**
  * sysfs_close_driver: closes driver and deletes device lists too
  * @driver: driver to close
- */ 
+ */
 void sysfs_close_driver(struct sysfs_driver *driver)
 {
-       if (driver != NULL) {
-               if (driver->devices != NULL
+       if (driver) {
+               if (driver->devices) 
                        dlist_destroy(driver->devices);
-               if (driver->directory != NULL)
-                       sysfs_close_directory(driver->directory);
+               if (driver->attrlist)
+                       dlist_destroy(driver->attrlist);
                free(driver);
        }
 }
-               
-/**
- * open_driver_dir: Open the sysfs_directory for this driver
- * @driver: Driver whose directory to be opened
- * Returns 0 on success and 1 on failure
- */ 
-static int open_driver_dir(struct sysfs_driver *driver)
-{
-       if (driver == NULL) {
-               errno = EINVAL;
-               return 1;
-       }
-       if (driver->directory == NULL) {
-               driver->directory = sysfs_open_directory(driver->path);
-               if (driver->directory == NULL) {
-                       dprintf("Error opening driver directory at %s\n", 
-                                       driver->path);
-                       return 1;
-               }
-       }
-       return 0;
-}
 
 /**
  * alloc_driver: allocates and initializes driver
@@ -75,244 +53,104 @@ static struct sysfs_driver *alloc_driver(void)
 }
 
 /**
- * sysfs_open_driver_path: opens and initializes driver structure
- * @path: path to driver directory
- * returns struct sysfs_driver with success and NULL with error
+ * get_driver_bus: gets bus the driver is on
+ * Returns 0 on success and 1 on error
  */
-struct sysfs_driver *sysfs_open_driver_path(const char *path)
+static int get_driver_bus(struct sysfs_driver *drv)
 {
-       struct sysfs_driver *driver = NULL;
-
-       if (path == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-       if ((sysfs_path_is_dir(path)) != 0) {
-               dprintf("Invalid path to driver: %s\n", path);
-               return NULL;
-       }
-       driver = alloc_driver();
-       if (driver == NULL) {
-               dprintf("Error allocating driver at %s\n", path);
-               return NULL;
-       }
-       if ((sysfs_get_name_from_path(path, driver->name, 
-                                       SYSFS_NAME_LEN)) != 0) {
-               dprintf("Error getting driver name from path\n");
-               free(driver);
-               return NULL;
-       }
-       safestrcpy(driver->path, path);
-       if ((sysfs_remove_trailing_slash(driver->path)) != 0) {
-               dprintf("Invalid path to driver %s\n", driver->path);
-               sysfs_close_driver(driver);
-               return NULL;
-       }
+       char drvpath[SYSFS_PATH_MAX], *c = NULL;
        
-       return driver;
-}
-
-/**
- * sysfs_get_driver_attributes: gets list of attributes for the given driver
- * @driver: sysfs_driver for which attributes are required
- * returns a dlist of attributes corresponding to the driver if present
- *     NULL otherwise
- */
-struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *driver)
-{
-       if (driver == NULL) {
+       if (!drv) {
                errno = EINVAL;
-               return NULL;
-       }
-
-       if (driver->directory == NULL) {
-               if ((open_driver_dir(driver)) == 1) 
-                       return NULL;
-       }
-       if (driver->directory->attributes == NULL) {
-               if ((sysfs_read_dir_attributes(driver->directory)) != 0) 
-                       return NULL;
+               return 1;
        }
-       return(driver->directory->attributes);
-}
 
-/**
- * sysfs_refresh_driver_attributes: refreshes the driver's list of attributes
- * @driver: sysfs_driver whose attributes to refresh
- *
- * NOTE: Upon return, prior references to sysfs_attributes for this driver
- *             _may_ not be valid
- *             
- * Returns list of attributes on success and NULL on failure
- */
-struct dlist *sysfs_refresh_driver_attributes(struct sysfs_driver *driver)
-{
-       if (driver == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-       if (driver->directory == NULL)
-               return (sysfs_get_driver_attributes(driver));
-       
-       if ((sysfs_refresh_dir_attributes(driver->directory)) != 0) {
-               dprintf("Error refreshing driver attributes\n");
-               return NULL;
-       }
-       return (driver->directory->attributes);
+       safestrcpy(drvpath, drv->path);
+       c = strstr(drvpath, SYSFS_DRIVERS_NAME);
+       if (c == NULL)
+               return 1;
+       *--c = '\0';
+       c = strstr(drvpath, SYSFS_BUS_NAME);
+       if (c == NULL)
+               return 1;
+       c = strstr(c, "/");
+       if (c == NULL)
+               return 1;
+       c++;
+       safestrcpy(drv->bus, c);
+       return 0;
 }
 
 /**
- * sysfs_get_driver_attr: searches driver's attributes by name
+ * sysfs_get_driver_attr: searches drv's attributes by name
  * @drv: driver to look through
  * @name: attribute name to get
- * returns sysfs_attribute reference on success or NULL with error
- */ 
+ * returns sysfs_attribute reference with success or NULL with error.
+ */
 struct sysfs_attribute *sysfs_get_driver_attr(struct sysfs_driver *drv,
-                                       const char *name)
+                                               const char *name)
 {
-       struct dlist *attrlist = NULL;
-
-        if (drv == NULL) {
-                errno = EINVAL;
-                return NULL;
-        }
-       
-       attrlist = sysfs_get_driver_attributes(drv);
-       if (attrlist == NULL) 
+       if (!drv || !name) {
+               errno = EINVAL;
                return NULL;
-
-       return sysfs_get_directory_attribute(drv->directory, (char *)name);
+       }
+       return get_attribute(drv, (char *)name);
 }
 
 /**
- * sysfs_get_driver_links: gets list of links from the given driver
- * @driver: sysfs_driver for which links list is required
- * returns a dlist of links corresponding to the driver if present
- *     NULL otherwise
+ * sysfs_get_driver_attributes: gets list of driver attributes
+ * @dev: driver whose attributes list is needed
+ * returns dlist of attributes on success or NULL on error
  */
-struct dlist *sysfs_get_driver_links(struct sysfs_driver *driver)
+struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *drv)
 {
-       if (driver == NULL) {
+       if (!drv) {
                errno = EINVAL;
                return NULL;
        }
-
-       if (driver->directory == NULL) 
-               if ((open_driver_dir(driver)) == 1)
-                       return NULL;
-       
-       if (driver->directory->links == NULL)
-               if ((sysfs_read_dir_links(driver->directory)) != 0) 
-                       return NULL;
-               
-       return(driver->directory->links);
+       return get_attributes_list(drv);
 }
 
 /**
- * sysfs_get_driver_devices: open up the list of devices this driver supports
- * @driver: sysfs_driver for which devices are needed
- * Returns dlist of devices on SUCCESS or NULL with ERROR
- */ 
-struct dlist *sysfs_get_driver_devices(struct sysfs_driver *driver)
+ * sysfs_open_driver_path: opens and initializes driver structure
+ * @path: path to driver directory
+ * returns struct sysfs_driver with success and NULL with error
+ */
+struct sysfs_driver *sysfs_open_driver_path(const char *path)
 {
-       struct sysfs_link *curlink = NULL;
-       struct sysfs_device *device = NULL;
+       struct sysfs_driver *driver = NULL;
 
-       if (driver == NULL) {
+       if (!path) {
                errno = EINVAL;
                return NULL;
        }
-       
-       if (driver->devices != NULL)
-               return (driver->devices);
-
-       if (driver->directory == NULL || driver->directory->links == NULL) {
-               struct dlist *list = NULL;
-               list = sysfs_get_driver_links(driver);
-       }
-       
-       if (driver->directory->links != NULL) {
-               dlist_for_each_data(driver->directory->links, curlink, 
-                                               struct sysfs_link) {
-                       device = sysfs_open_device_path(curlink->target);
-                       if (device == NULL) {
-                               dprintf("Error opening device at %s\n", 
-                                               curlink->target);
-                               return NULL;
-                       }
-                       if (driver->devices == NULL) 
-                               driver->devices = dlist_new_with_delete
-                                               (sizeof(struct sysfs_device),
-                                                sysfs_close_driver_device);
-                       dlist_unshift_sorted(driver->devices, device, 
-                                                               sort_list);
-               }
+       if (sysfs_path_is_dir(path)) {
+               dprintf("Invalid path to driver: %s\n", path);
+               return NULL;
        }
-       return (driver->devices);
-}
-
-/**
- * sysfs_refresh_driver_devices: Refreshes drivers list of devices
- * @driver: sysfs_driver whose devices list needs to be refreshed
- *
- * NOTE: Upon return from this function, prior sysfs_device references from
- *             this driver's list of devices _may_ not be valid
- *             
- * Returns dlist of devices on success and NULL on failure
- */
-struct dlist *sysfs_refresh_driver_devices(struct sysfs_driver *driver)
-{
-       if (driver == NULL) {
-               errno = EINVAL;
+       driver = alloc_driver();
+       if (!driver) {
+               dprintf("Error allocating driver at %s\n", path);
                return NULL;
        }
-       
-       if (driver->devices != NULL) {
-               dlist_destroy(driver->devices);
-               driver->devices = NULL;
+       if (sysfs_get_name_from_path(path, driver->name, SYSFS_NAME_LEN)) {
+               dprintf("Error getting driver name from path\n");
+               free(driver);
+               return NULL;
        }
-       
-       if (driver->directory == NULL)
-               return (sysfs_get_driver_devices(driver));
-
-       if ((sysfs_refresh_dir_links(driver->directory)) != 0) {
-               dprintf("Error refreshing driver links\n");
+       safestrcpy(driver->path, path);
+       if (sysfs_remove_trailing_slash(driver->path)) {
+               dprintf("Invalid path to driver %s\n", driver->path);
+               sysfs_close_driver(driver);
                return NULL;
        }
-       
-       return (sysfs_get_driver_devices(driver));
-}
-
-/**
- * sysfs_get_driver_device: looks up a device from a list of driver's devices
- *     and returns its sysfs_device corresponding to it
- * @driver: sysfs_driver on which to search
- * @name: name of the device to search
- * Returns a sysfs_device if found, NULL otherwise
- */
-struct sysfs_device *sysfs_get_driver_device(struct sysfs_driver *driver,
-                               const char *name)
-{
-       struct sysfs_device *device = NULL;
-       struct dlist *devlist = NULL;
-
-       if (driver == NULL || name == NULL) {
-               errno = EINVAL;
+       if (get_driver_bus(driver)) {
+               dprintf("Could not get the bus driver is on\n");
+               sysfs_close_driver(driver);
                return NULL;
        }
 
-       if (driver->devices == NULL) {
-               devlist = sysfs_get_driver_devices(driver);
-               if (devlist == NULL) {
-                       dprintf("Error getting driver devices\n");
-                       return NULL;
-               }
-       }
-       dlist_for_each_data(driver->devices, device, struct sysfs_device) {
-               if (!(strncmp(device->name, name, SYSFS_NAME_LEN)))
-                       return device;
-       }
-       return NULL;
+       return driver;
 }
 
 /**
@@ -327,11 +165,11 @@ struct sysfs_device *sysfs_get_driver_device(struct sysfs_driver *driver,
 static int get_driver_path(const char *bus, const char *drv, 
                        char *path, size_t psize)
 {
-       if (bus == NULL || drv == NULL || path == NULL || psize == 0) {
+       if (!bus || !drv || !path || psize == 0) {
                errno = EINVAL;
                return -1;
        }
-       if (sysfs_get_mnt_path(path, psize) != 0) {
+       if (sysfs_get_mnt_path(path, psize)) {
                dprintf("Error getting sysfs mount path\n");
                return -1;
        }
@@ -346,50 +184,6 @@ static int get_driver_path(const char *bus, const char *drv,
        return 0;
 }
 
-/**
- * sysfs_open_driver_attr: read the user supplied driver attribute
- * @bus: bus on which to look 
- * @drv: driver whose attribute has to be read
- * @attrib: Attribute to be read
- * Returns struct sysfs_attribute on success and NULL on failure
- *
- * NOTE:
- *     A call to sysfs_close_attribute() is required to close the
- *     attribute returned and to free memory
- */ 
-struct sysfs_attribute *sysfs_open_driver_attr(const char *bus, 
-               const char *drv, const char *attrib)
-{
-       struct sysfs_attribute *attribute = NULL;
-       char path[SYSFS_PATH_MAX];
-
-       if (bus == NULL || drv == NULL || attrib == NULL) {
-               errno = EINVAL;
-               return NULL;
-       }
-
-       memset(path, 0, SYSFS_PATH_MAX);
-       if ((get_driver_path(bus, drv, path, SYSFS_PATH_MAX)) != 0) {
-               dprintf("Error getting to driver %s\n", drv);
-               return NULL;
-       }
-       safestrcat(path, "/");
-       safestrcat(path, attrib);
-       attribute = sysfs_open_attribute(path);
-        if (attribute == NULL) {
-               dprintf("Error opening attribute %s for driver %s\n",
-                               attrib, drv);
-               return NULL;
-       }
-       if ((sysfs_read_attribute(attribute)) != 0) {
-                dprintf("Error reading attribute %s for driver %s\n", 
-                               attrib, drv);
-               sysfs_close_attribute(attribute);
-               return NULL;
-       }
-       return attribute;
-}
-
 /**
  * sysfs_open_driver: open driver by name, given its bus
  * @bus_name: Name of the bus
@@ -402,21 +196,66 @@ struct sysfs_driver *sysfs_open_driver(const char *bus_name,
        char path[SYSFS_PATH_MAX];
        struct sysfs_driver *driver = NULL;
 
-       if (drv_name == NULL || bus_name == NULL) {
+       if (!drv_name || !bus_name) {
                errno = EINVAL;
                return NULL;
        }
 
        memset(path, 0, SYSFS_PATH_MAX);
-       if ((get_driver_path(bus_name, drv_name, path, SYSFS_PATH_MAX)) != 0) {
+       if (get_driver_path(bus_name, drv_name, path, SYSFS_PATH_MAX)) {
                dprintf("Error getting to driver %s\n", drv_name);
                return NULL;
        }
        driver = sysfs_open_driver_path(path);
-       if (driver == NULL) {
+       if (!driver) {
                dprintf("Error opening driver at %s\n", path);
                return NULL;
        }
        return driver;
 }
 
+/**
+ * sysfs_get_driver_devices: gets list of devices that use the driver
+ * @drv: sysfs_driver whose device list is needed
+ * Returns dlist of struct sysfs_device on success and NULL on failure
+ */
+struct dlist *sysfs_get_driver_devices(struct sysfs_driver *drv)
+{
+       char *ln = NULL;
+       struct dlist *linklist = NULL;
+       struct sysfs_device *dev = NULL;
+
+       if (!drv) {
+               errno = EINVAL;
+               return NULL;
+       }
+
+       linklist = read_dir_links(drv->path);
+       if (linklist) {
+               dlist_for_each_data(linklist, ln, char) {
+                       
+                       if (!strncmp(ln, SYSFS_MODULE_NAME, strlen(ln)))
+                               continue;
+
+                       dev = sysfs_open_device(drv->bus, ln);
+                       if (!dev) {
+                               dprintf("Error opening driver's device\n");
+                               sysfs_close_list(linklist);
+                               return NULL;
+                       }
+                       if (!drv->devices) {
+                               drv->devices = dlist_new_with_delete
+                                       (sizeof(struct sysfs_device),
+                                        sysfs_close_driver_device);
+                               if (!drv->devices) {
+                                       dprintf("Error creating device list\n");
+                                       sysfs_close_list(linklist);
+                                       return NULL;
+                               }
+                       }
+                       dlist_unshift_sorted(drv->devices, dev, sort_list);
+               }
+               sysfs_close_list(linklist);
+       }
+       return drv->devices;
+}
index 8b1f56ed146f73ea47ad012810542a859e4efd07..9f6e18f665dd592cdb9de80ef9830e78880cd477 100644 (file)
 #include "libsysfs.h"
 #include "sysfs.h"
 
-static int sort_char(void *new, void *old)
-{
-       return ((strncmp((char *)new, (char *)old, 
-                       strlen((char *)new))) < 0 ? 1 : 0);
-}
-
 /**
  * sysfs_remove_trailing_slash: Removes any trailing '/' in the given path
  * @path: Path to look for the trailing '/'
@@ -38,7 +32,7 @@ int sysfs_remove_trailing_slash(char *path)
 {
        char *c = NULL;
 
-       if (path == NULL) {
+       if (!path) {
                errno = EINVAL;
                return 1;
        }
@@ -53,54 +47,6 @@ int sysfs_remove_trailing_slash(char *path)
        return 0;
 }
 
-/**
- * sysfs_get_fs_mnt_path: Gets the mount point for specified filesystem.
- * @fs_type: filesystem type to retrieve mount point
- * @mnt_path: place to put the retrieved mount path
- * @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)
-{
-       FILE *mnt;
-       struct mntent *mntent;
-       int ret = 0;
-       size_t dirlen = 0;
-
-       /* check arg */
-       if (fs_type == NULL || mnt_path == NULL || len == 0) {
-               errno = EINVAL;
-               return -1;
-       }
-
-       if ((mnt = setmntent(SYSFS_PROC_MNTS, "r")) == NULL) {
-               dprintf("Error getting mount information\n");
-               return -1;
-       }
-       while (ret == 0 && dirlen == 0 && (mntent = getmntent(mnt)) != NULL) {
-               if (strcmp(mntent->mnt_type, fs_type) == 0) {
-                       dirlen = strlen(mntent->mnt_dir);
-                       if (dirlen <= (len - 1)) {
-                               safestrcpymax(mnt_path, mntent->mnt_dir, len);
-                       } else {
-                               dprintf("Error - mount path too long\n");
-                               ret = -1;
-                       }
-               }
-       }
-       endmntent(mnt);
-       if (dirlen == 0 && ret == 0) {
-               dprintf("Filesystem %s not found!\n", fs_type);
-               errno = EINVAL;
-               ret = -1;
-       }
-       if ((sysfs_remove_trailing_slash(mnt_path)) != 0)
-               ret = -1;
-       
-       return ret;
-}
-
 /*
  * sysfs_get_mnt_path: Gets the sysfs mount point.
  * @mnt_path: place to put "sysfs" mount point
@@ -109,22 +55,21 @@ static int sysfs_get_fs_mnt_path(const char *fs_type,
  */
 int sysfs_get_mnt_path(char *mnt_path, size_t len)
 {
-       char *sysfs_path = NULL;
-       int ret = 0;
-
-       if (mnt_path == NULL || len == 0) {
-               errno = EINVAL;
-               return -1;
+       static char sysfs_path[SYSFS_PATH_MAX] = "";
+       const char *sysfs_path_env;
+
+       /* evaluate only at the first call */
+       if (sysfs_path[0] == '\0') {
+               /* possible overrride of real mount path */
+               sysfs_path_env = getenv(SYSFS_PATH_ENV);
+               if (sysfs_path_env != NULL) {
+                       safestrcpymax(mnt_path, sysfs_path_env, len);
+                       return 0;
+               }
+               safestrcpymax(mnt_path, SYSFS_MNT_PATH, len);
        }
-       sysfs_path = getenv(SYSFS_PATH_ENV);
-       if (sysfs_path != NULL) {
-               safestrcpymax(mnt_path, sysfs_path, len);
-               if ((sysfs_remove_trailing_slash(mnt_path)) != 0)
-                       return 1;
-       } else
-               ret = sysfs_get_fs_mnt_path(SYSFS_FSTYPE_NAME, mnt_path, len);
 
-       return ret;
+       return 0;
 }
 
 /**
@@ -137,8 +82,8 @@ int sysfs_get_name_from_path(const char *path, char *name, size_t len)
 {
        char tmp[SYSFS_PATH_MAX];
        char *n = NULL;
-                                                                                
-       if (path == NULL || name == NULL || len == 0) {
+
+       if (!path || !name || len == 0) {
                errno = EINVAL;
                return -1;
        }
@@ -161,7 +106,7 @@ int sysfs_get_name_from_path(const char *path, char *name, size_t len)
        safestrcpymax(name, n, len);
        return 0;
 }
-       
+
 /**
  * sysfs_get_link: returns link source
  * @path: symbolic link's path
@@ -176,7 +121,7 @@ int sysfs_get_link(const char *path, char *target, size_t len)
        char *d = NULL, *s = NULL;
        int slashes = 0, count = 0;
 
-       if (path == NULL || target == NULL || len == 0) {
+       if (!path || !target || len == 0) {
                errno = EINVAL;
                return -1;
        }
@@ -190,15 +135,15 @@ int sysfs_get_link(const char *path, char *target, size_t len)
                return -1;
        }
        d = linkpath;
-       /* 
+       /*
         * Three cases here:
         * 1. relative path => format ../..
         * 2. absolute path => format /abcd/efgh
         * 3. relative path _from_ this dir => format abcd/efgh
-        */ 
+        */
        switch (*d) {
                case '.': 
-                       /* 
+                       /*
                         * handle the case where link is of type ./abcd/xxx
                         */
                        safestrcpy(temp_path, devdir);
@@ -215,9 +160,8 @@ int sysfs_get_link(const char *path, char *target, size_t len)
                        }
                        safestrcpymax(target, temp_path, len);
                        break;
-                       /* 
-                        * relative path  
-                        * getting rid of leading "../.." 
+                       /*
+                        * relative path, getting rid of leading "../.."
                         */
 parse_path:
                        while (*d == '/' || *d == '.') {
@@ -254,16 +198,6 @@ parse_path:
        return 0;
 }
 
-/**
- * sysfs_del_name: free function for sysfs_open_subsystem_list
- * @name: memory area to be freed
- */ 
-static void sysfs_del_name(void *name)
-{
-       free(name);
-}
-
-
 /**
  * sysfs_close_list: generic list free routine
  * @list: dlist to free
@@ -271,142 +205,22 @@ static void sysfs_del_name(void *name)
  */
 void sysfs_close_list(struct dlist *list)
 {
-       if (list != NULL)
+       if (list)
                dlist_destroy(list);
 }
 
 /**
- * sysfs_open_subsystem_list: gets a list of all supported "name" subsystem
- *     details from the system
- * @name: name of the subsystem, eg., "bus", "class", "devices"
- * Returns a dlist of supported names or NULL if subsystem not supported
- */ 
-struct dlist *sysfs_open_subsystem_list(char *name)
-{
-       char sysfs_path[SYSFS_PATH_MAX], *subsys_name = NULL;
-       char *c = NULL;
-       struct sysfs_directory *dir = NULL, *cur = NULL;
-       struct dlist *list = NULL;
-       
-       if (name == NULL)
-               return NULL;
-
-       if (sysfs_get_mnt_path(sysfs_path, SYSFS_PATH_MAX) != 0) {
-               dprintf("Error getting sysfs mount point\n");
-               return NULL;
-       }
-
-       safestrcat(sysfs_path, "/");
-       safestrcat(sysfs_path, name);
-       dir = sysfs_open_directory(sysfs_path);
-       if (dir == NULL) {
-               dprintf("Error opening sysfs_directory at %s\n", sysfs_path);
-               return NULL;
-       }
-
-       if ((sysfs_read_dir_subdirs(dir)) != 0) {
-               dprintf("Error reading sysfs_directory at %s\n", sysfs_path);
-               sysfs_close_directory(dir);
-               return NULL;
-       }
-
-       if (dir->subdirs != NULL) {
-               list = dlist_new_with_delete(SYSFS_NAME_LEN,
-                               sysfs_del_name);
-               if (list == NULL) {
-                       dprintf("Error creating list\n");
-                       sysfs_close_directory(dir);
-                       return NULL;
-               }
-
-               dlist_for_each_data(dir->subdirs, cur,
-                               struct sysfs_directory) {
-                       subsys_name = (char *)calloc(1, SYSFS_NAME_LEN);
-                       safestrcpymax(subsys_name, cur->name, SYSFS_NAME_LEN);
-                       dlist_unshift_sorted(list, subsys_name, sort_char);
-               }
-       }
-       sysfs_close_directory(dir);
-       /*
-        * We are now considering "block" as a "class". Hence, if the subsys
-        * name requested here is "class", verify if "block" is supported on
-        * this system and return the same.
-        */ 
-       if (strcmp(name, SYSFS_CLASS_NAME) == 0) {
-               c = strstr(sysfs_path, SYSFS_CLASS_NAME);
-               if (c == NULL)
-                       goto out;
-               *c = '\0';
-               safestrcpymax(c, SYSFS_BLOCK_NAME, 
-                               sizeof(sysfs_path) - strlen(sysfs_path));
-               if ((sysfs_path_is_dir(sysfs_path)) == 0) {
-                       subsys_name = (char *)calloc(1, SYSFS_NAME_LEN);
-                       safestrcpymax(subsys_name, SYSFS_BLOCK_NAME, 
-                                       SYSFS_NAME_LEN);
-                       dlist_unshift_sorted(list, subsys_name, sort_char);
-               }
-       }
-out:
-       return list;
-}
-
-
-/**
- * sysfs_open_bus_devices_list: gets a list of all devices on "name" bus
- * @name: name of the subsystem, eg., "pci", "scsi", "usb"
- * Returns a dlist of supported names or NULL if subsystem not supported
- */ 
-struct dlist *sysfs_open_bus_devices_list(char *name)
+ * sysfs_open_directory_list: gets a list of all directories under "path"
+ * @path: path to read
+ * Returns a dlist of supported names or NULL no directories (errno is set
+ *     in case of error
+ */
+struct dlist *sysfs_open_directory_list(const char *path)
 {
-       char sysfs_path[SYSFS_PATH_MAX], *device_name = NULL;
-       struct sysfs_directory *dir = NULL;
-       struct sysfs_link *cur = NULL;
-       struct dlist *list = NULL;
-       
-       if (name == NULL)
-               return NULL;
-
-       if (sysfs_get_mnt_path(sysfs_path, SYSFS_PATH_MAX) != 0) {
-               dprintf("Error getting sysfs mount point\n");
-               return NULL;
-       }
-
-       safestrcat(sysfs_path, "/");
-       safestrcat(sysfs_path, SYSFS_BUS_NAME);
-       safestrcat(sysfs_path, "/");
-       safestrcat(sysfs_path, name);
-       safestrcat(sysfs_path, "/");
-       safestrcat(sysfs_path, SYSFS_DEVICES_NAME);
-       dir = sysfs_open_directory(sysfs_path);
-       if (dir == NULL) {
-               dprintf("Error opening sysfs_directory at %s\n", sysfs_path);
-               return NULL;
-       }
-
-       if ((sysfs_read_dir_links(dir)) != 0) {
-               dprintf("Error reading sysfs_directory at %s\n", sysfs_path);
-               sysfs_close_directory(dir);
+       if (!path)
                return NULL;
-       }
-
-       if (dir->links != NULL) {
-               list = dlist_new_with_delete(SYSFS_NAME_LEN,
-                               sysfs_del_name);
-               if (list == NULL) {
-                       dprintf("Error creating list\n");
-                       sysfs_close_directory(dir);
-                       return NULL;
-               }
 
-               dlist_for_each_data(dir->links, cur,
-                               struct sysfs_link) {
-                       device_name = (char *)calloc(1, SYSFS_NAME_LEN);
-                       safestrcpymax(device_name, cur->name, SYSFS_NAME_LEN);
-                       dlist_unshift_sorted(list, device_name, sort_char);
-               }
-       }
-       sysfs_close_directory(dir);
-       return list;
+       return (read_dir_subdirs(path));
 }
 
 /**
@@ -418,7 +232,7 @@ int sysfs_path_is_dir(const char *path)
 {
        struct stat astats;
 
-       if (path == NULL) {
+       if (!path) {
                errno = EINVAL;
                return 1;
        }
@@ -428,7 +242,7 @@ int sysfs_path_is_dir(const char *path)
        }
        if (S_ISDIR(astats.st_mode))
                return 0;
-               
+
        return 1;
 }
 
@@ -441,7 +255,7 @@ int sysfs_path_is_link(const char *path)
 {
        struct stat astats;
 
-       if (path == NULL) {
+       if (!path) {
                errno = EINVAL;
                return 1;
        }
@@ -451,7 +265,7 @@ int sysfs_path_is_link(const char *path)
        }
        if (S_ISLNK(astats.st_mode))
                return 0;
-               
+
        return 1;
 }
 
@@ -464,7 +278,7 @@ int sysfs_path_is_file(const char *path)
 {
        struct stat astats;
 
-       if (path == NULL) {
+       if (!path) {
                errno = EINVAL;
                return 1;
        }
@@ -474,6 +288,6 @@ int sysfs_path_is_file(const char *path)
        }
        if (S_ISREG(astats.st_mode))
                return 0;
-               
+
        return 1;
 }
index bbcc3d8f4904721a6fa9be9c09656acca6654f6f..963b69aed2f41e4e35ce69f9f449fa9430b9a275 100644 (file)
@@ -47,10 +47,6 @@ attributes along the device chain. Useful for finding
 unique attributes to compose a rule.
 .RB Needs " \-p " specified.
 .TP
-.B \-s
-Print all sysfs devices with the major/minor number, the physical device and
-the bus value.
-.TP
 .B \-h
 Print help text.
 .SH "FILES"
index e9de6e5e095a9e688d0f089612d6bf655afed9b4..a4c17da3f09069bded7b65c3d3b97a86c6f6ce9b 100644 (file)
@@ -49,26 +49,13 @@ void log_message (int level, const char *format, ...)
 }
 #endif
 
-static int print_all_attributes(const char *path)
+static void print_all_attributes(struct dlist *attr_list)
 {
-       struct dlist *attributes;
        struct sysfs_attribute *attr;
-       struct sysfs_directory *sysfs_dir;
        char value[SYSFS_VALUE_SIZE];
        int len;
-       int retval = 0;
-
-       sysfs_dir = sysfs_open_directory(path);
-       if (sysfs_dir == NULL)
-               return -1;
-
-       attributes = sysfs_get_dir_attributes(sysfs_dir);
-       if (attributes == NULL) {
-               retval = -1;
-               goto exit;
-       }
 
-       dlist_for_each_data(attributes, attr, struct sysfs_attribute) {
+       dlist_for_each_data(attr_list, attr, struct sysfs_attribute) {
                if (attr->value != NULL) {
                        strfieldcpy(value, attr->value);
                        len = strlen(value);
@@ -92,11 +79,6 @@ static int print_all_attributes(const char *path)
                }
        }
        printf("\n");
-
-exit:
-       sysfs_close_directory(sysfs_dir);
-
-       return retval;
 }
 
 static int print_record(struct udevice *udev)
@@ -123,6 +105,7 @@ static int print_device_chain(const char *path)
        struct sysfs_attribute *attr;
        struct sysfs_device *sysfs_dev;
        struct sysfs_device *sysfs_dev_parent;
+       struct dlist *attr_list;
        int retval = 0;
 
        /*  get the class dev */
@@ -147,11 +130,14 @@ static int print_device_chain(const char *path)
        /* open sysfs class device directory and print all attributes */
        printf("  looking at class device '%s':\n", class_dev->path);
        printf("    SUBSYSTEM=\"%s\"\n", class_dev->classname);
-       if (print_all_attributes(class_dev->path) != 0) {
+
+       attr_list = sysfs_get_classdev_attributes(class_dev);
+       if (attr_list == NULL) {
                printf("couldn't open class device directory\n");
                retval = -1;
                goto exit;
        }
+       print_all_attributes(attr_list);
 
        /* get the device link (if parent exists look here) */
        class_dev_parent = sysfs_get_classdev_parent(class_dev);
@@ -165,13 +151,20 @@ static int print_device_chain(const char *path)
 
        /* look the device chain upwards */
        while (sysfs_dev != NULL) {
+               attr_list = sysfs_get_device_attributes(sysfs_dev);
+               if (attr_list == NULL) {
+                       printf("couldn't open device directory\n");
+                       retval = -1;
+                       goto exit;
+               }
+
                printf("  looking at the device chain at '%s':\n", sysfs_dev->path);
                printf("    BUS=\"%s\"\n", sysfs_dev->bus);
                printf("    ID=\"%s\"\n", sysfs_dev->bus_id);
                printf("    DRIVER=\"%s\"\n", sysfs_dev->driver_name);
 
                /* open sysfs device directory and print all attributes */
-               print_all_attributes(sysfs_dev->path);
+               print_all_attributes(attr_list);
 
                sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
                if (sysfs_dev_parent == NULL)
@@ -185,65 +178,9 @@ exit:
        return retval;
 }
 
-/* print all class/main block devices with major/minor, physical device, driver and bus */
-static int print_sysfs_devices(void)
-{
-       struct dlist *subsyslist;
-       char *class;
-
-       subsyslist = sysfs_open_subsystem_list("class");
-       if (!subsyslist)
-               return -1;
-
-       dlist_for_each_data(subsyslist, class, char) {
-               struct sysfs_class *cls;
-               struct dlist *class_devices;
-               struct sysfs_class_device *class_dev;
-               struct sysfs_device *phys_dev;
-               unsigned int major, minor;
-
-               cls = sysfs_open_class(class);
-               if (!cls)
-                       continue;
-
-               class_devices = sysfs_get_class_devices(cls);
-               if (!class_devices)
-                       continue;
-
-               dlist_for_each_data(class_devices, class_dev, struct sysfs_class_device) {
-                       struct sysfs_attribute *attr;
-
-                       printf("\n");
-                       printf("DEVPATH        '%s'\n", class_dev->path);
-                       printf("SUBSYSTEM      '%s'\n", class_dev->classname);
-
-                       attr = sysfs_get_classdev_attr(class_dev, "dev");
-                       if (attr) {
-                               sscanf(attr->value, "%u:%u", &major, &minor);
-                               printf("MAJOR          %u\n", major);
-                               printf("MINOR          %u\n", minor);
-                       }
-
-                       phys_dev = sysfs_get_classdev_device(class_dev);
-                       if (phys_dev) {
-                               printf("PHYSDEVPATH    '%s'\n", phys_dev->path);
-                               if (phys_dev->bus[0] != '\0')
-                                       printf("PHYSDEVBUS     '%s'\n", phys_dev->bus);
-
-                               if (phys_dev->driver_name[0] != '\0')
-                                       printf("PHYSDEVDRIVER  '%s'\n", phys_dev->driver_name);
-                       }
-               }
-               sysfs_close_class(cls);
-       }
-       sysfs_close_list(subsyslist);
-
-       return 0;
-}
-
 static int process_options(int argc, char *argv[])
 {
-       static const char short_options[] = "an:p:q:rsVh";
+       static const char short_options[] = "an:p:q:rVh";
        int option;
        int retval = 1;
        struct udevice udev;
@@ -304,10 +241,6 @@ static int process_options(int argc, char *argv[])
                        root = 1;
                        break;
 
-               case 's':
-                       print_sysfs_devices();
-                       exit(0);
-
                case 'a':
                        attributes = 1;
                        break;