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

[PATCH] libsysfs: version 2.0

This commit is contained in:
kay.sievers@vrfy.org 2005-04-15 16:28:56 +02:00 committed by Greg KH
parent d4b6114300
commit 197178360f
9 changed files with 530 additions and 14 deletions

View File

@ -551,7 +551,7 @@ void dlist_sort_custom(struct dlist *list, int (*compare)(void *, void *))
struct dlist *templist;
unsigned int passcount = 1;
unsigned int mergecount = 1;
dlist_start(list);
templist = dlist_new(list->data_size);

View File

@ -3,7 +3,7 @@
*
* Internal Header Definitions 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

View File

@ -50,6 +50,7 @@
* Just use the dlist_(insert|delete)_(before|after) macros if you do not want
* to think about it.
*/
#include <stddef.h>

View File

@ -184,6 +184,21 @@ 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);
extern void sysfs_close_class(struct sysfs_class *cls);
extern struct sysfs_class *sysfs_open_class(const char *name);
extern struct sysfs_class_device *sysfs_get_class_device
(struct sysfs_class *cls, const char *name);
extern struct dlist *sysfs_get_class_devices(struct sysfs_class *cls);
/* 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 dlist *sysfs_get_bus_devices(struct sysfs_bus *bus);
extern struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus);
extern struct sysfs_device *sysfs_get_bus_device
(struct sysfs_bus *bus, const char *id);
extern struct sysfs_driver *sysfs_get_bus_driver
(struct sysfs_bus *bus, const char *drvname);
/**
* sort_list: sorter function to keep list elements sorted in alphabetical

317
libsysfs/sysfs_bus.c Normal file
View File

@ -0,0 +1,317 @@
/*
* sysfs_bus.c
*
* Generic bus utility functions for libsysfs
*
* 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
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "libsysfs.h"
#include "sysfs.h"
static void sysfs_close_dev(void *dev)
{
sysfs_close_device((struct sysfs_device *)dev);
}
static void sysfs_close_drv(void *drv)
{
sysfs_close_driver((struct sysfs_driver *)drv);
}
/*
* compares names.
* @a: name looked for
* @b: sysfs_device comparing being compared
* returns 1 if a==b->name or 0 not equal
*/
static int name_equal(void *a, void *b)
{
if (!a || !b)
return 0;
if (strcmp(((char *)a), ((struct sysfs_device *)b)->name) == 0)
return 1;
return 0;
}
/**
* sysfs_close_bus: close single bus
* @bus: bus structure
*/
void sysfs_close_bus(struct sysfs_bus *bus)
{
if (bus) {
if (bus->attrlist)
dlist_destroy(bus->attrlist);
if (bus->devices)
dlist_destroy(bus->devices);
if (bus->drivers)
dlist_destroy(bus->drivers);
free(bus);
}
}
/**
* alloc_bus: mallocs new bus structure
* returns sysfs_bus_bus struct or NULL
*/
static struct sysfs_bus *alloc_bus(void)
{
return (struct sysfs_bus *)calloc(1, sizeof(struct sysfs_bus));
}
/**
* sysfs_get_bus_devices: gets all devices for bus
* @bus: bus to get devices for
* returns dlist of devices with success and NULL with failure
*/
struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus)
{
struct sysfs_device *dev;
struct dlist *linklist;
char path[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX];
char target[SYSFS_PATH_MAX];
char *curlink;
if (!bus) {
errno = EINVAL;
return NULL;
}
memset(path, 0, SYSFS_PATH_MAX);
safestrcpy(path, bus->path);
safestrcat(path, "/");
safestrcat(path, SYSFS_DEVICES_NAME);
linklist = read_dir_links(path);
if (linklist) {
dlist_for_each_data(linklist, curlink, char) {
if (bus->devices) {
dev = (struct sysfs_device *)
dlist_find_custom(bus->devices,
(void *)curlink, name_equal);
if (dev)
continue;
}
safestrcpy(devpath, path);
safestrcat(devpath, "/");
safestrcat(devpath, curlink);
if (sysfs_get_link(devpath, target, SYSFS_PATH_MAX)) {
dprintf("Error getting link - %s\n", devpath);
continue;
}
dev = sysfs_open_device_path(target);
if (!dev) {
dprintf("Error opening device at %s\n",
target);
continue;
}
if (!bus->devices)
bus->devices = dlist_new_with_delete
(sizeof(struct sysfs_device),
sysfs_close_dev);
dlist_unshift_sorted(bus->devices, dev, sort_list);
}
sysfs_close_list(linklist);
}
return (bus->devices);
}
/**
* sysfs_get_bus_drivers: gets all drivers for bus
* @bus: bus to get devices for
* returns dlist of devices with success and NULL with failure
*/
struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus)
{
struct sysfs_driver *drv;
struct dlist *dirlist;
char path[SYSFS_PATH_MAX], drvpath[SYSFS_PATH_MAX];
char *curdir;
if (!bus) {
errno = EINVAL;
return NULL;
}
memset(path, 0, SYSFS_PATH_MAX);
safestrcpy(path, bus->path);
safestrcat(path, "/");
safestrcat(path, SYSFS_DRIVERS_NAME);
dirlist = read_dir_subdirs(path);
if (dirlist) {
dlist_for_each_data(dirlist, curdir, char) {
if (bus->drivers) {
drv = (struct sysfs_driver *)
dlist_find_custom(bus->drivers,
(void *)curdir, name_equal);
if (drv)
continue;
}
safestrcpy(drvpath, path);
safestrcat(drvpath, "/");
safestrcat(drvpath, curdir);
drv = sysfs_open_driver_path(drvpath);
if (!drv) {
dprintf("Error opening driver at %s\n",
drvpath);
continue;
}
if (!bus->drivers)
bus->drivers = dlist_new_with_delete
(sizeof(struct sysfs_driver),
sysfs_close_drv);
dlist_unshift_sorted(bus->drivers, drv, sort_list);
}
sysfs_close_list(dirlist);
}
return (bus->drivers);
}
/**
* sysfs_open_bus: opens specific bus and all its devices on system
* returns sysfs_bus structure with success or NULL with error.
*/
struct sysfs_bus *sysfs_open_bus(const char *name)
{
struct sysfs_bus *bus;
char buspath[SYSFS_PATH_MAX];
if (!name) {
errno = EINVAL;
return NULL;
}
memset(buspath, 0, SYSFS_PATH_MAX);
if (sysfs_get_mnt_path(buspath, SYSFS_PATH_MAX)) {
dprintf("Sysfs not supported on this system\n");
return NULL;
}
safestrcat(buspath, "/");
safestrcat(buspath, SYSFS_BUS_NAME);
safestrcat(buspath, "/");
safestrcat(buspath, name);
if (sysfs_path_is_dir(buspath)) {
dprintf("Invalid path to bus: %s\n", buspath);
return NULL;
}
bus = alloc_bus();
if (!bus) {
dprintf("calloc failed\n");
return NULL;
}
safestrcpy(bus->name, name);
safestrcpy(bus->path, buspath);
if (sysfs_remove_trailing_slash(bus->path)) {
dprintf("Incorrect path to bus %s\n", bus->path);
sysfs_close_bus(bus);
return NULL;
}
return bus;
}
/**
* sysfs_get_bus_device: Get specific device on bus using device's id
* @bus: bus to find device on
* @id: bus_id for device
* returns struct sysfs_device reference or NULL if not found.
*/
struct sysfs_device *sysfs_get_bus_device(struct sysfs_bus *bus,
const char *id)
{
struct sysfs_device *dev = NULL;
char devpath[SYSFS_PATH_MAX], target[SYSFS_PATH_MAX];
if (!bus || !id) {
errno = EINVAL;
return NULL;
}
if (bus->devices) {
dev = (struct sysfs_device *)dlist_find_custom
(bus->devices, (void *)id, name_equal);
if (dev)
return dev;
}
safestrcpy(devpath, bus->path);
safestrcat(devpath, "/");
safestrcat(devpath, SYSFS_DEVICES_NAME);
safestrcat(devpath, "/");
safestrcat(devpath, id);
if (sysfs_path_is_link(devpath)) {
dprintf("No such device %s on bus %s?\n", id, bus->name);
return NULL;
}
if (!sysfs_get_link(devpath, target, SYSFS_PATH_MAX)) {
dev = sysfs_open_device_path(target);
if (!dev) {
dprintf("Error opening device at %s\n", target);
return NULL;
}
if (!bus->devices)
bus->devices = dlist_new_with_delete
(sizeof(struct sysfs_device),
sysfs_close_dev);
dlist_unshift_sorted(bus->devices, dev, sort_list);
}
return dev;
}
/**
* sysfs_get_bus_driver: Get specific driver on bus using driver name
* @bus: bus to find driver on
* @drvname: name of driver
* returns struct sysfs_driver reference or NULL if not found.
*/
struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus,
const char *drvname)
{
struct sysfs_driver *drv;
char drvpath[SYSFS_PATH_MAX];
if (!bus || !drvname) {
errno = EINVAL;
return NULL;
}
if (bus->drivers) {
drv = (struct sysfs_driver *)dlist_find_custom
(bus->drivers, (void *)drvname, name_equal);
if (drv)
return drv;
}
safestrcpy(drvpath, bus->path);
safestrcat(drvpath, "/");
safestrcat(drvpath, SYSFS_DRIVERS_NAME);
safestrcat(drvpath, "/");
safestrcat(drvpath, drvname);
drv = sysfs_open_driver_path(drvpath);
if (!drv) {
dprintf("Error opening driver at %s\n", drvpath);
return NULL;
}
if (!bus->drivers)
bus->drivers = dlist_new_with_delete
(sizeof(struct sysfs_driver),
sysfs_close_drv);
dlist_unshift_sorted(bus->drivers, drv, sort_list);
return drv;
}

View File

@ -40,6 +40,43 @@ void sysfs_close_class_device(struct sysfs_class_device *dev)
}
}
static void sysfs_close_cls_dev(void *dev)
{
sysfs_close_class_device((struct sysfs_class_device *)dev);
}
/**
* sysfs_close_class: close the given class
* @cls: sysfs_class to close
*/
void sysfs_close_class(struct sysfs_class *cls)
{
if (cls) {
if (cls->devices)
dlist_destroy(cls->devices);
if (cls->attrlist)
dlist_destroy(cls->attrlist);
free(cls);
}
}
static int cdev_name_equal(void *a, void *b)
{
if (!a || !b)
return 0;
if (strncmp((char *)a, ((struct sysfs_class_device *)b)->name,
strlen((char *)a)) == 0)
return 1;
return 0;
}
static struct sysfs_class *alloc_class(void)
{
return (struct sysfs_class *) calloc(1, sizeof(struct sysfs_class));
}
/**
* alloc_class_device: mallocs and initializes new class device struct.
* returns sysfs_class_device or NULL.
@ -96,7 +133,7 @@ struct sysfs_class_device *sysfs_open_class_device_path(const char *path)
errno = EINVAL;
return NULL;
}
if ((sysfs_path_is_dir(path)) != 0) {
if (sysfs_path_is_dir(path)) {
dprintf("%s is not a valid path to a class device\n", path);
return NULL;
}
@ -113,7 +150,7 @@ struct sysfs_class_device *sysfs_open_class_device_path(const char *path)
}
safestrcpy(cdev->path, path);
if ((sysfs_remove_trailing_slash(cdev->path)) != 0) {
if (sysfs_remove_trailing_slash(cdev->path)) {
dprintf("Invalid path to class device %s\n", cdev->path);
sysfs_close_class_device(cdev);
return NULL;
@ -335,3 +372,150 @@ struct sysfs_device *sysfs_get_classdev_device
}
return clsdev->sysdevice;
}
/**
* 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) {
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)) {
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
* @cls: sysfs_class to find the device on
* @name: name of the class device to look for
*
* Returns sysfs_class_device * on success and NULL on failure
*/
struct sysfs_class_device *sysfs_get_class_device(struct sysfs_class *cls,
const char *name)
{
char path[SYSFS_PATH_MAX];
struct sysfs_class_device *cdev = NULL;
if (!cls || !name) {
errno = EINVAL;
return NULL;
}
if (cls->devices) {
cdev = (struct sysfs_class_device *)dlist_find_custom
(cls->devices, (void *)name, cdev_name_equal);
if (cdev)
return cdev;
}
safestrcpy(path, cls->path);
safestrcat(path, "/");
safestrcat(path, name);
if (!sysfs_path_is_dir(path)) {
cdev = sysfs_open_class_device_path(path);
if (!cdev) {
dprintf("Error opening class device at %s\n", path);
return NULL;
}
}
if (!cls->devices)
cls->devices = dlist_new_with_delete
(sizeof(struct sysfs_class_device),
sysfs_close_cls_dev);
dlist_unshift_sorted(cls->devices, cdev, sort_list);
return cdev;
}
/**
* sysfs_get_class_devices: get all class devices in the given class
* @cls: sysfs_class whose devices list is needed
*
* Returns a dlist of sysfs_class_device * on success and NULL on failure
*/
struct dlist *sysfs_get_class_devices(struct sysfs_class *cls)
{
char path[SYSFS_PATH_MAX];
char *cdev_name;
struct sysfs_class_device *cdev = NULL;
struct dlist *dirlist;
if (!cls) {
errno = EINVAL;
return NULL;
}
safestrcpy(path, cls->path);
dirlist = read_dir_subdirs(path);
if (dirlist) {
dlist_for_each_data(dirlist, cdev_name, char) {
if (cls->devices) {
cdev = (struct sysfs_class_device *)
dlist_find_custom(cls->devices,
(void *)cdev_name, cdev_name_equal);
if (cdev)
continue;
}
safestrcpy(path, cls->path);
safestrcat(path, "/");
safestrcat(path, cdev_name);
cdev = sysfs_open_class_device_path(path);
if (cdev) {
if (!cls->devices)
cls->devices = dlist_new_with_delete
(sizeof(struct sysfs_class_device),
sysfs_close_cls_dev);
dlist_unshift_sorted(cls->devices, cdev,
sort_list);
}
}
sysfs_close_list(dirlist);
}
return cls->devices;
}

View File

@ -38,7 +38,6 @@ static int get_dev_driver(struct sysfs_device *dev)
errno = EINVAL;
return -1;
}
memset(path, 0, SYSFS_PATH_MAX);
memset(devpath, 0, SYSFS_PATH_MAX);
safestrcpymax(path, dev->path, SYSFS_PATH_MAX);
@ -53,9 +52,9 @@ static int get_dev_driver(struct sysfs_device *dev)
}
/*
* Devices on on earlier kernels do not have the "driver" link.
* Devices 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);
@ -81,7 +80,7 @@ static int get_dev_driver(struct sysfs_device *dev)
safestrcat(devpath, drv);
safestrcat(devpath, "/");
safestrcat(devpath, dev->bus_id);
if (sysfs_path_is_link(devpath) == 0) {
if (!sysfs_path_is_link(devpath)) {
safestrcpy(dev->driver_name, drv);
sysfs_close_list(drvlist);
return 0;
@ -149,7 +148,7 @@ int sysfs_get_device_bus(struct sysfs_device *dev)
safestrcat(path, SYSFS_DEVICES_NAME);
safestrcat(path, "/");
safestrcat(path, dev->bus_id);
if ((sysfs_path_is_link(path)) == 0) {
if (!sysfs_path_is_link(path)) {
memset(target, 0, SYSFS_PATH_MAX);
if (sysfs_get_link(path, target,
SYSFS_PATH_MAX)) {

View File

@ -338,7 +338,7 @@ struct sysfs_attribute *get_attribute(void *dev, const char *name)
SYSFS_PATH_MAX);
safestrcatmax(path, "/", SYSFS_PATH_MAX);
safestrcatmax(path, name, SYSFS_PATH_MAX);
if (!(sysfs_path_is_file(path)))
if (!sysfs_path_is_file(path))
cur = add_attribute((void *)dev, path);
return cur;
}
@ -373,7 +373,7 @@ struct dlist *read_dir_links(const char *path)
safestrcpy(file_path, path);
safestrcat(file_path, "/");
safestrcat(file_path, dirent->d_name);
if ((sysfs_path_is_link(file_path)) == 0) {
if (!sysfs_path_is_link(file_path)) {
if (!linklist) {
linklist = dlist_new_with_delete
(SYSFS_NAME_LEN, sysfs_del_name);
@ -421,7 +421,7 @@ struct dlist *read_dir_subdirs(const char *path)
safestrcpy(file_path, path);
safestrcat(file_path, "/");
safestrcat(file_path, dirent->d_name);
if ((sysfs_path_is_dir(file_path)) == 0) {
if (!sysfs_path_is_dir(file_path)) {
if (!dirlist) {
dirlist = dlist_new_with_delete
(SYSFS_NAME_LEN, sysfs_del_name);
@ -471,7 +471,7 @@ struct dlist *get_attributes_list(void *dev)
safestrcpy(file_path, path);
safestrcat(file_path, "/");
safestrcat(file_path, dirent->d_name);
if ((sysfs_path_is_file(file_path)) == 0) {
if (!sysfs_path_is_file(file_path)) {
if (((struct sysfs_device *)dev)->attrlist) {
/* check if attr is already in the list */
attr = (struct sysfs_attribute *)

View File

@ -3,7 +3,7 @@
*
* System 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