summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormananth <mananth>2003-10-15 12:16:35 +0000
committermananth <mananth>2003-10-15 12:16:35 +0000
commita8dc5520e8863135dd277f37711564a8b4c73a06 (patch)
treeea134160a2324f64e73d7913c0a85be88572c67c
parentfc281a0436d90c72d33044190c95eb00be67f08a (diff)
downloadsysfsutils-a8dc5520e8863135dd277f37711564a8b4c73a06.tar.gz
Corrected "write attribute" functions
-rw-r--r--ChangeLog9
-rw-r--r--include/libsysfs.h9
-rw-r--r--lib/sysfs_device.c15
-rw-r--r--lib/sysfs_dir.c70
-rw-r--r--lib/sysfs_utils.c69
5 files changed, 118 insertions, 54 deletions
diff --git a/ChangeLog b/ChangeLog
index 6393174..09ba5c3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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;
+}
+