libudev: implement udev_device_set_attribute_value()
This commit is contained in:
committed by
Kay Sievers
parent
814cc56212
commit
946f182575
+3
-3
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user