144 lines
4.2 KiB
Plaintext
144 lines
4.2 KiB
Plaintext
From e3354354518377b34fa3b501c11a62b61a54b0d4 Mon Sep 17 00:00:00 2001
|
|
From: Hannes Reinecke <hare@suse.de>
|
|
Date: Tue, 13 Jan 2009 15:34:55 +0100
|
|
Subject: [PATCH] Implement sysfs_attr_set_value()
|
|
|
|
Complement to sysfs_attr_get_value(). We might want to modify some
|
|
sysfs values from multipathing.
|
|
|
|
References: bnc#464155
|
|
|
|
Signed-off-by: Hannes Reinecke <hare@suse.de>
|
|
---
|
|
libmultipath/sysfs.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
libmultipath/sysfs.h | 2 +
|
|
2 files changed, 102 insertions(+), 0 deletions(-)
|
|
|
|
diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c
|
|
index e00a101..4a472ae 100644
|
|
--- a/libmultipath/sysfs.c
|
|
+++ b/libmultipath/sysfs.c
|
|
@@ -461,6 +461,106 @@ out:
|
|
return attr && attr->value && strlen(attr->value) ? attr->value : NULL;
|
|
}
|
|
|
|
+int sysfs_attr_set_value(const char *devpath, const char *attr_name,
|
|
+ char *value, int value_len)
|
|
+{
|
|
+ char path_full[PATH_SIZE];
|
|
+ const char *path;
|
|
+ struct sysfs_attr *attr_loop;
|
|
+ struct sysfs_attr *attr = NULL;
|
|
+ struct stat statbuf;
|
|
+ int fd;
|
|
+ ssize_t size = 0;
|
|
+ size_t sysfs_len;
|
|
+
|
|
+ dbg("open '%s'/'%s'", devpath, attr_name);
|
|
+ sysfs_len = strlcpy(path_full, sysfs_path, sizeof(path_full));
|
|
+ if(sysfs_len >= sizeof(path_full))
|
|
+ sysfs_len = sizeof(path_full) - 1;
|
|
+ path = &path_full[sysfs_len];
|
|
+ strlcat(path_full, devpath, sizeof(path_full));
|
|
+ strlcat(path_full, "/", sizeof(path_full));
|
|
+ strlcat(path_full, attr_name, sizeof(path_full));
|
|
+
|
|
+ /* look for attribute in cache */
|
|
+ list_for_each_entry(attr_loop, &attr_list, node) {
|
|
+ if (strcmp(attr_loop->path, path) == 0) {
|
|
+ dbg("found in cache '%s'", attr_loop->path);
|
|
+ attr = attr_loop;
|
|
+ }
|
|
+ }
|
|
+ if (!attr) {
|
|
+ /* store attribute in cache */
|
|
+ dbg("new uncached attribute '%s'", path_full);
|
|
+ attr = malloc(sizeof(struct sysfs_attr));
|
|
+ if (attr == NULL)
|
|
+ return -1;
|
|
+ memset(attr, 0x00, sizeof(struct sysfs_attr));
|
|
+ strlcpy(attr->path, path, sizeof(attr->path));
|
|
+ dbg("add to cache '%s'", path_full);
|
|
+ list_add(&attr->node, &attr_list);
|
|
+ } else {
|
|
+ /* clear old value */
|
|
+ if(attr->value)
|
|
+ memset(attr->value, 0x00, sizeof(attr->value));
|
|
+ }
|
|
+
|
|
+ if (lstat(path_full, &statbuf) != 0) {
|
|
+ dbg("stat '%s' failed: %s", path_full, strerror(errno));
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ if (S_ISLNK(statbuf.st_mode)) {
|
|
+ /* links return the last element of the target path */
|
|
+ char link_target[PATH_SIZE];
|
|
+ int len;
|
|
+ const char *pos;
|
|
+
|
|
+ len = readlink(path_full, link_target, sizeof(link_target));
|
|
+ if (len > 0) {
|
|
+ link_target[len] = '\0';
|
|
+ pos = strrchr(link_target, '/');
|
|
+ if (pos != NULL) {
|
|
+ dbg("cache '%s' with link value '%s'",
|
|
+ path_full, value);
|
|
+ strlcpy(attr->value_local, &pos[1],
|
|
+ sizeof(attr->value_local));
|
|
+ attr->value = attr->value_local;
|
|
+ }
|
|
+ }
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ /* skip directories */
|
|
+ if (S_ISDIR(statbuf.st_mode))
|
|
+ goto out;
|
|
+
|
|
+ /* skip non-readable files */
|
|
+ if ((statbuf.st_mode & S_IRUSR) == 0)
|
|
+ goto out;
|
|
+
|
|
+ /* write attribute value */
|
|
+ fd = open(path_full, O_WRONLY);
|
|
+ if (fd < 0) {
|
|
+ dbg("attribute '%s' can not be opened: %s",
|
|
+ path_full, strerror(errno));
|
|
+ goto out;
|
|
+ }
|
|
+ size = write(fd, value, value_len);
|
|
+ close(fd);
|
|
+ if (size < 0)
|
|
+ goto out;
|
|
+
|
|
+ /* successfully wrote new value, store it */
|
|
+ remove_trailing_chars(value, '\n');
|
|
+ dbg("cache '%s' with attribute value '%s'", path_full, value);
|
|
+ strlcpy(attr->value_local, value, sizeof(attr->value_local));
|
|
+ attr->value = attr->value_local;
|
|
+
|
|
+out:
|
|
+ return size;
|
|
+}
|
|
+
|
|
int sysfs_lookup_devpath_by_subsys_id(char *devpath_full, size_t len,
|
|
const char *subsystem, const char *id)
|
|
{
|
|
diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h
|
|
index 620962c..ac76acf 100644
|
|
--- a/libmultipath/sysfs.h
|
|
+++ b/libmultipath/sysfs.h
|
|
@@ -20,6 +20,8 @@ struct sysfs_device *sysfs_device_get_parent(struct sysfs_device *dev);
|
|
struct sysfs_device *sysfs_device_get_parent_with_subsystem(struct sysfs_device *dev, const char *subsystem);
|
|
void sysfs_device_put(struct sysfs_device *dev);
|
|
char *sysfs_attr_get_value(const char *devpath, const char *attr_name);
|
|
+int sysfs_attr_set_value(const char *devpath, const char *attr_name,
|
|
+ char *value, int value_len);
|
|
int sysfs_resolve_link(char *path, size_t size);
|
|
int sysfs_get_size (struct sysfs_device * dev, unsigned long long * size);
|
|
|
|
--
|
|
1.5.3.2
|
|
|