list.h
SYSFS_OBJS = \
- libsysfs/sysfs_bus.o \
libsysfs/sysfs_class.o \
libsysfs/sysfs_device.o \
libsysfs/sysfs_dir.o \
#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
*
* 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"
#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
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);
(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);
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);
(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
*
* 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)
*/
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;
}
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);
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
*/
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);
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;
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)
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) {
(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;
}
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;
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
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;
}
-
*
* 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;
}
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.
*/
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, "/");
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;
return 0;
}
}
- }
- sysfs_close_list(buslist);
- }
- return -1;
+ }
+ sysfs_close_list(buslist);
+ }
+ return -1;
}
/**
*/
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,
}
}
-/**
- * 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);
}
}
*/
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));
}
/**
*/
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);
}
}
/**
- * 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);
}
/**
{
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;
}
* 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;
}
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;
}
*/
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;
}
}
}
*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;
-}
-
*
* 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)
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);
}
{
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;
}
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
long pgsize = 0;
int fd;
- if (sysattr == NULL) {
+ if (!sysattr) {
errno = EINVAL;
return -1;
}
}
pgsize = sysconf(_SC_PAGESIZE);
fbuf = (char *)calloc(1, pgsize+1);
- if (fbuf == NULL) {
+ if (!fbuf) {
dprintf("calloc failed\n");
return -1;
}
sysattr->len = length;
close(fd);
vbuf = (char *)realloc(fbuf, length+1);
- if (vbuf == NULL) {
+ if (!vbuf) {
dprintf("realloc failed\n");
free(fbuf);
return -1;
}
/**
- * 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;
}
*
* 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
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
}
/**
- * 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;
}
/**
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;
}
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
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;
+}
#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 '/'
{
char *c = NULL;
- if (path == NULL) {
+ if (!path) {
errno = EINVAL;
return 1;
}
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
*/
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;
}
/**
{
char tmp[SYSFS_PATH_MAX];
char *n = NULL;
-
- if (path == NULL || name == NULL || len == 0) {
+
+ if (!path || !name || len == 0) {
errno = EINVAL;
return -1;
}
safestrcpymax(name, n, len);
return 0;
}
-
+
/**
* sysfs_get_link: returns link source
* @path: symbolic link's path
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;
}
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);
}
safestrcpymax(target, temp_path, len);
break;
- /*
- * relative path
- * getting rid of leading "../.."
+ /*
+ * relative path, getting rid of leading "../.."
*/
parse_path:
while (*d == '/' || *d == '.') {
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
*/
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));
}
/**
{
struct stat astats;
- if (path == NULL) {
+ if (!path) {
errno = EINVAL;
return 1;
}
}
if (S_ISDIR(astats.st_mode))
return 0;
-
+
return 1;
}
{
struct stat astats;
- if (path == NULL) {
+ if (!path) {
errno = EINVAL;
return 1;
}
}
if (S_ISLNK(astats.st_mode))
return 0;
-
+
return 1;
}
{
struct stat astats;
- if (path == NULL) {
+ if (!path) {
errno = EINVAL;
return 1;
}
}
if (S_ISREG(astats.st_mode))
return 0;
-
+
return 1;
}
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"
}
#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);
}
}
printf("\n");
-
-exit:
- sysfs_close_directory(sysfs_dir);
-
- return retval;
}
static int print_record(struct udevice *udev)
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 */
/* 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);
/* 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)
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;
root = 1;
break;
- case 's':
- print_sysfs_devices();
- exit(0);
-
case 'a':
attributes = 1;
break;