diff options
author | Tom Gundersen <teg@jklm.no> | 2014-11-11 16:37:55 +0100 |
---|---|---|
committer | Tom Gundersen <teg@jklm.no> | 2014-12-11 13:54:18 +0100 |
commit | 5b6c2d709fe07e4235256875ff5acc76a66bf427 (patch) | |
tree | 32686bf387067bf9af4f3ebbe2652003aeb448c9 | |
parent | f51a79ba39bdec25f5d2a6afc2cb0517728a7f95 (diff) |
sd-device: add sd_device_get_sysattr_value
-rw-r--r-- | src/libsystemd/sd-device/sd-device.c | 111 | ||||
-rw-r--r-- | src/systemd/sd-device.h | 1 |
2 files changed, 110 insertions, 2 deletions
diff --git a/src/libsystemd/sd-device/sd-device.c b/src/libsystemd/sd-device/sd-device.c index b582905a3..70fed11c4 100644 --- a/src/libsystemd/sd-device/sd-device.c +++ b/src/libsystemd/sd-device/sd-device.c @@ -30,6 +30,7 @@ #include "fileio.h" #include "hashmap.h" #include "set.h" +#include "strv.h" #include "sd-device.h" @@ -40,6 +41,7 @@ struct sd_device { sd_device *parent; OrderedHashmap *properties; + Hashmap *sysattrs; Set *tags; char *syspath; @@ -106,7 +108,7 @@ _public_ sd_device *sd_device_unref(sd_device *device) { free(device->id_filename); ordered_hashmap_free_free_free(device->properties); - + hashmap_free_free_free(device->sysattrs); set_free_free(device->tags); free(device); @@ -153,6 +155,43 @@ static int device_add_property(sd_device *device, const char *_key, const char * return 0; } +static int device_add_sysattr(sd_device *device, const char *_key, const char *_value) { + _cleanup_free_ char *key = NULL; + _cleanup_free_ char *value = NULL; + int r; + + assert(device); + assert(_key); + + + r = hashmap_ensure_allocated(&device->sysattrs, &string_hash_ops); + if (r < 0) + return r; + + key = strdup(_key); + if (!key) + return -ENOMEM; + + if (_value) { + value = strdup(_value); + if (!value) + return -ENOMEM; + } else { + value = strdup(""); + if (!value) + return -ENOMEM; + } + + r = hashmap_put(device->sysattrs, key, value); + if (r < 0) + return r; + + key = NULL; + value = NULL; + + return 0; +} + static int device_add_tag(sd_device *device, const char *tag) { int r; @@ -1195,7 +1234,7 @@ _public_ int sd_device_get_property_value(sd_device *device, const char *key, co if (r < 0) return r; - value = hashmap_get(device->properties, key); + value = ordered_hashmap_get(device->properties, key); if (!value) return -ENOENT; @@ -1213,3 +1252,71 @@ _public_ int sd_device_has_tag(sd_device *device, const char *tag, int *has_tag) return 0; } + +_public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value) { + _cleanup_close_ int fd = -1; + _cleanup_free_ char *value = NULL; + const char *syspath; + char *path; + struct stat statbuf; + int r; + + assert_return(device, -EINVAL); + assert_return(sysattr, -EINVAL); + assert_return(_value, -EINVAL); + + /* look for possibly already cached result */ + value = hashmap_get(device->sysattrs, sysattr); + if (value) { + if (isempty(value)) + return -ENOENT; + + *_value = value; + value = NULL; + + return 0; + } + + r = sd_device_get_syspath(device, &syspath); + if (r < 0) + return r; + + path = strappenda(syspath, "/", sysattr); + r = lstat(path, &statbuf); + if (r < 0) { + r = device_add_sysattr(device, sysattr, NULL); + if (r < 0) + return r; + + return -ENOENT; + } else if (S_ISLNK(statbuf.st_mode)) { + /* Some core links return only the last element of the target path, + * these are just values, the paths should not be exposed. */ + if (STR_IN_SET(sysattr, "driver", "subsystem", "module")) { + r = readlink_value(path, &value); + if (r < 0) + return r; + } else + return -EINVAL; + } else if (S_ISDIR(statbuf.st_mode)) { + /* skip directories */ + return -EINVAL; + } else if (!(statbuf.st_mode & S_IRUSR)) { + /* skip non-readable files */ + return -EPERM; + } else { + /* read attribute value */ + r = read_one_line_file(path, &value); + if (r < 0) + return r; + } + + r = device_add_sysattr(device, sysattr, value); + if (r < 0) + return r; + + *_value = value; + value = NULL; + + return 0; +} diff --git a/src/systemd/sd-device.h b/src/systemd/sd-device.h index 09f2137b1..15df05e84 100644 --- a/src/systemd/sd-device.h +++ b/src/systemd/sd-device.h @@ -52,6 +52,7 @@ int sd_device_get_is_initialized(sd_device *device, int *initialized); int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *usec); int sd_device_get_property_value(sd_device *device, const char *key, const char **value); int sd_device_has_tag(sd_device *device, const char *tag, int *has_tag); +int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value); _SD_END_DECLARATIONS; |