[systemd-commits] docs/libudev Makefile.am src/libudev

Kay Sievers kay at kemper.freedesktop.org
Wed Mar 13 09:47:09 PDT 2013


 Makefile.am                       |    6 +-
 docs/libudev/libudev-sections.txt |    1 
 src/libudev/libudev-device.c      |  102 ++++++++++++++++++++++++++++++++++++++
 src/libudev/libudev.h             |    1 
 src/libudev/libudev.sym           |    4 +
 5 files changed, 111 insertions(+), 3 deletions(-)

New commits:
commit 946f1825751919a176cd0039002a514de0c9c70f
Author: Hannes Reinecke <hare at suse.de>
Date:   Mon Mar 11 12:49:27 2013 +0100

    libudev: implement udev_device_set_attribute_value()

diff --git a/Makefile.am b/Makefile.am
index 2a010c7..3073b0d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,9 +31,9 @@ SUBDIRS = . po
 # keep intermediate files
 .SECONDARY:
 
-LIBUDEV_CURRENT=3
-LIBUDEV_REVISION=2
-LIBUDEV_AGE=2
+LIBUDEV_CURRENT=4
+LIBUDEV_REVISION=0
+LIBUDEV_AGE=3
 
 LIBGUDEV_CURRENT=1
 LIBGUDEV_REVISION=3
diff --git a/docs/libudev/libudev-sections.txt b/docs/libudev/libudev-sections.txt
index 067a3f5..c154645 100644
--- a/docs/libudev/libudev-sections.txt
+++ b/docs/libudev/libudev-sections.txt
@@ -53,6 +53,7 @@ udev_device_get_driver
 udev_device_get_devnum
 udev_device_get_action
 udev_device_get_sysattr_value
+udev_device_set_sysattr_value
 udev_device_get_sysattr_list_entry
 udev_device_get_seqnum
 udev_device_get_usec_since_initialized
diff --git a/src/libudev/libudev-device.c b/src/libudev/libudev-device.c
index 9fe3d63..05c5fbc 100644
--- a/src/libudev/libudev-device.c
+++ b/src/libudev/libudev-device.c
@@ -1440,6 +1440,108 @@ out:
         return val;
 }
 
+/**
+ * udev_device_set_sysattr_value:
+ * @udev_device: udev device
+ * @sysattr: attribute name
+ * @value: new value to be set
+ *
+ * Update the contents of the sys attribute and the cached value of the device.
+ *
+ * Returns: Negative error code on failure or 0 on success.
+ **/
+_public_ int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value)
+{
+        struct udev_device *dev;
+        char path[UTIL_PATH_SIZE];
+        struct stat statbuf;
+        int fd;
+        ssize_t size, value_len;
+        int ret = 0;
+
+        if (udev_device == NULL)
+                return -EINVAL;
+        dev = udev_device;
+        if (sysattr == NULL)
+                return -EINVAL;
+        if (value == NULL)
+                value_len = 0;
+        else
+                value_len = strlen(value);
+restart:
+        strscpyl(path, sizeof(path), udev_device_get_syspath(dev), "/", sysattr, NULL);
+        if (lstat(path, &statbuf) != 0) {
+                udev_list_entry_add(&dev->sysattr_value_list, sysattr, NULL);
+                ret = -ENXIO;
+                goto out;
+        }
+
+        if (S_ISLNK(statbuf.st_mode)) {
+                /*
+                 * Cannot modify core link values
+                 */
+                if (streq(sysattr, "driver") ||
+                    streq(sysattr, "subsystem") ||
+                    streq(sysattr, "module")) {
+                        ret = -EPERM;
+                } else if (!streq(sysattr, "device")) {
+                        /* resolve custom link to a device */
+                        strscpyl(path, sizeof(path), udev_device->syspath, "/", sysattr, NULL);
+                        dev = udev_device_new_from_syspath(udev_device->udev, path);
+                        if (dev != NULL)
+                                goto restart;
+                        ret = -ENXIO;
+                } else {
+                        /* Unhandled, to not try to modify anything */
+                        ret = -EINVAL;
+                }
+                goto out;
+        }
+
+        /* skip directories */
+        if (S_ISDIR(statbuf.st_mode)) {
+                ret = -EISDIR;
+                goto out;
+        }
+
+        /* skip non-readable files */
+        if ((statbuf.st_mode & S_IRUSR) == 0) {
+                ret = -EACCES;
+                goto out;
+        }
+
+        /* Value is limited to 4k */
+        if (value_len > 4096) {
+                ret = -EINVAL;
+                goto out;
+        }
+        util_remove_trailing_chars(value, '\n');
+
+        /* write attribute value */
+        fd = open(path, O_WRONLY|O_CLOEXEC);
+        if (fd < 0) {
+                ret = -errno;
+                goto out;
+        }
+        size = write(fd, value, value_len);
+        close(fd);
+        if (size < 0) {
+                ret = -errno;
+                goto out;
+        }
+        if (size < value_len) {
+                ret = -EIO;
+                goto out;
+        }
+
+        /* wrote a valid value, store it in cache and return it */
+        udev_list_entry_add(&dev->sysattr_value_list, sysattr, value);
+out:
+        if (dev != udev_device)
+                udev_device_unref(dev);
+        return ret;
+}
+
 static int udev_device_sysattr_list_read(struct udev_device *udev_device)
 {
         struct dirent *dent;
diff --git a/src/libudev/libudev.h b/src/libudev/libudev.h
index bb41532..61567b1 100644
--- a/src/libudev/libudev.h
+++ b/src/libudev/libudev.h
@@ -107,6 +107,7 @@ const char *udev_device_get_action(struct udev_device *udev_device);
 unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device);
 unsigned long long int udev_device_get_usec_since_initialized(struct udev_device *udev_device);
 const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr);
+int udev_device_set_sysattr_value(struct udev_device *udev_device, const char *sysattr, char *value);
 int udev_device_has_tag(struct udev_device *udev_device, const char *tag);
 
 /*
diff --git a/src/libudev/libudev.sym b/src/libudev/libudev.sym
index df6a1ae..c232fbf 100644
--- a/src/libudev/libudev.sym
+++ b/src/libudev/libudev.sym
@@ -108,3 +108,7 @@ global:
         udev_hwdb_unref;
         udev_hwdb_get_properties_list_entry;
 } LIBUDEV_189;
+
+LIBUDEV_199 {
+        udev_device_set_sysattr_value;
+} LIBUDEV_196;



More information about the systemd-commits mailing list