summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormananth <mananth>2003-12-04 06:11:24 +0000
committermananth <mananth>2003-12-04 06:11:24 +0000
commit9da20ce9c84e0e91530afeb538e1402c5b8129e5 (patch)
tree2f0bced6903dca3a686c5c5397338307bd8ec32c
parente1660f07958223956f3b4fac6f66eecaa002ab92 (diff)
downloadsysfsutils-9da20ce9c84e0e91530afeb538e1402c5b8129e5.tar.gz
classdev_parent() patch and removes usage of _DIR #defines
-rw-r--r--ChangeLog6
-rw-r--r--cmd/lsbus.c3
-rw-r--r--cmd/systool.c6
-rw-r--r--include/libsysfs.h8
-rw-r--r--lib/sysfs_bus.c18
-rw-r--r--lib/sysfs_class.c125
-rw-r--r--lib/sysfs_device.c18
-rw-r--r--lib/sysfs_driver.c6
-rw-r--r--lib/sysfs_utils.c9
-rw-r--r--test/get_classdev_parent.c74
-rw-r--r--test/get_driver.c6
11 files changed, 238 insertions, 41 deletions
diff --git a/ChangeLog b/ChangeLog
index 22d5d36..036b5df 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);