summaryrefslogtreecommitdiff
path: root/udev/lib
diff options
context:
space:
mode:
Diffstat (limited to 'udev/lib')
-rw-r--r--udev/lib/exported_symbols1
-rw-r--r--udev/lib/libudev-device.c74
-rw-r--r--udev/lib/libudev-enumerate.c2
-rw-r--r--udev/lib/libudev-private.h4
-rw-r--r--udev/lib/libudev-util.c13
-rw-r--r--udev/lib/libudev.h1
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,