diff options
author | mananth <mananth> | 2003-12-04 06:11:24 +0000 |
---|---|---|
committer | mananth <mananth> | 2003-12-04 06:11:24 +0000 |
commit | 9da20ce9c84e0e91530afeb538e1402c5b8129e5 (patch) | |
tree | 2f0bced6903dca3a686c5c5397338307bd8ec32c | |
parent | e1660f07958223956f3b4fac6f66eecaa002ab92 (diff) | |
download | sysfsutils-9da20ce9c84e0e91530afeb538e1402c5b8129e5.tar.gz |
classdev_parent() patch and removes usage of _DIR #defines
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | cmd/lsbus.c | 3 | ||||
-rw-r--r-- | cmd/systool.c | 6 | ||||
-rw-r--r-- | include/libsysfs.h | 8 | ||||
-rw-r--r-- | lib/sysfs_bus.c | 18 | ||||
-rw-r--r-- | lib/sysfs_class.c | 125 | ||||
-rw-r--r-- | lib/sysfs_device.c | 18 | ||||
-rw-r--r-- | lib/sysfs_driver.c | 6 | ||||
-rw-r--r-- | lib/sysfs_utils.c | 9 | ||||
-rw-r--r-- | test/get_classdev_parent.c | 74 | ||||
-rw-r--r-- | test/get_driver.c | 6 |
11 files changed, 238 insertions, 41 deletions
@@ -1,4 +1,10 @@ +12/01/2003 - Ananth Mavinakayanahalli <ananth@in.ibm.com> + * Removed usage of _DIR #defines + * Added functionality to obtain parent of a class device + * Added get_classdev_parent.c in test/. This file is not + built by default as of now + 11/27/2003 - Ananth Mavinakayanahalli <ananth@in.ibm.com> * Updated library and utilities with the optimization patch diff --git a/cmd/lsbus.c b/cmd/lsbus.c index 89b3562..923ba22 100644 --- a/cmd/lsbus.c +++ b/cmd/lsbus.c @@ -345,7 +345,8 @@ int print_sysfs_buses(void) unsigned char *cur = NULL; int ret = 0; - strcpy(subsys, SYSFS_BUS_DIR); + strcat(subsys, "/"); + strcpy(subsys, SYSFS_BUS_NAME); list = sysfs_open_subsystem_list(subsys); if (list != NULL) { fprintf(stdout, "Supported sysfs buses:\n"); diff --git a/cmd/systool.c b/cmd/systool.c index 5a675b5..873d664 100644 --- a/cmd/systool.c +++ b/cmd/systool.c @@ -548,7 +548,7 @@ int show_default_info(void) unsigned char *cur = NULL; int retval = 0, i; - strcpy(subsys, SYSFS_BUS_DIR); + strcpy(subsys, SYSFS_BUS_NAME); list = sysfs_open_subsystem_list(subsys); if (list != NULL) { fprintf(stdout, "Supported sysfs buses:\n"); @@ -557,7 +557,7 @@ int show_default_info(void) } sysfs_close_list(list); - strcpy(subsys, SYSFS_CLASS_DIR); + strcpy(subsys, SYSFS_CLASS_NAME); list = sysfs_open_subsystem_list(subsys); if (list != NULL) { fprintf(stdout, "Supported sysfs classes:\n"); @@ -566,7 +566,7 @@ int show_default_info(void) } sysfs_close_list(list); - strcpy(subsys, SYSFS_DEVICES_DIR); + strcpy(subsys, SYSFS_DEVICES_NAME); list = sysfs_open_subsystem_list(subsys); if (list != NULL) { fprintf(stdout, "Supported sysfs devices:\n"); diff --git a/include/libsysfs.h b/include/libsysfs.h index ee2b23d..ba8eb32 100644 --- a/include/libsysfs.h +++ b/include/libsysfs.h @@ -31,15 +31,10 @@ */ #define SYSFS_FSTYPE_NAME "sysfs" #define SYSFS_PROC_MNTS "/proc/mounts" -#define SYSFS_BUS_DIR "/bus" #define SYSFS_BUS_NAME "bus" -#define SYSFS_CLASS_DIR "/class" #define SYSFS_CLASS_NAME "class" -#define SYSFS_BLOCK_DIR "/block" #define SYSFS_BLOCK_NAME "block" -#define SYSFS_DEVICES_DIR "/devices" #define SYSFS_DEVICES_NAME "devices" -#define SYSFS_DRIVERS_DIR "/drivers" #define SYSFS_DRIVERS_NAME "drivers" #define SYSFS_NAME_ATTRIBUTE "name" #define SYSFS_UNKNOWN "unknown" @@ -121,6 +116,7 @@ struct sysfs_class_device { unsigned char path[SYSFS_PATH_MAX]; /* 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; @@ -231,6 +227,8 @@ 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 unsigned char *name); extern struct dlist *sysfs_get_class_devices(struct sysfs_class *cls); diff --git a/lib/sysfs_bus.c b/lib/sysfs_bus.c index eb21e10..5ed3904 100644 --- a/lib/sysfs_bus.c +++ b/lib/sysfs_bus.c @@ -292,7 +292,8 @@ struct sysfs_bus *sysfs_open_bus(const unsigned char *name) return NULL; } - strcat(buspath, SYSFS_BUS_DIR); + strcat(buspath, "/"); + strcat(buspath, SYSFS_BUS_NAME); strcat(buspath, "/"); strcat(buspath, name); if ((sysfs_path_is_dir(buspath)) != 0) { @@ -428,10 +429,12 @@ struct sysfs_device *sysfs_open_bus_device(unsigned char *busname, return NULL; } - strcat(path, SYSFS_BUS_DIR); + strcat(path, "/"); + strcat(path, SYSFS_BUS_NAME); strcat(path, "/"); strcat(path, busname); - strcat(path, SYSFS_DEVICES_DIR); + strcat(path, "/"); + strcat(path, SYSFS_DEVICES_NAME); strcat(path, "/"); strcat(path, dev_id); @@ -464,15 +467,18 @@ int sysfs_find_driver_bus(const unsigned char *driver, unsigned char *busname, } memset(subsys, 0, SYSFS_PATH_MAX); - strcpy(subsys, SYSFS_BUS_DIR); + strcat(subsys, "/"); + strcpy(subsys, SYSFS_BUS_NAME); buslist = sysfs_open_subsystem_list(subsys); if (buslist != NULL) { dlist_for_each_data(buslist, bus, char) { memset(subsys, 0, SYSFS_PATH_MAX); - strcpy(subsys, SYSFS_BUS_DIR); + strcat(subsys, "/"); + strcpy(subsys, SYSFS_BUS_NAME); strcat(subsys, "/"); strcat(subsys, bus); - strcat(subsys, SYSFS_DRIVERS_DIR); + strcat(subsys, "/"); + strcat(subsys, SYSFS_DRIVERS_NAME); drivers = sysfs_open_subsystem_list(subsys); if (drivers != NULL) { dlist_for_each_data(drivers, curdrv, char) { diff --git a/lib/sysfs_class.c b/lib/sysfs_class.c index 5efe166..5e2bd14 100644 --- a/lib/sysfs_class.c +++ b/lib/sysfs_class.c @@ -58,6 +58,8 @@ void sysfs_close_class_device(struct sysfs_class_device *dev) sysfs_close_device(dev->sysdevice); if (dev->driver != NULL) sysfs_close_driver(dev->driver); + if (dev->parent != NULL) + sysfs_close_class_device(dev->parent); free(dev); } } @@ -133,19 +135,18 @@ static void set_classdev_classname(struct sysfs_class_device *cdev) unsigned char *c = NULL, *e = NULL; int count = 0; - c = strstr(cdev->path, SYSFS_CLASS_DIR); - if (c == NULL) - c = strstr(cdev->path, SYSFS_BLOCK_DIR); - else { - c++; - while (c != NULL && *c != '/') - c++; + c = strstr(cdev->path, SYSFS_CLASS_NAME); + if (c == NULL) { + c = strstr(cdev->path, SYSFS_BLOCK_NAME); + } else { + c = strstr(c, "/"); } if (c == NULL) strcpy(cdev->classname, SYSFS_UNKNOWN); else { - c++; + if (*c == '/') + c++; e = c; while (e != NULL && *e != '/' && *e != '\0') { e++; @@ -253,9 +254,11 @@ struct sysfs_class *sysfs_open_class(const unsigned char *name) * if "name" is "block" and proceed accordingly */ if (strcmp(name, SYSFS_BLOCK_NAME) == 0) { - strcat(classpath, SYSFS_BLOCK_DIR); + strcat(classpath, "/"); + strcat(classpath, SYSFS_BLOCK_NAME); } else { - strcat(classpath, SYSFS_CLASS_DIR); + strcat(classpath, "/"); + strcat(classpath, SYSFS_CLASS_NAME); strcat(classpath, "/"); strcat(classpath, name); } @@ -381,7 +384,101 @@ struct sysfs_driver *sysfs_get_classdev_driver } return (clsdev->driver); } - + +/* + * get_blockdev_parent: Get the parent class device for a "block" subsystem + * device if present + * @clsdev: block subsystem class device whose parent needs to be found + * Returns 0 on success and 1 on error + */ +static int get_blockdev_parent(struct sysfs_class_device *clsdev) +{ + unsigned char parent_path[SYSFS_PATH_MAX], value[256], *c = NULL; + + memset(parent_path, 0, SYSFS_PATH_MAX); + strcpy(parent_path, clsdev->path); + + c = strstr(parent_path, SYSFS_BLOCK_NAME); + if (c == NULL) { + dprintf("Class device %s does not belong to BLOCK subsystem", + clsdev->name); + return 1; + } + + c += strlen(SYSFS_BLOCK_NAME); + if (*c == '/') + c++; + 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, '/'); + if (c == NULL) + goto errout; + *c = '\0'; + + /* Now validate if the parent has the "dev" attribute */ + memset(value, 0, 256); + strcat(parent_path, "/dev"); + if ((sysfs_read_attribute_value(parent_path, value, 256)) != 0) { + dprintf("Block device %s does not have a parent\n", + clsdev->name); + return 1; + } + + c = strrchr(parent_path, '/'); + if (c == NULL) + goto errout; + + *c = '\0'; + clsdev->parent = sysfs_open_class_device(parent_path); + if (clsdev->parent == NULL) { + dprintf("Error opening the parent class device at %s\n", + parent_path); + return 1; + } + return 0; + +errout: + dprintf("Invalid path %s\n", clsdev->path); + return 1; +} + +/** + * sysfs_get_classdev_parent: Retrieves the parent of a class device. + * eg., when working with hda1, this function can be used to retrieve the + * sysfs_class_device for hda + * + * @clsdev: class device whose parent details are required. + * Returns sysfs_class_device of the parent on success, NULL on failure + */ +struct sysfs_class_device *sysfs_get_classdev_parent + (struct sysfs_class_device *clsdev) +{ + if (clsdev == NULL) { + errno = EINVAL; + return NULL; + } + if (clsdev->parent != NULL) + 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 (!(strcmp(clsdev->classname, SYSFS_BLOCK_NAME))) { + if ((get_blockdev_parent(clsdev)) == 0) + return (clsdev->parent); + } + return NULL; +} + /** * get_classdev_path: given the class and a device in the class, return the * absolute path to the device @@ -403,9 +500,11 @@ static int get_classdev_path(const unsigned char *classname, return -1; } if (strcmp(classname, SYSFS_BLOCK_NAME) == 0) { - strcat(path, SYSFS_BLOCK_DIR); + strcat(path, "/"); + strcat(path, SYSFS_BLOCK_NAME); } else { - strcat(path, SYSFS_CLASS_DIR); + strcat(path, "/"); + strcat(path, SYSFS_CLASS_NAME); strcat(path, "/"); strcat(path, classname); } diff --git a/lib/sysfs_device.c b/lib/sysfs_device.c index 2d1fb9d..9834a8c 100644 --- a/lib/sysfs_device.c +++ b/lib/sysfs_device.c @@ -36,10 +36,12 @@ static int confirm_device_bus(struct sysfs_device *dev, if (sysfs_get_mnt_path(devpath, SYSFS_PATH_MAX) != 0) return -1; - strcat(devpath, SYSFS_BUS_DIR); + strcat(devpath, "/"); + strcat(devpath, SYSFS_BUS_NAME); strcat(devpath, "/"); strcat(devpath, busname); - strcat(devpath, SYSFS_DEVICES_DIR); + strcat(devpath, "/"); + strcat(devpath, SYSFS_DEVICES_NAME); strcat(devpath, "/"); strcat(devpath, bus_id); @@ -69,7 +71,8 @@ static int get_device_bus(struct sysfs_device *dev) return -1; } - strcpy(subsys, SYSFS_BUS_DIR); /* subsys = /bus */ + strcat(subsys, "/"); + strcpy(subsys, SYSFS_BUS_NAME); /* subsys = /bus */ buslist = sysfs_open_subsystem_list(subsys); if (buslist != NULL) { dlist_for_each_data(buslist, bus, char) { @@ -350,7 +353,8 @@ struct sysfs_root_device *sysfs_open_root_device(const unsigned char *name) return NULL; } - strcat(rootpath, SYSFS_DEVICES_DIR); + strcat(rootpath, "/"); + strcat(rootpath, SYSFS_DEVICES_NAME); strcat(rootpath, "/"); strcat(rootpath, name); if ((sysfs_path_is_dir(rootpath)) != 0) { @@ -446,10 +450,12 @@ static int get_device_absolute_path(const unsigned char *device, dprintf ("Sysfs not supported on this system\n"); return -1; } - strcat(bus_path, SYSFS_BUS_DIR); + strcat(bus_path, "/"); + strcat(bus_path, SYSFS_BUS_NAME); strcat(bus_path, "/"); strcat(bus_path, bus); - strcat(bus_path, SYSFS_DEVICES_DIR); + strcat(bus_path, "/"); + strcat(bus_path, SYSFS_DEVICES_NAME); strcat(bus_path, "/"); strcat(bus_path, device); /* diff --git a/lib/sysfs_driver.c b/lib/sysfs_driver.c index 2842c0f..6857b6f 100644 --- a/lib/sysfs_driver.c +++ b/lib/sysfs_driver.c @@ -301,10 +301,12 @@ static int get_driver_path(const unsigned char *bus, dprintf("Error getting sysfs mount path\n"); return -1; } - strcat(path, SYSFS_BUS_DIR); + strcat(path, "/"); + strcat(path, SYSFS_BUS_NAME); strcat(path, "/"); strcat(path, bus); - strcat(path, SYSFS_DRIVERS_DIR); + strcat(path, "/"); + strcat(path, SYSFS_DRIVERS_NAME); strcat(path, "/"); strcat(path, drv); return 0; diff --git a/lib/sysfs_utils.c b/lib/sysfs_utils.c index 7e6b221..89920b6 100644 --- a/lib/sysfs_utils.c +++ b/lib/sysfs_utils.c @@ -218,6 +218,7 @@ struct dlist *sysfs_open_subsystem_list(unsigned char *name) return NULL; } + strcat(sysfs_path, "/"); strcat(sysfs_path, name); dir = sysfs_open_directory(sysfs_path); if (dir == NULL) { @@ -253,7 +254,7 @@ struct dlist *sysfs_open_subsystem_list(unsigned char *name) * name requested here is "class", verify if "block" is supported on * this system and return the same. */ - if (strcmp(name, SYSFS_CLASS_DIR) == 0) { + if (strcmp(name, SYSFS_CLASS_NAME) == 0) { c = strstr(sysfs_path, SYSFS_CLASS_NAME); if (c == NULL) goto out; @@ -293,10 +294,12 @@ struct dlist *sysfs_open_bus_devices_list(unsigned char *name) return NULL; } - strcat(sysfs_path, SYSFS_BUS_DIR); + strcat(sysfs_path, "/"); + strcat(sysfs_path, SYSFS_BUS_NAME); strcat(sysfs_path, "/"); strcat(sysfs_path, name); - strcat(sysfs_path, SYSFS_DEVICES_DIR); + strcat(sysfs_path, "/"); + strcat(sysfs_path, SYSFS_DEVICES_NAME); dir = sysfs_open_directory(sysfs_path); if (dir == NULL) { dprintf("Error opening sysfs_directory at %s\n", sysfs_path); diff --git a/test/get_classdev_parent.c b/test/get_classdev_parent.c new file mode 100644 index 0000000..f256aa6 --- /dev/null +++ b/test/get_classdev_parent.c @@ -0,0 +1,74 @@ +/* + * get_classdev_parent.c + * + * Utility to get a given class device as well as its parent if available + * + * Copyright (C) IBM Corp. 2003 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2 of the License. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "libsysfs.h" + +int main(int argc, char *argv[]) +{ + struct sysfs_class_device *cdev = NULL, *parent = NULL; + struct sysfs_attribute *attr = NULL; + struct dlist *attrlist = NULL; + struct sysfs_device *device = NULL; + struct sysfs_driver *driver = NULL; + + /* FIXME: edit this path to any valid path on your system to test */ + cdev = sysfs_open_class_device("/sys/block/sda/sda1"); + if (cdev == NULL) { + fprintf(stdout, "Class device not found\n"); + return 1; + } + + fprintf(stdout, "Class device %s\n", cdev->name); + + attrlist = sysfs_get_classdev_attributes(cdev); + if (attrlist != NULL) { + dlist_for_each_data(attrlist, attr, struct sysfs_attribute) + fprintf(stdout, "\t%s : %s", attr->name, attr->value); + } + fprintf(stdout, "\n"); + + device = sysfs_get_classdev_device(cdev); + if (device) + fprintf(stdout, "\tDevice : %s\n", cdev->sysdevice->bus_id); + driver = sysfs_get_classdev_driver(cdev); + if (driver) + fprintf(stdout, "\tDriver : %s\n", cdev->driver->name); + + parent = sysfs_get_classdev_parent(cdev); + if (parent != NULL) { + fprintf(stdout, "parent is %s\n", parent->name); + attrlist = sysfs_get_classdev_attributes(parent); + if (attrlist != NULL) { + dlist_for_each_data(attrlist, attr, struct sysfs_attribute) + fprintf(stdout, "\t%s : %s", attr->name, attr->value); + } + fprintf(stdout, "\n"); + } else + fprintf(stdout, "No parent device found\n"); + + sysfs_close_class_device(cdev); + return 0; +} + diff --git a/test/get_driver.c b/test/get_driver.c index 5f2ff93..249faa9 100644 --- a/test/get_driver.c +++ b/test/get_driver.c @@ -55,10 +55,12 @@ int main(int argc, char *argv[]) fprintf(stdout, "Sysfs not mounted?\n"); return 1; } - strcat(path, SYSFS_BUS_DIR); + strcat(path, "/"); + strcat(path, SYSFS_BUS_NAME); strcat(path, "/"); strcat(path, bus); - strcat(path, SYSFS_DRIVERS_DIR); + strcat(path, "/"); + strcat(path, SYSFS_DRIVERS_NAME); strcat(path, "/"); strcat(path, argv[1]); driver = sysfs_open_driver(path); |