1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-19 22:50:17 +03:00

[PATCH] big libsysfs diet (pre 2.0 version)

This commit is contained in:
kay.sievers@vrfy.org 2005-02-23 12:21:39 +01:00 committed by Greg KH
parent 8d1b4df219
commit f385ff6512
10 changed files with 703 additions and 2430 deletions

View File

@ -129,7 +129,6 @@ HEADERS = \
list.h
SYSFS_OBJS = \
libsysfs/sysfs_bus.o \
libsysfs/sysfs_class.o \
libsysfs/sysfs_device.o \
libsysfs/sysfs_dir.o \

View File

@ -27,19 +27,37 @@
#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

View File

@ -3,7 +3,7 @@
*
* Header Definitions for libsysfs
*
* Copyright (C) IBM Corp. 2003
* Copyright (C) IBM Corp. 2004-2005
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -27,27 +27,6 @@
#include <string.h>
#include "dlist.h"
/*
* Defines to prevent buffer overruns
*/
#define safestrcpy(to, from) strncpy(to, from, sizeof(to)-1)
#define safestrcat(to, from) strncat(to, from, sizeof(to) - strlen(to)-1)
#define safestrcpymax(to, from, max) \
do { \
to[max-1] = '\0'; \
strncpy(to, from, max-1); \
} while (0)
#define safestrcatmax(to, from, max) \
do { \
to[max-1] = '\0'; \
strncat(to, from, max - strlen(to)-1); \
} while (0)
/*
* Generic #defines go here..
*/
#define SYSFS_FSTYPE_NAME "sysfs"
#define SYSFS_PROC_MNTS "/proc/mounts"
#define SYSFS_BUS_NAME "bus"
@ -55,106 +34,92 @@ do { \
#define SYSFS_BLOCK_NAME "block"
#define SYSFS_DEVICES_NAME "devices"
#define SYSFS_DRIVERS_NAME "drivers"
#define SYSFS_MODULE_NAME "module"
#define SYSFS_NAME_ATTRIBUTE "name"
#define SYSFS_UNKNOWN "unknown"
#define SYSFS_PATH_ENV "SYSFS_PATH"
#define SYSFS_PATH_MAX 255
#define SYSFS_NAME_LEN 50
#define SYSFS_BUS_ID_SIZE 20
#define SYSFS_PATH_MAX 256
#define SYSFS_NAME_LEN 64
#define SYSFS_BUS_ID_SIZE 32
#define SYSFS_METHOD_SHOW 0x01 /* attr can be read by user */
#define SYSFS_METHOD_STORE 0x02 /* attr can be changed by user */
enum sysfs_attribute_method {
SYSFS_METHOD_SHOW = 0x01, /* attr can be read by user */
SYSFS_METHOD_STORE = 0x02, /* attr can be changed by user */
};
/* NOTE: statically define mnt path for sysfs */
#define SYSFS_MNT_PATH "/sys"
/*
* NOTE: We have the statically allocated "name" as the first element of all
* NOTE:
* 1. We have the statically allocated "name" as the first element of all
* the structures. This feature is used in the "sorter" function for dlists
* 2. As is the case with attrlist
* 3. As is the case with path
*/
struct sysfs_attribute {
char name[SYSFS_NAME_LEN];
char path[SYSFS_PATH_MAX];
char *value;
unsigned short len; /* value length */
unsigned short method; /* show and store */
};
struct sysfs_link {
char name[SYSFS_NAME_LEN];
char path[SYSFS_PATH_MAX];
char target[SYSFS_PATH_MAX];
};
struct sysfs_directory {
char name[SYSFS_NAME_LEN];
char path[SYSFS_PATH_MAX];
/* Private: for internal use only */
struct dlist *subdirs;
struct dlist *links;
struct dlist *attributes;
unsigned short len; /* value length */
enum sysfs_attribute_method method; /* show and store */
};
struct sysfs_driver {
char name[SYSFS_NAME_LEN];
char path[SYSFS_PATH_MAX];
struct dlist *attrlist;
char bus[SYSFS_NAME_LEN];
/* Private: for internal use only */
struct dlist *devices;
struct sysfs_directory *directory;
};
struct sysfs_device {
char name[SYSFS_NAME_LEN];
char path[SYSFS_PATH_MAX];
struct dlist *attrlist;
char bus_id[SYSFS_NAME_LEN];
char bus[SYSFS_NAME_LEN];
char driver_name[SYSFS_NAME_LEN];
char path[SYSFS_PATH_MAX];
/* Private: for internal use only */
struct sysfs_device *parent;
/* NOTE - we still don't populate this */
struct dlist *children;
struct sysfs_directory *directory;
};
struct sysfs_root_device {
char name[SYSFS_NAME_LEN];
char path[SYSFS_PATH_MAX];
/* Private: for internal use only */
struct dlist *devices;
struct sysfs_directory *directory;
};
/* NOTE: not used as of now */
struct sysfs_bus {
char name[SYSFS_NAME_LEN];
char path[SYSFS_PATH_MAX];
struct dlist *attrlist;
/* Private: for internal use only */
struct dlist *drivers;
struct dlist *devices;
struct sysfs_directory *directory;
};
struct sysfs_class_device {
char name[SYSFS_NAME_LEN];
char classname[SYSFS_NAME_LEN];
char path[SYSFS_PATH_MAX];
struct dlist *attrlist;
char classname[SYSFS_NAME_LEN];
/* Private: for internal use only */
struct sysfs_class_device *parent;
struct sysfs_device *sysdevice; /* NULL if virtual */
struct sysfs_driver *driver; /* NULL if not implemented */
struct sysfs_directory *directory;
};
/* NOTE: not used as of now */
struct sysfs_class {
char name[SYSFS_NAME_LEN];
char path[SYSFS_PATH_MAX];
struct dlist *attrlist;
/* Private: for internal use only */
struct dlist *devices;
struct sysfs_directory *directory;
};
#ifdef __cplusplus
@ -171,43 +136,15 @@ extern int sysfs_path_is_dir(const char *path);
extern int sysfs_path_is_link(const char *path);
extern int sysfs_path_is_file(const char *path);
extern int sysfs_get_link(const char *path, char *target, size_t len);
extern struct dlist *sysfs_open_subsystem_list(char *name);
extern struct dlist *sysfs_open_bus_devices_list(char *name);
extern struct dlist *sysfs_open_directory_list(const char *path);
extern void sysfs_close_list(struct dlist *list);
/* sysfs directory and file access */
extern void sysfs_close_attribute(struct sysfs_attribute *sysattr);
extern struct sysfs_attribute *sysfs_open_attribute(const char *path);
extern int sysfs_read_attribute(struct sysfs_attribute *sysattr);
extern int sysfs_read_attribute_value(const char *attrpath,
char *value, size_t vsize);
extern int sysfs_write_attribute(struct sysfs_attribute *sysattr,
const char *new_value, size_t len);
extern char *sysfs_get_value_from_attributes(struct dlist *attr,
const char *name);
extern int sysfs_refresh_dir_attributes(struct sysfs_directory *sysdir);
extern int sysfs_refresh_dir_links(struct sysfs_directory *sysdir);
extern int sysfs_refresh_dir_subdirs(struct sysfs_directory *sysdir);
extern void sysfs_close_directory(struct sysfs_directory *sysdir);
extern struct sysfs_directory *sysfs_open_directory(const char *path);
extern int sysfs_read_dir_attributes(struct sysfs_directory *sysdir);
extern int sysfs_read_dir_links(struct sysfs_directory *sysdir);
extern int sysfs_read_dir_subdirs(struct sysfs_directory *sysdir);
extern int sysfs_read_directory(struct sysfs_directory *sysdir);
extern int sysfs_read_all_subdirs(struct sysfs_directory *sysdir);
extern struct sysfs_directory *sysfs_get_subdirectory
(struct sysfs_directory *dir, char *subname);
extern void sysfs_close_link(struct sysfs_link *ln);
extern struct sysfs_link *sysfs_open_link(const char *lnpath);
extern struct sysfs_link *sysfs_get_directory_link
(struct sysfs_directory *dir, char *linkname);
extern struct sysfs_link *sysfs_get_subdirectory_link
(struct sysfs_directory *dir, char *linkname);
extern struct sysfs_attribute *sysfs_get_directory_attribute
(struct sysfs_directory *dir, char *attrname);
extern struct dlist *sysfs_get_dir_attributes(struct sysfs_directory *dir);
extern struct dlist *sysfs_get_dir_links(struct sysfs_directory *dir);
extern struct dlist *sysfs_get_dir_subdirs(struct sysfs_directory *dir);
/* sysfs driver access */
extern void sysfs_close_driver(struct sysfs_driver *driver);
@ -218,19 +155,8 @@ extern struct sysfs_attribute *sysfs_get_driver_attr
(struct sysfs_driver *drv, const char *name);
extern struct dlist *sysfs_get_driver_attributes(struct sysfs_driver *driver);
extern struct dlist *sysfs_get_driver_devices(struct sysfs_driver *driver);
extern struct dlist *sysfs_refresh_driver_devices(struct sysfs_driver *driver);
extern struct dlist *sysfs_get_driver_links(struct sysfs_driver *driver);
extern struct sysfs_device *sysfs_get_driver_device
(struct sysfs_driver *driver, const char *name);
extern struct dlist *sysfs_refresh_driver_attributes
(struct sysfs_driver *driver);
extern struct sysfs_attribute *sysfs_open_driver_attr
(const char *bus, const char *drv, const char *attrib);
/* generic sysfs device access */
extern void sysfs_close_root_device(struct sysfs_root_device *root);
extern struct sysfs_root_device *sysfs_open_root_device(const char *name);
extern struct dlist *sysfs_get_root_devices(struct sysfs_root_device *root);
extern void sysfs_close_device_tree(struct sysfs_device *device);
extern struct sysfs_device *sysfs_open_device_tree(const char *path);
extern void sysfs_close_device(struct sysfs_device *dev);
@ -241,27 +167,8 @@ extern struct sysfs_device *sysfs_open_device_path(const char *path);
extern int sysfs_get_device_bus(struct sysfs_device *dev);
extern struct sysfs_attribute *sysfs_get_device_attr
(struct sysfs_device *dev, const char *name);
extern struct dlist *sysfs_get_device_attributes(struct sysfs_device *device);
extern struct dlist *sysfs_refresh_device_attributes
(struct sysfs_device *device);
extern struct sysfs_attribute *sysfs_open_device_attr(const char *bus,
const char *bus_id, const char *attrib);
/* generic sysfs bus access */
extern void sysfs_close_bus(struct sysfs_bus *bus);
extern struct sysfs_bus *sysfs_open_bus(const char *name);
extern struct sysfs_device *sysfs_get_bus_device(struct sysfs_bus *bus,
char *id);
extern struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus,
char *drvname);
extern struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus);
extern struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus);
extern struct dlist *sysfs_get_bus_attributes(struct sysfs_bus *bus);
extern struct dlist *sysfs_refresh_bus_attributes(struct sysfs_bus *bus);
extern struct sysfs_attribute *sysfs_get_bus_attribute
(struct sysfs_bus *bus, char *attrname);
extern int sysfs_find_driver_bus(const char *driver, char *busname,
size_t bsize);
extern struct dlist *sysfs_get_device_attributes
(struct sysfs_device *dev);
/* generic sysfs class access */
extern void sysfs_close_class_device(struct sysfs_class_device *dev);
@ -269,26 +176,14 @@ extern struct sysfs_class_device *sysfs_open_class_device_path
(const char *path);
extern struct sysfs_class_device *sysfs_open_class_device
(const char *classname, const char *name);
extern struct sysfs_device *sysfs_get_classdev_device
(struct sysfs_class_device *clsdev);
extern struct sysfs_driver *sysfs_get_classdev_driver
(struct sysfs_class_device *clsdev);
extern struct sysfs_class_device *sysfs_get_classdev_parent
(struct sysfs_class_device *clsdev);
extern void sysfs_close_class(struct sysfs_class *cls);
extern struct sysfs_class *sysfs_open_class(const char *name);
extern struct dlist *sysfs_get_class_devices(struct sysfs_class *cls);
extern struct sysfs_class_device *sysfs_get_class_device
(struct sysfs_class *cls, char *name);
extern struct dlist *sysfs_get_classdev_attributes
(struct sysfs_class_device *cdev);
extern struct dlist *sysfs_refresh_classdev_attributes
(struct sysfs_class_device *cdev);
extern struct sysfs_attribute *sysfs_get_classdev_attr
(struct sysfs_class_device *clsdev, const char *name);
extern struct sysfs_attribute *sysfs_open_classdev_attr
(const char *classname, const char *dev,
const char *attrib);
extern struct dlist *sysfs_get_classdev_attributes
(struct sysfs_class_device *clsdev);
extern struct sysfs_device *sysfs_get_classdev_device
(struct sysfs_class_device *clsdev);
/**
* sort_list: sorter function to keep list elements sorted in alphabetical

View File

@ -3,7 +3,7 @@
*
* Generic class utility functions for libsysfs
*
* Copyright (C) IBM Corp. 2003
* Copyright (C) IBM Corp. 2003-2005
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -23,95 +23,50 @@
#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;
dev = calloc(1, sizeof(struct sysfs_class_device));
return 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));
}
/**
* set_classdev_classname: Grabs classname from path
* @cdev: class device to set
* Returns nothing
*/
static void set_classdev_classname(struct sysfs_class_device *cdev)
{
char *c = NULL, *e = NULL;
char *c, *e;
int count = 0;
c = strstr(cdev->path, SYSFS_CLASS_NAME);
if (c == NULL) {
c = strstr(cdev->path, SYSFS_BLOCK_NAME);
} else {
c = strchr(c, '/');
c = strstr(c, "/");
}
if (c == NULL)
@ -135,9 +90,9 @@ static void set_classdev_classname(struct sysfs_class_device *cdev)
*/
struct sysfs_class_device *sysfs_open_class_device_path(const char *path)
{
struct sysfs_class_device *cdev = NULL;
struct sysfs_class_device *cdev;
if (path == NULL) {
if (!path) {
errno = EINVAL;
return NULL;
}
@ -146,11 +101,11 @@ struct sysfs_class_device *sysfs_open_class_device_path(const char *path)
return NULL;
}
cdev = alloc_class_device();
if (cdev == NULL) {
if (!cdev) {
dprintf("calloc failed\n");
return NULL;
}
if ((sysfs_get_name_from_path(path, cdev->name, SYSFS_NAME_LEN)) != 0) {
if (sysfs_get_name_from_path(path, cdev->name, SYSFS_NAME_LEN)) {
errno = EINVAL;
dprintf("Error getting class device name\n");
sysfs_close_class_device(cdev);
@ -168,245 +123,6 @@ struct sysfs_class_device *sysfs_open_class_device_path(const char *path)
return cdev;
}
/**
* sysfs_get_class_devices: gets all devices for class
* @cls: class to get devices for
* returns dlist of class_devices with success and NULL with error
*/
struct dlist *sysfs_get_class_devices(struct sysfs_class *cls)
{
struct sysfs_class_device *dev = NULL;
struct sysfs_directory *cur = NULL;
if (cls == NULL) {
errno = EINVAL;
return NULL;
}
if (cls->devices != NULL)
return cls->devices;
if (cls->directory == NULL) {
cls->directory = sysfs_open_directory(cls->path);
if (cls->directory == NULL)
return NULL;
}
if ((sysfs_read_dir_subdirs(cls->directory)) != 0)
return NULL;
if (cls->directory->subdirs != NULL) {
dlist_for_each_data(cls->directory->subdirs, cur,
struct sysfs_directory) {
dev = sysfs_open_class_device_path(cur->path);
if (dev == NULL) {
dprintf("Error opening device at %s\n",
cur->path);
continue;
}
if (cls->devices == NULL)
cls->devices = dlist_new_with_delete
(sizeof(struct sysfs_class_device),
sysfs_close_cls_dev);
dlist_unshift_sorted(cls->devices, dev, sort_list);
}
}
return cls->devices;
}
/**
* sysfs_open_class: opens specific class and all its devices on system
* returns sysfs_class structure with success or NULL with error.
*/
struct sysfs_class *sysfs_open_class(const char *name)
{
struct sysfs_class *cls = NULL;
char classpath[SYSFS_PATH_MAX];
if (name == NULL) {
errno = EINVAL;
return NULL;
}
memset(classpath, 0, SYSFS_PATH_MAX);
if ((sysfs_get_mnt_path(classpath, SYSFS_PATH_MAX)) != 0) {
dprintf("Sysfs not supported on this system\n");
return NULL;
}
/*
* We shall now treat "block" also as a class. Hence, check here
* if "name" is "block" and proceed accordingly
*/
if (strcmp(name, SYSFS_BLOCK_NAME) == 0) {
safestrcat(classpath, "/");
safestrcat(classpath, SYSFS_BLOCK_NAME);
} else {
safestrcat(classpath, "/");
safestrcat(classpath, SYSFS_CLASS_NAME);
safestrcat(classpath, "/");
safestrcat(classpath, name);
}
if ((sysfs_path_is_dir(classpath)) != 0) {
dprintf("Class %s not found on the system\n", name);
return NULL;
}
cls = alloc_class();
if (cls == NULL) {
dprintf("calloc failed\n");
return NULL;
}
safestrcpy(cls->name, name);
safestrcpy(cls->path, classpath);
if ((sysfs_remove_trailing_slash(cls->path)) != 0) {
dprintf("Invalid path to class device %s\n", cls->path);
sysfs_close_class(cls);
return NULL;
}
return cls;
}
/**
* sysfs_get_class_device: Get specific class device using the device's id
* @class: class to find device on
* @name: class name of the device
*/
struct sysfs_class_device *sysfs_get_class_device(struct sysfs_class *cls,
char *name)
{
if (cls == NULL || name == NULL) {
errno = EINVAL;
return NULL;
}
if (cls->devices == NULL) {
cls->devices = sysfs_get_class_devices(cls);
if (cls->devices == NULL)
return NULL;
}
return (struct sysfs_class_device *)dlist_find_custom(cls->devices,
name, class_name_equal);
}
/**
* sysfs_get_classdev_device: returns the sysfs_device corresponding to
* sysfs_class_device, if present
* @clsdev: class device whose sysfs_device is required
* Returns sysfs_device on success, NULL on error or if device is not
* implemented
*/
struct sysfs_device *sysfs_get_classdev_device
(struct sysfs_class_device *clsdev)
{
struct sysfs_link *devlink = NULL;
char devpath[SYSFS_PATH_MAX];
if (clsdev == NULL) {
errno = EINVAL;
return NULL;
}
safestrcpy(devpath, clsdev->path);
safestrcat(devpath, "/device");
if ((sysfs_path_is_link(devpath)) != 0) {
if (clsdev->sysdevice != NULL) {
sysfs_close_device(clsdev->sysdevice);
clsdev->sysdevice = NULL;
}
return NULL;
}
if (clsdev->directory == NULL) {
clsdev->directory = sysfs_open_directory(clsdev->path);
if (clsdev->directory == NULL)
return NULL;
}
devlink = sysfs_get_directory_link(clsdev->directory, "device");
if (devlink == NULL) {
if (clsdev->sysdevice != NULL) {
dprintf("Device link no longer exists\n");
sysfs_close_device(clsdev->sysdevice);
clsdev->sysdevice = NULL;
}
return NULL;
}
if (clsdev->sysdevice != NULL) {
if (!strncmp(devlink->target, clsdev->sysdevice->path,
SYSFS_PATH_MAX))
/* sysdevice hasn't changed */
return (clsdev->sysdevice);
else
/* come here only if the device link for has changed */
sysfs_close_device(clsdev->sysdevice);
}
clsdev->sysdevice = sysfs_open_device_path(devlink->target);
if (clsdev->sysdevice == NULL)
return NULL;
return (clsdev->sysdevice);
}
/**
* sysfs_get_classdev_driver: returns the sysfs_driver corresponding to
* sysfs_class_device, if present
* @clsdev: class device whose sysfs_device is required
* Returns sysfs_driver on success, NULL on error or if driver is not
* implemented
*/
struct sysfs_driver *sysfs_get_classdev_driver
(struct sysfs_class_device *clsdev)
{
struct sysfs_link *drvlink = NULL;
char drvpath[SYSFS_PATH_MAX];
if (clsdev == NULL) {
errno = EINVAL;
return NULL;
}
safestrcpy(drvpath, clsdev->path);
safestrcat(drvpath, "/driver");
if ((sysfs_path_is_link(drvpath)) != 0) {
if (clsdev->driver != NULL) {
sysfs_close_driver(clsdev->driver);
clsdev->driver = NULL;
}
return NULL;
}
if (clsdev->directory == NULL) {
clsdev->directory = sysfs_open_directory(clsdev->path);
if (clsdev->directory == NULL)
return NULL;
}
drvlink = sysfs_get_directory_link(clsdev->directory, "driver");
if (drvlink == NULL) {
if (clsdev->driver != NULL) {
dprintf("Driver link no longer exists\n");
sysfs_close_driver(clsdev->driver);
clsdev->driver = NULL;
}
return NULL;
}
if (clsdev->driver != NULL) {
if (!strncmp(drvlink->target, clsdev->driver->path,
SYSFS_PATH_MAX))
/* driver hasn't changed */
return (clsdev->driver);
else
/* come here only if the device link for has changed */
sysfs_close_driver(clsdev->driver);
}
clsdev->driver = sysfs_open_driver_path(drvlink->target);
if (clsdev->driver == NULL)
return NULL;
return (clsdev->driver);
}
/**
* get_blockdev_parent: Get the parent class device for a "block" subsystem
* device if present
@ -415,7 +131,8 @@ struct sysfs_driver *sysfs_get_classdev_driver
*/
static int get_blockdev_parent(struct sysfs_class_device *clsdev)
{
char parent_path[SYSFS_PATH_MAX], *c = NULL;
char parent_path[SYSFS_PATH_MAX];
char *c;
safestrcpy(parent_path, clsdev->path);
c = strstr(parent_path, SYSFS_BLOCK_NAME);
@ -430,20 +147,20 @@ static int get_blockdev_parent(struct sysfs_class_device *clsdev)
else
goto errout;
/* validate whether the given class device is a partition or not */
if ((strncmp(c, clsdev->name, strlen(clsdev->name))) == 0) {
dprintf("%s not a partition\n", clsdev->name);
return 1;
}
c = strchr(c, '/');
/* validate whether the given class device is a partition or not */
if ((strncmp(c, clsdev->name, strlen(clsdev->name))) == 0) {
dprintf("%s not a partition\n", clsdev->name);
return 1;
}
c = strchr(c, '/');
if (c == NULL)
goto errout;
*c = '\0';
clsdev->parent = sysfs_open_class_device_path(parent_path);
if (clsdev->parent == NULL) {
if (!clsdev->parent) {
dprintf("Error opening the parent class device at %s\n",
parent_path);
return 1;
@ -466,19 +183,19 @@ errout:
struct sysfs_class_device *sysfs_get_classdev_parent
(struct sysfs_class_device *clsdev)
{
if (clsdev == NULL) {
if (!clsdev) {
errno = EINVAL;
return NULL;
}
if (clsdev->parent != NULL)
if (clsdev->parent)
return (clsdev->parent);
/*
/*
* As of now, only block devices have a parent child heirarchy in sysfs
* We do not know, if, in the future, more classes will have a similar
* structure. Hence, we now call a specialized function for block and
* later we can add support functions for other subsystems as required.
*/
*/
if (!(strncmp(clsdev->classname, SYSFS_BLOCK_NAME,
sizeof(SYSFS_BLOCK_NAME)))) {
if ((get_blockdev_parent(clsdev)) == 0)
@ -499,13 +216,13 @@ struct sysfs_class_device *sysfs_get_classdev_parent
static int get_classdev_path(const char *classname, const char *clsdev,
char *path, size_t len)
{
if (classname == NULL || clsdev == NULL || path == NULL) {
if (!classname || !clsdev || !path) {
errno = EINVAL;
return -1;
}
if (sysfs_get_mnt_path(path, len) != 0) {
dprintf("Error getting sysfs mount path\n");
return -1;
if (sysfs_get_mnt_path(path, len) != 0) {
dprintf("Error getting sysfs mount path\n");
return -1;
}
if (strncmp(classname, SYSFS_BLOCK_NAME,
sizeof(SYSFS_BLOCK_NAME)) == 0) {
@ -535,9 +252,9 @@ struct sysfs_class_device *sysfs_open_class_device
(const char *classname, const char *name)
{
char devpath[SYSFS_PATH_MAX];
struct sysfs_class_device *cdev = NULL;
struct sysfs_class_device *cdev;
if (classname == NULL || name == NULL) {
if (!classname || !name) {
errno = EINVAL;
return NULL;
}
@ -549,9 +266,9 @@ struct sysfs_class_device *sysfs_open_class_device
name, classname);
return NULL;
}
cdev = sysfs_open_class_device_path(devpath);
if (cdev == NULL) {
if (!cdev) {
dprintf("Error getting class device %s from class %s\n",
name, classname);
return NULL;
@ -559,57 +276,6 @@ struct sysfs_class_device *sysfs_open_class_device
return cdev;
}
/**
* sysfs_get_classdev_attributes: returns a dlist of attributes for
* the requested class_device
* @cdev: sysfs_class_dev for which attributes are needed
* returns a dlist of attributes if exists, NULL otherwise
*/
struct dlist *sysfs_get_classdev_attributes(struct sysfs_class_device *cdev)
{
if (cdev == NULL)
return NULL;
if (cdev->directory == NULL) {
cdev->directory = sysfs_open_directory(cdev->path);
if (cdev->directory == NULL)
return NULL;
}
if (cdev->directory->attributes == NULL) {
if ((sysfs_read_dir_attributes(cdev->directory)) != 0)
return NULL;
}
return (cdev->directory->attributes);
}
/**
* sysfs_refresh_clsassdev_attributes: refreshes the driver's list of attributes
* @clsdev: sysfs_class_device whose attributes to refresh
*
* NOTE: Upon return, prior references to sysfs_attributes for this classdev
* _may_ not be valid
*
* Returns list of attributes on success and NULL on failure
*/
struct dlist *sysfs_refresh_classdev_attributes
(struct sysfs_class_device *clsdev)
{
if (clsdev == NULL) {
errno = EINVAL;
return NULL;
}
if (clsdev->directory == NULL)
return (sysfs_get_classdev_attributes(clsdev));
if ((sysfs_refresh_dir_attributes(clsdev->directory)) != 0) {
dprintf("Error refreshing class_device attributes\n");
return NULL;
}
return (clsdev->directory->attributes);
}
/**
* sysfs_get_classdev_attr: searches class device's attributes by name
* @clsdev: class device to look through
@ -619,90 +285,53 @@ struct dlist *sysfs_refresh_classdev_attributes
struct sysfs_attribute *sysfs_get_classdev_attr
(struct sysfs_class_device *clsdev, const char *name)
{
struct sysfs_attribute *cur = NULL;
struct sysfs_directory *sdir = NULL;
struct dlist *attrlist = NULL;
if (clsdev == NULL || name == NULL) {
if (!clsdev || !name) {
errno = EINVAL;
return NULL;
}
/*
* First, see if it's in the current directory. Then look at
* subdirs since class devices can have subdirs of attributes.
*/
attrlist = sysfs_get_classdev_attributes(clsdev);
if (attrlist != NULL) {
cur = sysfs_get_directory_attribute(clsdev->directory,
(char *)name);
if (cur != NULL)
return cur;
}
if (clsdev->directory == NULL)
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_attribute(clsdev, (char *)name);
}
/**
* 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_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 sysfs_attribute *sysfs_open_classdev_attr(const char *classname,
const char *dev, const char *attrib)
struct dlist *sysfs_get_classdev_attributes(struct sysfs_class_device *clsdev)
{
struct sysfs_attribute *attribute = NULL;
char path[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;
}
return attribute;
return get_attributes_list(clsdev);
}
/**
* 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_device *sysfs_get_classdev_device
(struct sysfs_class_device *clsdev)
{
char linkpath[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX];
if (!clsdev) {
errno = EINVAL;
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 clsdev->sysdevice;
}

View File

@ -3,7 +3,7 @@
*
* Generic device utility functions for libsysfs
*
* Copyright (C) IBM Corp. 2003
* Copyright (C) IBM Corp. 2003-2005
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -24,48 +24,64 @@
#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;
}
if (dev->bus[0] == '\0')
return 1;
memset(path, 0, SYSFS_PATH_MAX);
memset(devpath, 0, SYSFS_PATH_MAX);
safestrcpy(path, SYSFS_BUS_NAME);
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;
memset(path, 0, SYSFS_PATH_MAX);
memset(devpath, 0, SYSFS_PATH_MAX);
safestrcpy(path, dev->path);
c = strstr(path, SYSFS_DEVICES_NAME);
if (c == NULL) {
dprintf("Invalid path to device - %s\n", dev->path);
return -1;
} else
*c = '\0';
safestrcat(path, SYSFS_BUS_NAME);
safestrcat(path, "/");
safestrcat(path, dev->bus);
safestrcat(path, "/");
safestrcat(path, SYSFS_DRIVERS_NAME);
safestrcpy(devpath, dev->path);
c = strstr(devpath, SYSFS_DEVICES_NAME);
if (c == NULL)
return 1;
*c = '\0';
safestrcatmax(c, path, (sizeof(devpath) - strlen(devpath)));
drvlist = sysfs_open_subsystem_list(path);
if (drvlist != NULL) {
drvlist = sysfs_open_directory_list(path);
if (drvlist) {
dlist_for_each_data(drvlist, drv, char) {
safestrcpy(path, devpath);
safestrcat(path, "/");
safestrcat(path, drv);
safestrcat(path, "/");
safestrcat(path, dev->bus_id);
if (sysfs_path_is_link(path) == 0) {
safestrcpy(devpath, path);
safestrcat(devpath, "/");
safestrcat(devpath, drv);
safestrcat(devpath, "/");
safestrcat(devpath, dev->bus_id);
if (sysfs_path_is_link(devpath) == 0) {
safestrcpy(dev->driver_name, drv);
sysfs_close_list(drvlist);
return 0;
@ -73,35 +89,9 @@ static int get_dev_driver(struct sysfs_device *dev)
}
sysfs_close_list(drvlist);
}
return 1;
return -1;
}
/*
* get_device_driver_name: gets device's driver name, searches for driver
* link first before going the brute force route.
* @dev: device to retrieve driver
* returns 0 with success and 1 with error
*/
static int get_device_driver_name(struct sysfs_device *dev)
{
char devpath[SYSFS_PATH_MAX], drvpath[SYSFS_PATH_MAX];
if (dev == NULL) {
errno = EINVAL;
return 1;
}
memset(devpath, 0, SYSFS_PATH_MAX);
memset(drvpath, 0, SYSFS_PATH_MAX);
safestrcpy(devpath, dev->path);
safestrcat(devpath, "/driver");
if ((sysfs_get_link(devpath, drvpath, SYSFS_PATH_MAX)) != 0)
return(get_dev_driver(dev));
return (sysfs_get_name_from_path(drvpath, dev->driver_name,
SYSFS_NAME_LEN));
}
/**
* sysfs_get_device_bus: retrieves the bus name the device is on, checks path
* to bus' link to make sure it has correct device.
@ -110,31 +100,49 @@ static int get_device_driver_name(struct sysfs_device *dev)
*/
int sysfs_get_device_bus(struct sysfs_device *dev)
{
char subsys[SYSFS_NAME_LEN], path[SYSFS_PATH_MAX];
char target[SYSFS_PATH_MAX], *bus = NULL, *c = NULL;
struct dlist *buslist = NULL;
char devpath[SYSFS_PATH_MAX];
char subsys[SYSFS_NAME_LEN];
char path[SYSFS_PATH_MAX];
char target[SYSFS_PATH_MAX];
char *bus = NULL, *c;
struct dlist *buslist;
if (dev == NULL) {
if (!dev) {
errno = EINVAL;
return -1;
}
memset(path, 0, SYSFS_PATH_MAX);
memset(devpath, 0, SYSFS_PATH_MAX);
safestrcpymax(path, dev->path, SYSFS_PATH_MAX);
safestrcatmax(path, "/bus", SYSFS_PATH_MAX);
if (!sysfs_path_is_link(path)) {
if (!sysfs_get_link(path, devpath, SYSFS_PATH_MAX)) {
if (sysfs_get_name_from_path(devpath,
dev->bus, SYSFS_NAME_LEN))
return -1;
}
return 0;
}
/*
* Devices on on earlier kernels do not have the "bus" link.
* Look it up in the bus directory.
*/
memset(subsys, 0, SYSFS_NAME_LEN);
safestrcpy(subsys, SYSFS_BUS_NAME); /* subsys = bus */
buslist = sysfs_open_subsystem_list(subsys);
if (buslist != NULL) {
safestrcpy(subsys, dev->path);
c = strstr(subsys, SYSFS_DEVICES_NAME);
if (c == NULL) {
dprintf("Invalid path to device - %s\n", dev->path);
return -1;
} else
*c = '\0';
safestrcat(subsys, SYSFS_BUS_NAME);
buslist = sysfs_open_directory_list(subsys);
if (buslist) {
dlist_for_each_data(buslist, bus, char) {
memset(path, 0, SYSFS_PATH_MAX);
safestrcpy(path, dev->path);
c = strstr(path, "/devices");
if (c == NULL) {
dprintf("Invalid path to device %s\n", path);
sysfs_close_list(buslist);
return -1;
}
*c = '\0';
safestrcat(path, "/");
safestrcat(path, SYSFS_BUS_NAME);
safestrcpy(path, subsys);
safestrcat(path, "/");
safestrcat(path, bus);
safestrcat(path, "/");
@ -143,8 +151,8 @@ int sysfs_get_device_bus(struct sysfs_device *dev)
safestrcat(path, dev->bus_id);
if ((sysfs_path_is_link(path)) == 0) {
memset(target, 0, SYSFS_PATH_MAX);
if ((sysfs_get_link(path, target,
SYSFS_PATH_MAX)) != 0) {
if (sysfs_get_link(path, target,
SYSFS_PATH_MAX)) {
dprintf("Error getting link target\n");
sysfs_close_list(buslist);
return -1;
@ -156,10 +164,10 @@ int sysfs_get_device_bus(struct sysfs_device *dev)
return 0;
}
}
}
sysfs_close_list(buslist);
}
return -1;
}
sysfs_close_list(buslist);
}
return -1;
}
/**
@ -169,8 +177,8 @@ int sysfs_get_device_bus(struct sysfs_device *dev)
*/
void sysfs_close_device_tree(struct sysfs_device *devroot)
{
if (devroot != NULL) {
if (devroot->children != NULL) {
if (devroot) {
if (devroot->children) {
struct sysfs_device *child = NULL;
dlist_for_each_data(devroot->children, child,
@ -182,27 +190,19 @@ void sysfs_close_device_tree(struct sysfs_device *devroot)
}
}
/**
* sysfs_close_dev_tree: routine for dlist integration
*/
static void sysfs_close_dev_tree(void *dev)
{
sysfs_close_device_tree((struct sysfs_device *)dev);
}
/**
* sysfs_close_device: closes and cleans up a device
* @dev = device to clean up
*/
void sysfs_close_device(struct sysfs_device *dev)
{
if (dev != NULL) {
if (dev->parent != NULL)
if (dev) {
if (dev->parent)
sysfs_close_device(dev->parent);
if (dev->directory != NULL)
sysfs_close_directory(dev->directory);
if (dev->children != NULL && dev->children->count == 0)
if (dev->children && dev->children->count)
dlist_destroy(dev->children);
if (dev->attrlist)
dlist_destroy(dev->attrlist);
free(dev);
}
}
@ -213,36 +213,7 @@ void sysfs_close_device(struct sysfs_device *dev)
*/
static struct sysfs_device *alloc_device(void)
{
return (struct sysfs_device *)calloc(1, sizeof(struct sysfs_device));
}
/**
* open_device_dir: opens up sysfs_directory for specific root dev
* @name: name of root
* returns struct sysfs_directory with success and NULL with error
*/
static struct sysfs_directory *open_device_dir(const char *path)
{
struct sysfs_directory *rdir = NULL;
if (path == NULL) {
errno = EINVAL;
return NULL;
}
rdir = sysfs_open_directory(path);
if (rdir == NULL) {
errno = EINVAL;
dprintf ("Device %s not supported on this system\n", path);
return NULL;
}
if ((sysfs_read_dir_subdirs(rdir)) != 0) {
dprintf ("Error reading device at dir %s\n", path);
sysfs_close_directory(rdir);
return NULL;
}
return rdir;
return (struct sysfs_device *) calloc(1, sizeof(struct sysfs_device));
}
/**
@ -252,45 +223,44 @@ static struct sysfs_directory *open_device_dir(const char *path)
*/
struct sysfs_device *sysfs_open_device_path(const char *path)
{
struct sysfs_device *dev = NULL;
struct sysfs_device *dev;
if (path == NULL) {
if (!path) {
errno = EINVAL;
return NULL;
}
if ((sysfs_path_is_dir(path)) != 0) {
if (sysfs_path_is_dir(path)) {
dprintf("Incorrect path to device: %s\n", path);
return NULL;
}
dev = alloc_device();
if (dev == NULL) {
dev = alloc_device();
if (!dev) {
dprintf("Error allocating device at %s\n", path);
return NULL;
}
if ((sysfs_get_name_from_path(path, dev->bus_id,
SYSFS_NAME_LEN)) != 0) {
if (sysfs_get_name_from_path(path, dev->bus_id, SYSFS_NAME_LEN)) {
errno = EINVAL;
dprintf("Error getting device bus_id\n");
sysfs_close_device(dev);
return NULL;
}
safestrcpy(dev->path, path);
if ((sysfs_remove_trailing_slash(dev->path)) != 0) {
if (sysfs_remove_trailing_slash(dev->path)) {
dprintf("Invalid path to device %s\n", dev->path);
sysfs_close_device(dev);
return NULL;
}
/*
/*
* The "name" attribute no longer exists... return the device's
* sysfs representation instead, in the "dev->name" field, which
* implies that the dev->name and dev->bus_id contain same data.
*/
safestrcpy(dev->name, dev->bus_id);
if (sysfs_get_device_bus(dev) != 0)
if (sysfs_get_device_bus(dev))
dprintf("Could not get device bus\n");
if (get_device_driver_name(dev) != 0) {
if (get_dev_driver(dev)) {
dprintf("Could not get device %s's driver\n", dev->bus_id);
safestrcpy(dev->driver_name, SYSFS_UNKNOWN);
}
@ -298,207 +268,6 @@ struct sysfs_device *sysfs_open_device_path(const char *path)
return dev;
}
/**
* sysfs_open_device_tree: opens root device and all of its children,
* creating a tree of devices. Only opens children.
* @path: sysfs path to devices
* returns struct sysfs_device and its children with success or NULL with
* error.
*/
struct sysfs_device *sysfs_open_device_tree(const char *path)
{
struct sysfs_device *rootdev = NULL, *new = NULL;
struct sysfs_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
*/
struct dlist *sysfs_refresh_device_attributes(struct sysfs_device *device)
{
if (device == NULL) {
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);
}
/**
* sysfs_get_device_attr: searches dev's attributes by name
* @dev: device to look through
@ -508,18 +277,25 @@ struct dlist *sysfs_refresh_device_attributes(struct sysfs_device *device)
struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev,
const char *name)
{
struct dlist *attrlist = NULL;
if (dev == NULL || name == NULL) {
if (!dev || !name) {
errno = EINVAL;
return NULL;
}
attrlist = sysfs_get_device_attributes(dev);
if (attrlist == NULL)
return NULL;
return get_attribute(dev, (char *)name);
}
return sysfs_get_directory_attribute(dev->directory, (char *)name);
/**
* 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 dlist *sysfs_get_device_attributes(struct sysfs_device *dev)
{
if (!dev) {
errno = EINVAL;
return NULL;
}
return get_attributes_list(dev);
}
/**
@ -535,13 +311,13 @@ static int get_device_absolute_path(const char *device, const char *bus,
{
char bus_path[SYSFS_PATH_MAX];
if (device == NULL || path == NULL) {
if (!device || !path) {
errno = EINVAL;
return -1;
}
memset(bus_path, 0, SYSFS_PATH_MAX);
if (sysfs_get_mnt_path(bus_path, SYSFS_PATH_MAX) != 0) {
if (sysfs_get_mnt_path(bus_path, SYSFS_PATH_MAX)) {
dprintf ("Sysfs not supported on this system\n");
return -1;
}
@ -557,7 +333,7 @@ static int get_device_absolute_path(const char *device, const char *bus,
* We now are at /sys/bus/"bus_name"/devices/"device" which is a link.
* Now read this link to reach to the device.
*/
if ((sysfs_get_link(bus_path, path, psize)) != 0) {
if (sysfs_get_link(bus_path, path, psize)) {
dprintf("Error getting to device %s\n", device);
return -1;
}
@ -578,21 +354,21 @@ static int get_device_absolute_path(const char *device, const char *bus,
struct sysfs_device *sysfs_open_device(const char *bus, const char *bus_id)
{
char sysfs_path[SYSFS_PATH_MAX];
struct sysfs_device *device = NULL;
struct sysfs_device *device;
if (bus_id == NULL || bus == NULL) {
if (!bus_id || !bus) {
errno = EINVAL;
return NULL;
}
memset(sysfs_path, 0, SYSFS_PATH_MAX);
if ((get_device_absolute_path(bus_id, bus, sysfs_path,
SYSFS_PATH_MAX)) != 0) {
if (get_device_absolute_path(bus_id, bus, sysfs_path,
SYSFS_PATH_MAX)) {
dprintf("Error getting to device %s\n", bus_id);
return NULL;
}
device = sysfs_open_device_path(sysfs_path);
if (device == NULL) {
if (!device) {
dprintf("Error opening device %s\n", bus_id);
return NULL;
}
@ -608,20 +384,20 @@ struct sysfs_device *sysfs_open_device(const char *bus, const char *bus_id)
*/
struct sysfs_device *sysfs_get_device_parent(struct sysfs_device *dev)
{
char ppath[SYSFS_PATH_MAX], *tmp = NULL;
char ppath[SYSFS_PATH_MAX], *tmp;
if (dev == NULL) {
if (!dev) {
errno = EINVAL;
return NULL;
}
if (dev->parent != NULL)
if (dev->parent)
return (dev->parent);
memset(ppath, 0, SYSFS_PATH_MAX);
safestrcpy(ppath, dev->path);
tmp = strrchr(ppath, '/');
if (tmp == NULL) {
if (!tmp) {
dprintf("Invalid path to device %s\n", ppath);
return NULL;
}
@ -634,68 +410,22 @@ struct sysfs_device *sysfs_get_device_parent(struct sysfs_device *dev)
}
}
*tmp = '\0';
/*
* All "devices" have the "detach_state" attribute - validate here
*/
safestrcat(ppath, "/detach_state");
if ((sysfs_path_is_file(ppath)) != 0) {
if (sysfs_path_is_file(ppath)) {
dprintf("Device at %s does not have a parent\n", dev->path);
return NULL;
}
tmp = strrchr(ppath, '/');
*tmp = '\0';
dev->parent = sysfs_open_device_path(ppath);
if (dev->parent == NULL) {
if (!dev->parent) {
dprintf("Error opening device %s's parent at %s\n",
dev->bus_id, ppath);
return NULL;
}
return (dev->parent);
}
/*
* sysfs_open_device_attr: open the given device's attribute
* @bus: Bus on which to look
* @dev_id: device for which attribute is required
* @attrname: name of the attribute to look for
* Returns struct sysfs_attribute on success and NULL on failure
*
* NOTE:
* A call to sysfs_close_attribute() is required to close
* the attribute returned and free memory.
*/
struct sysfs_attribute *sysfs_open_device_attr(const char *bus,
const char *bus_id, const char *attrib)
{
struct sysfs_attribute *attribute = NULL;
char devpath[SYSFS_PATH_MAX];
if (bus == NULL || bus_id == NULL || attrib == NULL) {
errno = EINVAL;
return NULL;
}
memset(devpath, 0, SYSFS_PATH_MAX);
if ((get_device_absolute_path(bus_id, bus, devpath,
SYSFS_PATH_MAX)) != 0) {
dprintf("Error getting to device %s\n", bus_id);
return NULL;
}
safestrcat(devpath, "/");
safestrcat(devpath, attrib);
attribute = sysfs_open_attribute(devpath);
if (attribute == NULL) {
dprintf("Error opening attribute %s for device %s\n",
attrib, bus_id);
return NULL;
}
if ((sysfs_read_attribute(attribute)) != 0) {
dprintf("Error reading attribute %s for device %s\n",
attrib, bus_id);
sysfs_close_attribute(attribute);
return NULL;
}
return attribute;
}

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
*
* Driver utility functions for libsysfs
*
* Copyright (C) IBM Corp. 2003
* Copyright (C) IBM Corp. 2003-2005
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -28,42 +28,20 @@ static void sysfs_close_driver_device(void *device)
sysfs_close_device((struct sysfs_device *)device);
}
/**
/**
* sysfs_close_driver: closes driver and deletes device lists too
* @driver: driver to close
*/
*/
void sysfs_close_driver(struct sysfs_driver *driver)
{
if (driver != NULL) {
if (driver->devices != NULL)
if (driver) {
if (driver->devices)
dlist_destroy(driver->devices);
if (driver->directory != NULL)
sysfs_close_directory(driver->directory);
if (driver->attrlist)
dlist_destroy(driver->attrlist);
free(driver);
}
}
/**
* open_driver_dir: Open the sysfs_directory for this driver
* @driver: Driver whose directory to be opened
* Returns 0 on success and 1 on failure
*/
static int open_driver_dir(struct sysfs_driver *driver)
{
if (driver == NULL) {
errno = EINVAL;
return 1;
}
if (driver->directory == NULL) {
driver->directory = sysfs_open_directory(driver->path);
if (driver->directory == NULL) {
dprintf("Error opening driver directory at %s\n",
driver->path);
return 1;
}
}
return 0;
}
/**
* alloc_driver: allocates and initializes driver
@ -74,6 +52,65 @@ static struct sysfs_driver *alloc_driver(void)
return (struct sysfs_driver *)calloc(1, sizeof(struct sysfs_driver));
}
/**
* get_driver_bus: gets bus the driver is on
* Returns 0 on success and 1 on error
*/
static int get_driver_bus(struct sysfs_driver *drv)
{
char drvpath[SYSFS_PATH_MAX], *c = NULL;
if (!drv) {
errno = EINVAL;
return 1;
}
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 drv's attributes by name
* @drv: driver to look through
* @name: attribute name to get
* returns sysfs_attribute reference with success or NULL with error.
*/
struct sysfs_attribute *sysfs_get_driver_attr(struct sysfs_driver *drv,
const char *name)
{
if (!drv || !name) {
errno = EINVAL;
return NULL;
}
return get_attribute(drv, (char *)name);
}
/**
* 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_attributes(struct sysfs_driver *drv)
{
if (!drv) {
errno = EINVAL;
return NULL;
}
return get_attributes_list(drv);
}
/**
* sysfs_open_driver_path: opens and initializes driver structure
* @path: path to driver directory
@ -83,238 +120,39 @@ struct sysfs_driver *sysfs_open_driver_path(const char *path)
{
struct sysfs_driver *driver = NULL;
if (path == NULL) {
if (!path) {
errno = EINVAL;
return NULL;
}
if ((sysfs_path_is_dir(path)) != 0) {
if (sysfs_path_is_dir(path)) {
dprintf("Invalid path to driver: %s\n", path);
return NULL;
}
driver = alloc_driver();
if (driver == NULL) {
if (!driver) {
dprintf("Error allocating driver at %s\n", path);
return NULL;
}
if ((sysfs_get_name_from_path(path, driver->name,
SYSFS_NAME_LEN)) != 0) {
if (sysfs_get_name_from_path(path, driver->name, SYSFS_NAME_LEN)) {
dprintf("Error getting driver name from path\n");
free(driver);
return NULL;
}
safestrcpy(driver->path, path);
if ((sysfs_remove_trailing_slash(driver->path)) != 0) {
if (sysfs_remove_trailing_slash(driver->path)) {
dprintf("Invalid path to driver %s\n", driver->path);
sysfs_close_driver(driver);
return NULL;
}
if (get_driver_bus(driver)) {
dprintf("Could not get the bus driver is on\n");
sysfs_close_driver(driver);
return 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) {
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(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);
}
/**
* sysfs_get_driver_attr: searches driver's attributes by name
* @drv: driver to look through
* @name: attribute name to get
* returns sysfs_attribute reference on success or NULL with error
*/
struct sysfs_attribute *sysfs_get_driver_attr(struct sysfs_driver *drv,
const char *name)
{
struct dlist *attrlist = NULL;
if (drv == NULL) {
errno = EINVAL;
return NULL;
}
attrlist = sysfs_get_driver_attributes(drv);
if (attrlist == NULL)
return NULL;
return sysfs_get_directory_attribute(drv->directory, (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
*/
struct dlist *sysfs_get_driver_links(struct sysfs_driver *driver)
{
if (driver == NULL) {
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);
}
/**
* 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)
{
struct sysfs_link *curlink = NULL;
struct sysfs_device *device = NULL;
if (driver == NULL) {
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);
}
}
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;
return NULL;
}
if (driver->devices != NULL) {
dlist_destroy(driver->devices);
driver->devices = 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");
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;
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;
}
/**
* get_driver_path: looks up the bus the driver is on and builds path to
* the driver.
@ -327,11 +165,11 @@ struct sysfs_device *sysfs_get_driver_device(struct sysfs_driver *driver,
static int get_driver_path(const char *bus, const char *drv,
char *path, size_t psize)
{
if (bus == NULL || drv == NULL || path == NULL || psize == 0) {
if (!bus || !drv || !path || psize == 0) {
errno = EINVAL;
return -1;
}
if (sysfs_get_mnt_path(path, psize) != 0) {
if (sysfs_get_mnt_path(path, psize)) {
dprintf("Error getting sysfs mount path\n");
return -1;
}
@ -346,50 +184,6 @@ static int get_driver_path(const char *bus, const char *drv,
return 0;
}
/**
* sysfs_open_driver_attr: read the user supplied driver attribute
* @bus: bus on which to look
* @drv: driver whose attribute has to be read
* @attrib: Attribute to be read
* Returns struct sysfs_attribute on success and NULL on failure
*
* NOTE:
* A call to sysfs_close_attribute() is required to close the
* attribute returned and to free memory
*/
struct sysfs_attribute *sysfs_open_driver_attr(const char *bus,
const char *drv, const char *attrib)
{
struct sysfs_attribute *attribute = NULL;
char path[SYSFS_PATH_MAX];
if (bus == NULL || drv == NULL || attrib == NULL) {
errno = EINVAL;
return NULL;
}
memset(path, 0, SYSFS_PATH_MAX);
if ((get_driver_path(bus, drv, path, SYSFS_PATH_MAX)) != 0) {
dprintf("Error getting to driver %s\n", drv);
return NULL;
}
safestrcat(path, "/");
safestrcat(path, attrib);
attribute = sysfs_open_attribute(path);
if (attribute == NULL) {
dprintf("Error opening attribute %s for driver %s\n",
attrib, drv);
return NULL;
}
if ((sysfs_read_attribute(attribute)) != 0) {
dprintf("Error reading attribute %s for driver %s\n",
attrib, drv);
sysfs_close_attribute(attribute);
return NULL;
}
return attribute;
}
/**
* sysfs_open_driver: open driver by name, given its bus
* @bus_name: Name of the bus
@ -402,21 +196,66 @@ struct sysfs_driver *sysfs_open_driver(const char *bus_name,
char path[SYSFS_PATH_MAX];
struct sysfs_driver *driver = NULL;
if (drv_name == NULL || bus_name == NULL) {
if (!drv_name || !bus_name) {
errno = EINVAL;
return NULL;
}
memset(path, 0, SYSFS_PATH_MAX);
if ((get_driver_path(bus_name, drv_name, path, SYSFS_PATH_MAX)) != 0) {
if (get_driver_path(bus_name, drv_name, path, SYSFS_PATH_MAX)) {
dprintf("Error getting to driver %s\n", drv_name);
return NULL;
}
driver = sysfs_open_driver_path(path);
if (driver == NULL) {
if (!driver) {
dprintf("Error opening driver at %s\n", path);
return NULL;
}
return driver;
}
/**
* sysfs_get_driver_devices: gets list of devices that use the driver
* @drv: sysfs_driver whose device list is needed
* Returns dlist of struct sysfs_device on success and NULL on failure
*/
struct dlist *sysfs_get_driver_devices(struct sysfs_driver *drv)
{
char *ln = NULL;
struct dlist *linklist = NULL;
struct sysfs_device *dev = NULL;
if (!drv) {
errno = EINVAL;
return NULL;
}
linklist = read_dir_links(drv->path);
if (linklist) {
dlist_for_each_data(linklist, ln, char) {
if (!strncmp(ln, SYSFS_MODULE_NAME, strlen(ln)))
continue;
dev = sysfs_open_device(drv->bus, ln);
if (!dev) {
dprintf("Error opening driver's device\n");
sysfs_close_list(linklist);
return NULL;
}
if (!drv->devices) {
drv->devices = dlist_new_with_delete
(sizeof(struct sysfs_device),
sysfs_close_driver_device);
if (!drv->devices) {
dprintf("Error creating device list\n");
sysfs_close_list(linklist);
return NULL;
}
}
dlist_unshift_sorted(drv->devices, dev, sort_list);
}
sysfs_close_list(linklist);
}
return drv->devices;
}

View File

@ -23,12 +23,6 @@
#include "libsysfs.h"
#include "sysfs.h"
static int sort_char(void *new, void *old)
{
return ((strncmp((char *)new, (char *)old,
strlen((char *)new))) < 0 ? 1 : 0);
}
/**
* sysfs_remove_trailing_slash: Removes any trailing '/' in the given path
* @path: Path to look for the trailing '/'
@ -38,7 +32,7 @@ int sysfs_remove_trailing_slash(char *path)
{
char *c = NULL;
if (path == NULL) {
if (!path) {
errno = EINVAL;
return 1;
}
@ -53,54 +47,6 @@ int sysfs_remove_trailing_slash(char *path)
return 0;
}
/**
* sysfs_get_fs_mnt_path: Gets the mount point for specified filesystem.
* @fs_type: filesystem type to retrieve mount point
* @mnt_path: place to put the retrieved mount path
* @len: size of mnt_path
* returns 0 with success and -1 with error.
*/
static int sysfs_get_fs_mnt_path(const char *fs_type,
char *mnt_path, size_t len)
{
FILE *mnt;
struct mntent *mntent;
int ret = 0;
size_t dirlen = 0;
/* check arg */
if (fs_type == NULL || mnt_path == NULL || len == 0) {
errno = EINVAL;
return -1;
}
if ((mnt = setmntent(SYSFS_PROC_MNTS, "r")) == NULL) {
dprintf("Error getting mount information\n");
return -1;
}
while (ret == 0 && dirlen == 0 && (mntent = getmntent(mnt)) != NULL) {
if (strcmp(mntent->mnt_type, fs_type) == 0) {
dirlen = strlen(mntent->mnt_dir);
if (dirlen <= (len - 1)) {
safestrcpymax(mnt_path, mntent->mnt_dir, len);
} else {
dprintf("Error - mount path too long\n");
ret = -1;
}
}
}
endmntent(mnt);
if (dirlen == 0 && ret == 0) {
dprintf("Filesystem %s not found!\n", fs_type);
errno = EINVAL;
ret = -1;
}
if ((sysfs_remove_trailing_slash(mnt_path)) != 0)
ret = -1;
return ret;
}
/*
* sysfs_get_mnt_path: Gets the sysfs mount point.
* @mnt_path: place to put "sysfs" mount point
@ -109,22 +55,21 @@ static int sysfs_get_fs_mnt_path(const char *fs_type,
*/
int sysfs_get_mnt_path(char *mnt_path, size_t len)
{
char *sysfs_path = NULL;
int ret = 0;
static char sysfs_path[SYSFS_PATH_MAX] = "";
const char *sysfs_path_env;
if (mnt_path == NULL || len == 0) {
errno = EINVAL;
return -1;
/* evaluate only at the first call */
if (sysfs_path[0] == '\0') {
/* possible overrride of real mount path */
sysfs_path_env = getenv(SYSFS_PATH_ENV);
if (sysfs_path_env != NULL) {
safestrcpymax(mnt_path, sysfs_path_env, len);
return 0;
}
safestrcpymax(mnt_path, SYSFS_MNT_PATH, len);
}
sysfs_path = getenv(SYSFS_PATH_ENV);
if (sysfs_path != NULL) {
safestrcpymax(mnt_path, sysfs_path, len);
if ((sysfs_remove_trailing_slash(mnt_path)) != 0)
return 1;
} else
ret = sysfs_get_fs_mnt_path(SYSFS_FSTYPE_NAME, mnt_path, len);
return ret;
return 0;
}
/**
@ -137,8 +82,8 @@ int sysfs_get_name_from_path(const char *path, char *name, size_t len)
{
char tmp[SYSFS_PATH_MAX];
char *n = NULL;
if (path == NULL || name == NULL || len == 0) {
if (!path || !name || len == 0) {
errno = EINVAL;
return -1;
}
@ -161,7 +106,7 @@ int sysfs_get_name_from_path(const char *path, char *name, size_t len)
safestrcpymax(name, n, len);
return 0;
}
/**
* sysfs_get_link: returns link source
* @path: symbolic link's path
@ -176,7 +121,7 @@ int sysfs_get_link(const char *path, char *target, size_t len)
char *d = NULL, *s = NULL;
int slashes = 0, count = 0;
if (path == NULL || target == NULL || len == 0) {
if (!path || !target || len == 0) {
errno = EINVAL;
return -1;
}
@ -190,15 +135,15 @@ int sysfs_get_link(const char *path, char *target, size_t len)
return -1;
}
d = linkpath;
/*
/*
* Three cases here:
* 1. relative path => format ../..
* 2. absolute path => format /abcd/efgh
* 3. relative path _from_ this dir => format abcd/efgh
*/
*/
switch (*d) {
case '.':
/*
/*
* handle the case where link is of type ./abcd/xxx
*/
safestrcpy(temp_path, devdir);
@ -215,9 +160,8 @@ int sysfs_get_link(const char *path, char *target, size_t len)
}
safestrcpymax(target, temp_path, len);
break;
/*
* relative path
* getting rid of leading "../.."
/*
* relative path, getting rid of leading "../.."
*/
parse_path:
while (*d == '/' || *d == '.') {
@ -254,16 +198,6 @@ parse_path:
return 0;
}
/**
* sysfs_del_name: free function for sysfs_open_subsystem_list
* @name: memory area to be freed
*/
static void sysfs_del_name(void *name)
{
free(name);
}
/**
* sysfs_close_list: generic list free routine
* @list: dlist to free
@ -271,142 +205,22 @@ static void sysfs_del_name(void *name)
*/
void sysfs_close_list(struct dlist *list)
{
if (list != NULL)
if (list)
dlist_destroy(list);
}
/**
* sysfs_open_subsystem_list: gets a list of all supported "name" subsystem
* details from the system
* @name: name of the subsystem, eg., "bus", "class", "devices"
* Returns a dlist of supported names or NULL if subsystem not supported
*/
struct dlist *sysfs_open_subsystem_list(char *name)
* 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], *subsys_name = NULL;
char *c = NULL;
struct sysfs_directory *dir = NULL, *cur = NULL;
struct dlist *list = NULL;
if (name == NULL)
if (!path)
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)
{
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);
return NULL;
}
if (dir->links != NULL) {
list = dlist_new_with_delete(SYSFS_NAME_LEN,
sysfs_del_name);
if (list == NULL) {
dprintf("Error creating list\n");
sysfs_close_directory(dir);
return NULL;
}
dlist_for_each_data(dir->links, cur,
struct sysfs_link) {
device_name = (char *)calloc(1, SYSFS_NAME_LEN);
safestrcpymax(device_name, cur->name, SYSFS_NAME_LEN);
dlist_unshift_sorted(list, device_name, sort_char);
}
}
sysfs_close_directory(dir);
return list;
return (read_dir_subdirs(path));
}
/**
@ -418,7 +232,7 @@ int sysfs_path_is_dir(const char *path)
{
struct stat astats;
if (path == NULL) {
if (!path) {
errno = EINVAL;
return 1;
}
@ -428,7 +242,7 @@ int sysfs_path_is_dir(const char *path)
}
if (S_ISDIR(astats.st_mode))
return 0;
return 1;
}
@ -441,7 +255,7 @@ int sysfs_path_is_link(const char *path)
{
struct stat astats;
if (path == NULL) {
if (!path) {
errno = EINVAL;
return 1;
}
@ -451,7 +265,7 @@ int sysfs_path_is_link(const char *path)
}
if (S_ISLNK(astats.st_mode))
return 0;
return 1;
}
@ -464,7 +278,7 @@ int sysfs_path_is_file(const char *path)
{
struct stat astats;
if (path == NULL) {
if (!path) {
errno = EINVAL;
return 1;
}
@ -474,6 +288,6 @@ int sysfs_path_is_file(const char *path)
}
if (S_ISREG(astats.st_mode))
return 0;
return 1;
}

View File

@ -47,10 +47,6 @@ attributes along the device chain. Useful for finding
unique attributes to compose a rule.
.RB Needs " \-p " specified.
.TP
.B \-s
Print all sysfs devices with the major/minor number, the physical device and
the bus value.
.TP
.B \-h
Print help text.
.SH "FILES"

View File

@ -49,26 +49,13 @@ void log_message (int level, const char *format, ...)
}
#endif
static int print_all_attributes(const char *path)
static void print_all_attributes(struct dlist *attr_list)
{
struct dlist *attributes;
struct sysfs_attribute *attr;
struct sysfs_directory *sysfs_dir;
char value[SYSFS_VALUE_SIZE];
int len;
int retval = 0;
sysfs_dir = sysfs_open_directory(path);
if (sysfs_dir == NULL)
return -1;
attributes = sysfs_get_dir_attributes(sysfs_dir);
if (attributes == NULL) {
retval = -1;
goto exit;
}
dlist_for_each_data(attributes, attr, struct sysfs_attribute) {
dlist_for_each_data(attr_list, attr, struct sysfs_attribute) {
if (attr->value != NULL) {
strfieldcpy(value, attr->value);
len = strlen(value);
@ -92,11 +79,6 @@ static int print_all_attributes(const char *path)
}
}
printf("\n");
exit:
sysfs_close_directory(sysfs_dir);
return retval;
}
static int print_record(struct udevice *udev)
@ -123,6 +105,7 @@ static int print_device_chain(const char *path)
struct sysfs_attribute *attr;
struct sysfs_device *sysfs_dev;
struct sysfs_device *sysfs_dev_parent;
struct dlist *attr_list;
int retval = 0;
/* get the class dev */
@ -147,11 +130,14 @@ static int print_device_chain(const char *path)
/* open sysfs class device directory and print all attributes */
printf(" looking at class device '%s':\n", class_dev->path);
printf(" SUBSYSTEM=\"%s\"\n", class_dev->classname);
if (print_all_attributes(class_dev->path) != 0) {
attr_list = sysfs_get_classdev_attributes(class_dev);
if (attr_list == NULL) {
printf("couldn't open class device directory\n");
retval = -1;
goto exit;
}
print_all_attributes(attr_list);
/* get the device link (if parent exists look here) */
class_dev_parent = sysfs_get_classdev_parent(class_dev);
@ -165,13 +151,20 @@ static int print_device_chain(const char *path)
/* look the device chain upwards */
while (sysfs_dev != NULL) {
attr_list = sysfs_get_device_attributes(sysfs_dev);
if (attr_list == NULL) {
printf("couldn't open device directory\n");
retval = -1;
goto exit;
}
printf(" looking at the device chain at '%s':\n", sysfs_dev->path);
printf(" BUS=\"%s\"\n", sysfs_dev->bus);
printf(" ID=\"%s\"\n", sysfs_dev->bus_id);
printf(" DRIVER=\"%s\"\n", sysfs_dev->driver_name);
/* open sysfs device directory and print all attributes */
print_all_attributes(sysfs_dev->path);
print_all_attributes(attr_list);
sysfs_dev_parent = sysfs_get_device_parent(sysfs_dev);
if (sysfs_dev_parent == NULL)
@ -185,65 +178,9 @@ exit:
return retval;
}
/* print all class/main block devices with major/minor, physical device, driver and bus */
static int print_sysfs_devices(void)
{
struct dlist *subsyslist;
char *class;
subsyslist = sysfs_open_subsystem_list("class");
if (!subsyslist)
return -1;
dlist_for_each_data(subsyslist, class, char) {
struct sysfs_class *cls;
struct dlist *class_devices;
struct sysfs_class_device *class_dev;
struct sysfs_device *phys_dev;
unsigned int major, minor;
cls = sysfs_open_class(class);
if (!cls)
continue;
class_devices = sysfs_get_class_devices(cls);
if (!class_devices)
continue;
dlist_for_each_data(class_devices, class_dev, struct sysfs_class_device) {
struct sysfs_attribute *attr;
printf("\n");
printf("DEVPATH '%s'\n", class_dev->path);
printf("SUBSYSTEM '%s'\n", class_dev->classname);
attr = sysfs_get_classdev_attr(class_dev, "dev");
if (attr) {
sscanf(attr->value, "%u:%u", &major, &minor);
printf("MAJOR %u\n", major);
printf("MINOR %u\n", minor);
}
phys_dev = sysfs_get_classdev_device(class_dev);
if (phys_dev) {
printf("PHYSDEVPATH '%s'\n", phys_dev->path);
if (phys_dev->bus[0] != '\0')
printf("PHYSDEVBUS '%s'\n", phys_dev->bus);
if (phys_dev->driver_name[0] != '\0')
printf("PHYSDEVDRIVER '%s'\n", phys_dev->driver_name);
}
}
sysfs_close_class(cls);
}
sysfs_close_list(subsyslist);
return 0;
}
static int process_options(int argc, char *argv[])
{
static const char short_options[] = "an:p:q:rsVh";
static const char short_options[] = "an:p:q:rVh";
int option;
int retval = 1;
struct udevice udev;
@ -304,10 +241,6 @@ static int process_options(int argc, char *argv[])
root = 1;
break;
case 's':
print_sysfs_devices();
exit(0);
case 'a':
attributes = 1;
break;