diff options
Diffstat (limited to 'udev/lib')
-rw-r--r-- | udev/lib/exported_symbols | 1 | ||||
-rw-r--r-- | udev/lib/libudev-device.c | 74 | ||||
-rw-r--r-- | udev/lib/libudev-enumerate.c | 2 | ||||
-rw-r--r-- | udev/lib/libudev-private.h | 4 | ||||
-rw-r--r-- | udev/lib/libudev-util.c | 13 | ||||
-rw-r--r-- | udev/lib/libudev.h | 1 |
6 files changed, 89 insertions, 6 deletions
diff --git a/udev/lib/exported_symbols b/udev/lib/exported_symbols index f53165d810..aa3854d2aa 100644 --- a/udev/lib/exported_symbols +++ b/udev/lib/exported_symbols @@ -22,6 +22,7 @@ udev_device_get_action udev_device_get_driver udev_device_get_devnum udev_device_get_seqnum +udev_device_get_attr_value udev_enumerate_devices udev_monitor_new_from_socket udev_monitor_new_from_netlink diff --git a/udev/lib/libudev-device.c b/udev/lib/libudev-device.c index f400b621b7..cda2de7490 100644 --- a/udev/lib/libudev-device.c +++ b/udev/lib/libudev-device.c @@ -26,6 +26,7 @@ #include <errno.h> #include <string.h> #include <dirent.h> +#include <fcntl.h> #include <sys/stat.h> #include "libudev.h" @@ -52,6 +53,7 @@ struct udev_device { int num_fake_partitions; int devlink_priority; int ignore_remove; + struct list_head attr_list; }; static size_t devpath_to_db_path(struct udev *udev, const char *devpath, char *filename, size_t len) @@ -164,6 +166,7 @@ struct udev_device *device_init(struct udev *udev) udev_device->udev = udev; INIT_LIST_HEAD(&udev_device->link_list); INIT_LIST_HEAD(&udev_device->env_list); + INIT_LIST_HEAD(&udev_device->attr_list); info(udev_device->udev, "udev_device: %p created\n", udev_device); return udev_device; } @@ -302,6 +305,7 @@ void udev_device_unref(struct udev_device *udev_device) free(udev_device->driver); free(udev_device->devpath_old); free(udev_device->physdevpath); + util_name_list_cleanup(udev_device->udev, &udev_device->attr_list); info(udev_device->udev, "udev_device: %p released\n", udev_device); free(udev_device); } @@ -489,6 +493,72 @@ unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device) return udev_device->seqnum; } +const char *udev_device_get_attr_value(struct udev_device *udev_device, const char *attr) +{ + char path[UTIL_PATH_SIZE]; + char value[UTIL_NAME_SIZE]; + struct stat statbuf; + int fd; + ssize_t size; + const char *val = NULL; + + util_strlcpy(path, udev_device_get_syspath(udev_device), sizeof(path)); + util_strlcat(path, "/", sizeof(path)); + util_strlcat(path, attr, sizeof(path)); + + if (lstat(path, &statbuf) != 0) { + info(udev_device->udev, "stat '%s' failed: %s\n", path, strerror(errno)); + goto out; + } + + if (S_ISLNK(statbuf.st_mode)) { + /* links return the last element of the target path */ + char target[UTIL_NAME_SIZE]; + int len; + char *pos; + + len = readlink(path, target, sizeof(target)); + if (len > 0) { + target[len] = '\0'; + pos = strrchr(target, '/'); + if (pos != NULL) { + pos = &pos[1]; + info(udev_device->udev, "cache '%s' with link value '%s'\n", attr, pos); + val = util_name_list_add(udev_device->udev, &udev_device->attr_list, attr, pos, 0)->value; + } + } + 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; + + /* read attribute value */ + fd = open(path, O_RDONLY); + if (fd < 0) { + info(udev_device->udev, "attribute '%s' can not be opened\n", path); + goto out; + } + size = read(fd, value, sizeof(value)); + close(fd); + if (size < 0) + goto out; + if (size == sizeof(value)) + goto out; + + /* got a valid value, store and return it */ + value[size] = '\0'; + util_remove_trailing_chars(value, '\n'); + info(udev_device->udev, "'%s' has attribute value '%s'\n", path, value); + val = util_name_list_add(udev_device->udev, &udev_device->attr_list, attr, value, 0)->value; +out: + return val; +} int device_set_devpath(struct udev_device *udev_device, const char *devpath) { if (asprintf(&udev_device->syspath, "%s%s", udev_get_sys_path(udev_device->udev), devpath) < 0) @@ -518,14 +588,14 @@ int device_set_devname(struct udev_device *udev_device, const char *devname) int device_add_devlink(struct udev_device *udev_device, const char *devlink) { - if (util_name_list_add(udev_device->udev, &udev_device->link_list, devlink, 0) == NULL) + if (util_name_list_add(udev_device->udev, &udev_device->link_list, devlink, NULL, 0) == NULL) return -ENOMEM; return 0; } int device_add_property(struct udev_device *udev_device, const char *property) { - if (util_name_list_add(udev_device->udev, &udev_device->env_list, property, 0) == NULL) + if (util_name_list_add(udev_device->udev, &udev_device->env_list, property, NULL, 0) == NULL) return -ENOMEM; return 0; } diff --git a/udev/lib/libudev-enumerate.c b/udev/lib/libudev-enumerate.c index 9bd9101052..95a407652a 100644 --- a/udev/lib/libudev-enumerate.c +++ b/udev/lib/libudev-enumerate.c @@ -58,7 +58,7 @@ static int devices_scan_subsystem(struct udev *udev, util_strlcat(devpath, "/", sizeof(devpath)); util_strlcat(devpath, dent->d_name, sizeof(devpath)); util_resolve_sys_link(udev, devpath, sizeof(devpath)); - util_name_list_add(udev, device_list, devpath, 1); + util_name_list_add(udev, device_list, devpath, NULL, 1); } closedir(dir); return 0; diff --git a/udev/lib/libudev-private.h b/udev/lib/libudev-private.h index 8ca441639f..c2a3268038 100644 --- a/udev/lib/libudev-private.h +++ b/udev/lib/libudev-private.h @@ -110,13 +110,14 @@ extern int udev_ctrl_get_set_max_childs(struct udev_ctrl_msg *ctrl_msg); struct util_name_entry { struct list_head node; char *name; + char *value; int *i; }; extern ssize_t util_get_sys_subsystem(struct udev *udev, const char *devpath, char *subsystem, size_t size); extern ssize_t util_get_sys_driver(struct udev *udev, const char *devpath, char *driver, size_t size); extern int util_resolve_sys_link(struct udev *udev, char *devpath, size_t size); extern struct util_name_entry *util_name_list_add(struct udev *udev, struct list_head *name_list, - const char *name, int sort); + const char *name, const char *value, int sort); extern void util_name_list_cleanup(struct udev *udev, struct list_head *name_list); extern int util_log_priority(const char *priority); extern size_t util_path_encode(char *s, size_t len); @@ -125,4 +126,5 @@ extern void util_remove_trailing_chars(char *path, char c); extern size_t util_strlcpy(char *dst, const char *src, size_t size); extern size_t util_strlcat(char *dst, const char *src, size_t size); extern int util_replace_chars(char *str, const char *white); +extern char *util_sysattr_get_value(struct udev *udev, const char *devpath, const char *attr_name); #endif diff --git a/udev/lib/libudev-util.c b/udev/lib/libudev-util.c index 7aea8c67fb..50eacdd37d 100644 --- a/udev/lib/libudev-util.c +++ b/udev/lib/libudev-util.c @@ -27,6 +27,7 @@ #include <string.h> #include <dirent.h> #include <ctype.h> +#include <fcntl.h> #include <sys/stat.h> #include "libudev.h" @@ -97,7 +98,7 @@ int util_resolve_sys_link(struct udev *udev, char *devpath, size_t size) } struct util_name_entry *util_name_list_add(struct udev *udev, struct list_head *name_list, - const char *name, int sort) + const char *name, const char *value, int sort) { struct util_name_entry *name_loop; struct util_name_entry *name_new; @@ -126,7 +127,14 @@ struct util_name_entry *util_name_list_add(struct udev *udev, struct list_head * free(name_new); return NULL; } - dbg(udev, "adding '%s'\n", name_new->name); + if (value != NULL) { + name_new->value = strdup(value); + if (name_new->value == NULL) { + free(name_new); + return NULL; + } + } + dbg(udev, "adding '%s=%s'\n", name_new->name, name_new->value); list_add_tail(&name_new->node, &name_loop->node); return name_new; } @@ -139,6 +147,7 @@ void util_name_list_cleanup(struct udev *udev, struct list_head *name_list) list_for_each_entry_safe(name_loop, name_tmp, name_list, node) { list_del(&name_loop->node); free(name_loop->name); + free(name_loop->value); free(name_loop); } } diff --git a/udev/lib/libudev.h b/udev/lib/libudev.h index 703364380b..05f23e1705 100644 --- a/udev/lib/libudev.h +++ b/udev/lib/libudev.h @@ -67,6 +67,7 @@ extern const char *udev_device_get_driver(struct udev_device *udev_device); extern dev_t udev_device_get_devnum(struct udev_device *udev_device); extern const char *udev_device_get_action(struct udev_device *udev_device); extern unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device); +extern const char *udev_device_get_attr_value(struct udev_device *udev_device, const char *attr); extern int udev_enumerate_devices(struct udev *udev, const char *subsystem, int (*cb)(struct udev *udev, |