X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=libsysfs%2Fsysfs_device.c;h=fbd046f229a297fe5c58ba0d024f28518bba8623;hb=bc1530c65c282e27eb60de797291ca45c2d8cda2;hp=89704dcd8041092abf6b9f8e6c6362a1bf43ba84;hpb=fe3fe3b29ffbc7d0ce7dca6a371da31d8b3ff7f8;p=elogind.git diff --git a/libsysfs/sysfs_device.c b/libsysfs/sysfs_device.c index 89704dcd8..fbd046f22 100644 --- a/libsysfs/sysfs_device.c +++ b/libsysfs/sysfs_device.c @@ -23,6 +23,77 @@ #include "libsysfs.h" #include "sysfs.h" +static int confirm_device_bus(struct sysfs_device *dev, + unsigned char *busname, unsigned char *bus_id) +{ + struct sysfs_link *devlink = NULL; + unsigned char devpath[SYSFS_PATH_MAX]; + int result = 0; + + if (busname == NULL || bus_id == NULL) + return -1; + + if (sysfs_get_mnt_path(devpath, SYSFS_PATH_MAX) != 0) + return -1; + + strcat(devpath, SYSFS_BUS_DIR); + strcat(devpath, "/"); + strcat(devpath, busname); + strcat(devpath, SYSFS_DEVICES_DIR); + strcat(devpath, "/"); + strcat(devpath, bus_id); + + devlink = sysfs_open_link(devpath); + if (devlink == NULL) + return -1; + + if (strcmp(devlink->target, dev->path) == 0) + result++; + sysfs_close_link(devlink); + return result; +} + +/** + * get_device_bus: retrieves the bus name the device is on, checks path to + * bus' link to make sure it has correct device. + * @dev: device to get busname. + * returns 0 with success and -1 with error. + */ +static int get_device_bus(struct sysfs_device *dev) +{ + unsigned char subsys[SYSFS_NAME_LEN], *bus = NULL, *curdev = NULL; + struct dlist *buslist = NULL, *device_list = NULL; + + if (dev == NULL) { + errno = EINVAL; + return -1; + } + + strcpy(subsys, SYSFS_BUS_DIR); /* subsys = /bus */ + buslist = sysfs_open_subsystem_list(subsys); + if (buslist != NULL) { + dlist_for_each_data(buslist, bus, char) { + device_list = sysfs_open_bus_devices_list(bus); + if (device_list != NULL) { + dlist_for_each_data(device_list, + curdev, char) { + if (strcmp(dev->bus_id, curdev) == 0 + && confirm_device_bus(dev, bus, + curdev) > 0) { + strcpy(dev->bus, bus); + sysfs_close_list(device_list); + sysfs_close_list(buslist); + return 0; + } + } + sysfs_close_list(device_list); + } + } + sysfs_close_list(buslist); + } + return -1; +} + /** * sysfs_close_device_tree: closes every device in the supplied tree, * closing children only. @@ -150,6 +221,9 @@ struct sysfs_device *sysfs_open_device(const unsigned char *path) * implies that the dev->name and dev->bus_id contain same data. */ strncpy(dev->name, sdir->name, SYSFS_NAME_LEN); + + if (get_device_bus(dev) != 0) + strcpy(dev->bus, SYSFS_UNKNOWN); return dev; } @@ -338,55 +412,6 @@ struct dlist *sysfs_get_device_attributes(struct sysfs_device *device) return (device->directory->attributes); } -/** - * sysfs_open_device_by_id: 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 - * @bsize: size of the bus buffer - * returns struct sysfs_device if found, NULL otherwise - * NOTE: - * 1. Use sysfs_close_device to close the 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, - const unsigned char *bus, size_t bsize) -{ - char sysfs_path[SYSFS_PATH_MAX], device_path[SYSFS_PATH_MAX]; - struct sysfs_device *device = NULL; - - if (bus_id == NULL || bus == NULL) { - errno = EINVAL; - return NULL; - } - memset(sysfs_path, 0, SYSFS_PATH_MAX); - if ((sysfs_get_mnt_path(sysfs_path, SYSFS_PATH_MAX)) != 0) { - dprintf("Error getting sysfs mount path\n"); - return NULL; - } - strcat(sysfs_path, SYSFS_BUS_DIR); - strcat(sysfs_path, "/"); - strncat(sysfs_path, bus, bsize); - strcat(sysfs_path, SYSFS_DEVICES_DIR); - strcat(sysfs_path, "/"); - strcat(sysfs_path, bus_id); - - /* devices under /sys/bus/xxx/devices are links to devices subsystem */ - if ((sysfs_get_link(sysfs_path, device_path, SYSFS_PATH_MAX)) < 0) { - dprintf("Error getting device path\n"); - return NULL; - } - - device = sysfs_open_device(device_path); - if (device == NULL) { - dprintf("Error opening device %s\n", bus_id); - return NULL; - } - - return device; -} - /** * get_device_absolute_path: looks up the bus the device is on, gets * absolute path to the device @@ -395,29 +420,24 @@ struct sysfs_device *sysfs_open_device_by_id(const unsigned char *bus_id, * @psize: size of "path" * Returns 0 on success -1 on failure */ -static int get_device_absolute_path(const unsigned char *device, - unsigned char *path, size_t psize) +static int get_device_absolute_path(const unsigned char *device, + const unsigned char *bus, unsigned char *path, size_t psize) { - unsigned char bus_name[SYSFS_NAME_LEN], bus_path[SYSFS_PATH_MAX]; + unsigned char bus_path[SYSFS_NAME_LEN]; if (device == NULL || path == NULL) { errno = EINVAL; return -1; } - memset(bus_name, 0, SYSFS_NAME_LEN); memset(bus_path, 0, SYSFS_NAME_LEN); - if ((sysfs_find_device_bus(device, bus_name, SYSFS_NAME_LEN)) != 0) { - dprintf("Device %s not found\n", device); - return -1; - } if (sysfs_get_mnt_path(bus_path, SYSFS_PATH_MAX) != 0) { dprintf ("Sysfs not supported on this system\n"); return -1; } strcat(bus_path, SYSFS_BUS_DIR); strcat(bus_path, "/"); - strcat(bus_path, bus_name); + strcat(bus_path, bus); strcat(bus_path, SYSFS_DEVICES_DIR); strcat(bus_path, "/"); strcat(bus_path, device); @@ -433,106 +453,85 @@ static int get_device_absolute_path(const unsigned char *device, } /** - * sysfs_write_device_attr: modify a "writable" attribute for the given device - * @dev: device bus_id for which attribute has to be changed - * @attrib: attribute to change - * @value: value to change to - * @len: "value" length to write - * Returns 0 on success -1 on error - */ -int sysfs_write_device_attr(unsigned char *dev, unsigned char *attrib, - unsigned char *value, size_t len) + * sysfs_open_device_by_id: 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 + * @bsize: size of the bus buffer + * returns struct sysfs_device if found, NULL otherwise + * NOTE: + * 1. Use sysfs_close_device to close the 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, + const unsigned char *bus, size_t bsize) { - struct sysfs_attribute *attribute = NULL; - unsigned char devpath[SYSFS_PATH_MAX]; + char sysfs_path[SYSFS_PATH_MAX]; + struct sysfs_device *device = NULL; - if (dev == NULL || attrib == NULL || value == NULL) { + if (bus_id == NULL || bus == NULL) { errno = EINVAL; - return -1; - } - - memset(devpath, 0, SYSFS_PATH_MAX); - if ((get_device_absolute_path(dev, devpath, SYSFS_PATH_MAX)) != 0) { - dprintf("Error finding absolute path to device %s\n", dev); - return -1; - } - strcat(devpath, "/"); - strcat(devpath, attrib); - attribute = sysfs_open_attribute(devpath); - if (attribute == NULL) { - dprintf("Attribute %s could not be retrieved for device %s\n", - attrib, dev); - return -1; + return NULL; } - if (attribute->method & SYSFS_METHOD_SHOW) { - if ((sysfs_read_attribute(attribute)) != 0) { - dprintf("Error reading attribute %s for device %s\n", - attrib, dev); - sysfs_close_attribute(attribute); - return -1; - } + memset(sysfs_path, 0, SYSFS_PATH_MAX); + if ((get_device_absolute_path(bus_id, bus, sysfs_path, + SYSFS_PATH_MAX)) != 0) { + dprintf("Error getting to device %s\n", bus_id); + return NULL; } - if ((sysfs_write_attribute(attribute, value, len)) < 0) { - dprintf("Error setting %s to %s\n", attrib, value); - sysfs_close_attribute(attribute); - return -1; + + device = sysfs_open_device(sysfs_path); + if (device == NULL) { + dprintf("Error opening device %s\n", bus_id); + return NULL; } - sysfs_close_attribute(attribute); - return 0; + + return device; } -/** - * sysfs_read_device_attr: read an attribute of the given device - * @dev: device bus_id for which attribute has to be changed - * @attrib: attribute to read - * @value: buffer to return value in - * @len: size of buffer available - * Returns 0 on success -1 on error - */ -int sysfs_read_device_attr(unsigned char *dev, unsigned char *attrib, - unsigned char *value, size_t len) +/* + * 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 unsigned char *bus, + const unsigned char *bus_id, const unsigned char *attrib) { struct sysfs_attribute *attribute = NULL; unsigned char devpath[SYSFS_PATH_MAX]; - - if (dev == NULL || attrib == NULL || value == NULL) { + + if (bus == NULL || bus_id == NULL || attrib == NULL) { errno = EINVAL; - return -1; + return NULL; } - + memset(devpath, 0, SYSFS_PATH_MAX); - if ((get_device_absolute_path(dev, devpath, SYSFS_PATH_MAX)) != 0) { - dprintf("Error finding absolute path to device %s\n", dev); - return -1; + if ((get_device_absolute_path(bus_id, bus, devpath, + SYSFS_PATH_MAX)) != 0) { + dprintf("Error getting to device %s\n", bus_id); + return NULL; } strcat(devpath, "/"); strcat(devpath, attrib); attribute = sysfs_open_attribute(devpath); if (attribute == NULL) { dprintf("Error opening attribute %s for device %s\n", - attrib, dev); - return -1; - } - if (!(attribute->method & SYSFS_METHOD_SHOW)) { - dprintf("Show method not supported for attribute %s\n", - attrib); - sysfs_close_attribute(attribute); - return -1; + attrib, bus_id); + return NULL; } if ((sysfs_read_attribute(attribute)) != 0) { dprintf("Error reading attribute %s for device %s\n", - attrib, dev); + attrib, bus_id); sysfs_close_attribute(attribute); - return -1; - } - if (attribute->len > len) { - dprintf("Value length %d is larger than supplied buffer %d\n", - attribute->len, len); - sysfs_close_attribute(attribute); - return -1; + return NULL; } - strncpy(value, attribute->value, attribute->len); - value[(attribute->len)+1] = 0; - sysfs_close_attribute(attribute); - return 0; + return attribute; } +