X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=libsysfs%2Fsysfs_device.c;h=66d5f9aef7c71b65b9e9272b053eb4bac8a21525;hp=82b54719ff7ef679bbce3dec09365e5f09ba125b;hb=ac28b86d631f23b5df74dbeb33e76a2b3f5d88bb;hpb=5d4754f19521568b775ba7a31465d3af192ce382 diff --git a/libsysfs/sysfs_device.c b/libsysfs/sysfs_device.c index 82b54719f..66d5f9aef 100644 --- a/libsysfs/sysfs_device.c +++ b/libsysfs/sysfs_device.c @@ -104,14 +104,6 @@ static void sysfs_close_device_tree(struct sysfs_device *devroot) } } -/** - * sysfs_del_device: routine for dlist integration - */ -static void sysfs_del_device(void *dev) -{ - sysfs_close_device((struct sysfs_device *)dev); -} - /** * sysfs_close_dev_tree: routine for dlist integration */ @@ -127,6 +119,8 @@ static void sysfs_close_dev_tree(void *dev) void sysfs_close_device(struct sysfs_device *dev) { if (dev != NULL) { + if (dev->parent != NULL) + sysfs_close_device(dev->parent); if (dev->directory != NULL) sysfs_close_directory(dev->directory); if (dev->children != NULL && dev->children->count == 0) @@ -164,7 +158,7 @@ static struct sysfs_directory *open_device_dir(const unsigned char *path) dprintf ("Device %s not supported on this system\n", path); return NULL; } - if ((sysfs_read_directory(rdir)) != 0) { + if ((sysfs_read_dir_subdirs(rdir)) != 0) { dprintf ("Error reading device at dir %s\n", path); sysfs_close_directory(rdir); return NULL; @@ -174,11 +168,11 @@ static struct sysfs_directory *open_device_dir(const unsigned char *path) } /** - * sysfs_open_device: opens and populates device structure + * sysfs_open_device_path: opens and populates device structure * @path: path to device, this is the /sys/devices/ path * returns sysfs_device structure with success or NULL with error */ -struct sysfs_device *sysfs_open_device(const unsigned char *path) +struct sysfs_device *sysfs_open_device_path(const unsigned char *path) { struct sysfs_device *dev = NULL; @@ -232,7 +226,7 @@ static struct sysfs_device *sysfs_open_device_tree(const unsigned char *path) errno = EINVAL; return NULL; } - rootdev = sysfs_open_device(path); + rootdev = sysfs_open_device_path(path); if (rootdev == NULL) { dprintf("Error opening root device at %s\n", path); return NULL; @@ -255,7 +249,7 @@ static struct sysfs_device *sysfs_open_device_tree(const unsigned char *path) if (rootdev->children == NULL) rootdev->children = dlist_new_with_delete (sizeof(struct sysfs_device), - sysfs_del_device); + sysfs_close_dev_tree); dlist_unshift(rootdev->children, new); } } @@ -342,7 +336,6 @@ struct sysfs_root_device *sysfs_open_root_device(const unsigned char *name) if (sysfs_trailing_slash(rootpath) == 0) strcat(rootpath, "/"); - strcat(rootpath, SYSFS_DEVICES_NAME); strcat(rootpath, "/"); strcat(rootpath, name); @@ -357,6 +350,7 @@ struct sysfs_root_device *sysfs_open_root_device(const unsigned char *name) dprintf("calloc failure\n"); return NULL; } + strcpy(root->name, name); strcpy(root->path, rootpath); return root; } @@ -416,10 +410,8 @@ struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev, cur = sysfs_get_directory_attribute(dev->directory, (unsigned char *)name); - if (cur != NULL) - return cur; - return NULL; + return cur; } /** @@ -445,10 +437,8 @@ static int get_device_absolute_path(const unsigned char *device, dprintf ("Sysfs not supported on this system\n"); return -1; } - if (sysfs_trailing_slash(bus_path) == 0) strcat(bus_path, "/"); - strcat(bus_path, SYSFS_BUS_NAME); strcat(bus_path, "/"); strcat(bus_path, bus); @@ -468,7 +458,7 @@ static int get_device_absolute_path(const unsigned char *device, } /** - * sysfs_open_device_by_id: open a device by id (use the "bus" subsystem) + * sysfs_open_device: open a device by id (use the "bus" subsystem) * @bus_id: bus_id of the device to open - has to be the "bus_id" in * /sys/bus/xxx/devices * @bus: bus the device belongs to @@ -478,7 +468,7 @@ static int get_device_absolute_path(const unsigned char *device, * 2. Bus the device is on must be supplied * Use sysfs_find_device_bus to get the bus name */ -struct sysfs_device *sysfs_open_device_by_id(const unsigned char *bus_id, +struct sysfs_device *sysfs_open_device(const unsigned char *bus_id, const unsigned char *bus) { char sysfs_path[SYSFS_PATH_MAX]; @@ -495,7 +485,7 @@ struct sysfs_device *sysfs_open_device_by_id(const unsigned char *bus_id, return NULL; } - device = sysfs_open_device(sysfs_path); + device = sysfs_open_device_path(sysfs_path); if (device == NULL) { dprintf("Error opening device %s\n", bus_id); return NULL; @@ -504,6 +494,60 @@ struct sysfs_device *sysfs_open_device_by_id(const unsigned char *bus_id, return device; } +/** + * sysfs_get_device_parent: opens up given device's parent and returns a + * reference to its sysfs_device + * @dev: sysfs_device whose parent is requested + * Returns sysfs_device of the parent on success and NULL on failure + */ +struct sysfs_device *sysfs_get_device_parent(struct sysfs_device *dev) +{ + unsigned char ppath[SYSFS_PATH_MAX], *tmp = NULL; + + if (dev == NULL) { + errno = EINVAL; + return NULL; + } + + if (dev->parent != NULL) + return (dev->parent); + + memset(ppath, 0, SYSFS_PATH_MAX); + strcpy(ppath, dev->path); + tmp = strrchr(ppath, '/'); + if (tmp == NULL) { + dprintf("Invalid path to device %s\n", ppath); + return NULL; + } + if (*(tmp +1) == '\0') { + *tmp = '\0'; + tmp = strrchr(tmp, '/'); + if (tmp == NULL) { + dprintf("Invalid path to device %s\n", ppath); + return NULL; + } + } + *tmp = '\0'; + + /* + * All "devices" have the "detach_state" attribute - validate here + */ + strcat(ppath, "/detach_state"); + if ((sysfs_path_is_file(ppath)) != 0) { + 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) { + 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