diff options
author | mananth <mananth> | 2003-10-15 12:16:35 +0000 |
---|---|---|
committer | mananth <mananth> | 2003-10-15 12:16:35 +0000 |
commit | a8dc5520e8863135dd277f37711564a8b4c73a06 (patch) | |
tree | ea134160a2324f64e73d7913c0a85be88572c67c | |
parent | fc281a0436d90c72d33044190c95eb00be67f08a (diff) | |
download | sysfsutils-a8dc5520e8863135dd277f37711564a8b4c73a06.tar.gz |
Corrected "write attribute" functions
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | include/libsysfs.h | 9 | ||||
-rw-r--r-- | lib/sysfs_device.c | 15 | ||||
-rw-r--r-- | lib/sysfs_dir.c | 70 | ||||
-rw-r--r-- | lib/sysfs_utils.c | 69 |
5 files changed, 118 insertions, 54 deletions
@@ -1,4 +1,11 @@ +09/23/2003 - Ananth Mavinakayanahalli <ananth@in.ibm.com> + * Fixed "write" attribute functions. + * Removed sysfs_write_attribute_value() + * Added sysfs_change_attribute_value() - a wrapper for + sysfs_write_attribute() + * Simplified sysfs_get_device_attr() + 09/16/2003 - Ananth Mavinakayanahalli <ananth@in.ibm.com> * Patch sysfs_close_driver() so as not to segfault when during dlist shifting. @@ -22,7 +29,7 @@ * Simplify sysfs_find_device_bus_name() 09/04/2003 - Ananth Mavinakayanahalli <ananth@in.ibm.com> - * Simplify sysfs_open_bus_device + * Simplified sysfs_open_bus_device 08/29/2003 - Ananth Mavinakayanahalli <ananth@in.ibm.com> * Removed "bus_name" from struct sysfs_device diff --git a/include/libsysfs.h b/include/libsysfs.h index 827e305..d7fc69b 100644 --- a/include/libsysfs.h +++ b/include/libsysfs.h @@ -142,6 +142,8 @@ extern int sysfs_get_link(const unsigned char *path, unsigned char *target, extern struct dlist *sysfs_open_subsystem_list(unsigned char *name); extern struct dlist *sysfs_open_bus_devices_list(unsigned char *name); extern void sysfs_close_list(struct dlist *list); +extern int sysfs_change_attribute_value(unsigned char *device, + unsigned char *attribute, unsigned char *value); /* sysfs directory and file access */ extern void sysfs_close_attribute(struct sysfs_attribute *sysattr); @@ -149,9 +151,8 @@ extern struct sysfs_attribute *sysfs_open_attribute(const unsigned char *path); extern int sysfs_read_attribute(struct sysfs_attribute *sysattr); extern int sysfs_read_attribute_value(const unsigned char *attrpath, unsigned char *value, size_t vsize); -extern int sysfs_write_attribute(struct sysfs_attribute *sysattr); -extern int sysfs_write_attribute_value(const unsigned char *attrpath, - unsigned char *value); +extern int sysfs_write_attribute(struct sysfs_attribute *sysattr, + const unsigned char *new_value); extern unsigned char *sysfs_get_value_from_attributes(struct dlist *attr, const unsigned char * name); extern void sysfs_close_directory(struct sysfs_directory *sysdir); @@ -188,7 +189,7 @@ extern struct sysfs_device *sysfs_open_device_tree(const unsigned char *path); extern struct sysfs_attribute *sysfs_get_device_attr (struct sysfs_device *dev, const unsigned char *name); extern struct dlist *sysfs_get_device_attributes(struct sysfs_device *device); -extern struct sysfs_driver *sysfs_open_driver_by_name +extern struct sysfs_device *sysfs_open_device_by_name (unsigned char *dev_name, unsigned char *bus, size_t bsize); /* generic sysfs bus access */ diff --git a/lib/sysfs_device.c b/lib/sysfs_device.c index e37789c..6f28a24 100644 --- a/lib/sysfs_device.c +++ b/lib/sysfs_device.c @@ -73,20 +73,17 @@ struct sysfs_attribute *sysfs_get_device_attr(struct sysfs_device *dev, const unsigned char *name) { struct sysfs_attribute *cur = NULL; - unsigned char attrname[SYSFS_NAME_LEN]; if (dev == NULL || dev->directory == NULL || dev->directory->attributes == NULL || name == NULL) { errno = EINVAL; return NULL; } - dlist_for_each_data(dev->directory->attributes, cur, - struct sysfs_attribute) { - if (strcmp(cur->name, attrname) != 0) - continue; - + + cur = sysfs_get_directory_attribute(dev->directory, + (unsigned char *)name); + if (cur != NULL) return cur; - } return NULL; } @@ -350,8 +347,8 @@ struct dlist *sysfs_get_device_attributes(struct sysfs_device *device) * returns struct sysfs_device if found, NULL otherwise * NOTE: Use sysfs_close_device to close the device */ -struct sysfs_device *sysfs_open_device_by_name(char *dev_name, char *bus, - size_t bsize) +struct sysfs_device *sysfs_open_device_by_name(unsigned char *dev_name, + unsigned char *bus, size_t bsize) { char sysfs_path[SYSFS_PATH_MAX], device_path[SYSFS_PATH_MAX]; struct sysfs_device *device = NULL; diff --git a/lib/sysfs_dir.c b/lib/sysfs_dir.c index 4c271cc..af48032 100644 --- a/lib/sysfs_dir.c +++ b/lib/sysfs_dir.c @@ -160,12 +160,14 @@ struct sysfs_attribute *sysfs_open_attribute(const unsigned char *path) return sysattr; } + /** * sysfs_write_attribute: write value to the attribute * @sysattr: attribute to write * returns 0 with success and -1 with error. */ -int sysfs_write_attribute(struct sysfs_attribute *sysattr) +int sysfs_write_attribute(struct sysfs_attribute *sysattr, + const unsigned char *new_value) { int fd; int length; @@ -180,19 +182,43 @@ int sysfs_write_attribute(struct sysfs_attribute *sysattr) sysattr->path); return -1; } - - if ((fd = open(sysattr->path, O_RDWR)) < 0) { + if ((strncmp(sysattr->value, new_value, sysattr->len)) == 0) { + dprintf("Attribute %s already has the requested value %s\n", + sysattr->name, new_value); + return 0; + } + /* + * open O_WRONLY since some attributes have no "read" but only + * "write" permission + */ + if ((fd = open(sysattr->path, O_WRONLY)) < 0) { + perror("sysfs_write_attribute: open"); dprintf ("Error reading attribute %s\n", sysattr->path); return -1; } - length = write(fd, sysattr->value, sizeof(sysattr->value)); + length = write(fd, new_value, strlen(new_value)); if (length < 0) { + perror("sysfs_write_attribute: write"); dprintf("Error write to the attribute %s\n", sysattr->path); close(fd); return -1; } + + /* + * Validate length that has been copied. Alloc appropriate area + * in sysfs_attribute + */ + if (length != sysattr->len) { + free(sysattr->value); /* can we use realloc here? */ + sysattr->value = (char *)calloc(1, length); + strncpy(sysattr->value, new_value, length); + } else { + /*"length" of the new value is same as old one */ + strncpy(sysattr->value, new_value, length); + } + close(fd); return 0; } @@ -252,42 +278,6 @@ int sysfs_read_attribute(struct sysfs_attribute *sysattr) } /** - * sysfs_write_attribute_value: given path to attribute, - * value will be saved to the attribute. - * @attrpath: sysfs path to attribute - * @value: value to give to attribute - * returns 0 with success and -1 with error. - */ -int sysfs_write_attribute_value(const unsigned char *attrpath, - unsigned char *value) -{ - struct sysfs_attribute *attr = NULL; - - if (attrpath == NULL || value == NULL) { - errno = EINVAL; - return -1; - } - - attr = sysfs_open_attribute(attrpath); - if (attr == NULL) { - dprintf("Invalid attribute path %s\n", attrpath); - errno = EINVAL; - return -1; - } - strncpy(attr->value,value,sizeof(value)); - if ((sysfs_write_attribute(attr) != 0 )) { - dprintf("Error write to attribute %s\n", attrpath); - sysfs_close_attribute(attr); - return -1; - } - - sysfs_close_attribute(attr); - - return 0; -} - - -/** * sysfs_read_attribute_value: given path to attribute, return its value. * values can be up to a pagesize, if buffer is smaller the value will * be truncated. diff --git a/lib/sysfs_utils.c b/lib/sysfs_utils.c index 2dcf22a..617311e 100644 --- a/lib/sysfs_utils.c +++ b/lib/sysfs_utils.c @@ -285,3 +285,72 @@ struct dlist *sysfs_open_bus_devices_list(unsigned char *name) sysfs_close_directory(dir); return list; } + + +/** + * sysfs_change_attribute_value: "write" attribute support + * @device: bus/class device for which attribute has to be changed + * @attribute: attribute thats needs modification + * @value: value to change to + * returns 0 on success and -1 on error + */ +int sysfs_change_attribute_value(unsigned char *device, + unsigned char *attribute, unsigned char *value) +{ + struct sysfs_device *dev = NULL; + struct sysfs_class_device *clsdev = NULL; + struct sysfs_attribute *attrib = NULL; + struct dlist *attributes = NULL; + char subsys_name[SYSFS_NAME_LEN]; + + if (device == NULL || attribute == NULL || value == NULL) { + dprintf("Incorrect parameters supplied\n"); + return -1; + } + + dev = sysfs_open_device_by_name(device, subsys_name, SYSFS_NAME_LEN); + if (dev != NULL) { + attrib = sysfs_get_directory_attribute(dev->directory, + attribute); + if (attrib == NULL) { + dprintf("Attribute %s not defined for device %s\n", + attribute, device); + sysfs_close_device(dev); + return -1; + } + if ((sysfs_write_attribute(attrib, value)) < 0) { + dprintf("Error writing value %s to attribute %s\n", + value, attribute); + sysfs_close_device(dev); + return -1; + } + return 0; + } + + /* not found in bus subsys - look in class */ + if ((sysfs_find_device_class_name(device, subsys_name, + SYSFS_NAME_LEN)) < 0) { + dprintf("Device %s not found\n", device); + return -1; + } + clsdev = sysfs_open_class_device_by_name(subsys_name, device); + if (clsdev != NULL) { + attrib = sysfs_get_directory_attribute(clsdev->directory, + attribute); + if (attrib != NULL) { + if ((sysfs_write_attribute(attrib, value)) == 0) { + sysfs_close_class_device(clsdev); + return 0; + } + dprintf("Error writing attribute value\n"); + sysfs_close_class_device(clsdev); + return -1; + } + dprintf("Attribute %s not defined for device %s\n", + attribute, device); + return -1; + } + dprintf("Device %s not found\n", device); + return -1; +} + |