From 1223227f952a1939a592760ae437e417ba24bb01 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 14 Dec 2020 16:40:10 +0900 Subject: [PATCH] udev: move util_resolve_subsys_kernel() to udev-util.c --- src/libudev/libudev-util.c | 57 --------------------------------- src/libudev/libudev-util.h | 1 - src/shared/udev-util.c | 65 ++++++++++++++++++++++++++++++++++++++ src/shared/udev-util.h | 1 + src/test/test-libudev.c | 34 -------------------- src/test/test-udev-util.c | 33 +++++++++++++++++++ src/udev/udev-event.c | 2 +- src/udev/udev-rules.c | 8 ++--- 8 files changed, 104 insertions(+), 97 deletions(-) diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c index 8a6b56be5c..a4835d4f40 100644 --- a/src/libudev/libudev-util.c +++ b/src/libudev/libudev-util.c @@ -18,63 +18,6 @@ * Utilities useful when dealing with devices and device node names. */ -/* handle "[/]" format */ -int util_resolve_subsys_kernel(const char *string, char *result, size_t maxsize, bool read_value) { - char temp[UTIL_PATH_SIZE], *subsys, *sysname, *attr; - _cleanup_(sd_device_unrefp) sd_device *dev = NULL; - const char *val; - int r; - - if (string[0] != '[') - return -EINVAL; - - strscpy(temp, sizeof(temp), string); - - subsys = &temp[1]; - - sysname = strchr(subsys, '/'); - if (!sysname) - return -EINVAL; - sysname[0] = '\0'; - sysname = &sysname[1]; - - attr = strchr(sysname, ']'); - if (!attr) - return -EINVAL; - attr[0] = '\0'; - attr = &attr[1]; - if (attr[0] == '/') - attr = &attr[1]; - if (attr[0] == '\0') - attr = NULL; - - if (read_value && !attr) - return -EINVAL; - - r = sd_device_new_from_subsystem_sysname(&dev, subsys, sysname); - if (r < 0) - return r; - - if (read_value) { - r = sd_device_get_sysattr_value(dev, attr, &val); - if (r < 0 && r != -ENOENT) - return r; - if (r == -ENOENT) - result[0] = '\0'; - else - strscpy(result, maxsize, val); - log_debug("value '[%s/%s]%s' is '%s'", subsys, sysname, attr, result); - } else { - r = sd_device_get_syspath(dev, &val); - if (r < 0) - return r; - - strscpyl(result, maxsize, val, attr ? "/" : NULL, attr ?: NULL, NULL); - log_debug("path '[%s/%s]%s' is '%s'", subsys, sysname, strempty(attr), result); - } - return 0; -} - /** * udev_util_encode_string: * @str: input string to be encoded diff --git a/src/libudev/libudev-util.h b/src/libudev/libudev-util.h index 547981311e..f03e9eb221 100644 --- a/src/libudev/libudev-util.h +++ b/src/libudev/libudev-util.h @@ -9,7 +9,6 @@ #define UTIL_PATH_SIZE 1024 #define UTIL_NAME_SIZE 512 #define UTIL_LINE_SIZE 16384 -int util_resolve_subsys_kernel(const char *string, char *result, size_t maxsize, bool read_value); /* Cleanup functions */ DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev*, udev_unref); diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index d03e4bbe6f..5a506887e7 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -16,6 +16,7 @@ #include "signal-util.h" #include "string-table.h" #include "string-util.h" +#include "strxcpyx.h" #include "udev-util.h" #include "utf8.h" @@ -471,3 +472,67 @@ size_t udev_replace_chars(char *str, const char *allow) { } return replaced; } + +int udev_resolve_subsys_kernel(const char *string, char *result, size_t maxsize, bool read_value) { + _cleanup_(sd_device_unrefp) sd_device *dev = NULL; + _cleanup_free_ char *temp = NULL; + char *subsys, *sysname, *attr; + const char *val; + int r; + + assert(string); + assert(result); + + /* handle "[/]" format */ + + if (string[0] != '[') + return -EINVAL; + + temp = strdup(string); + if (!temp) + return -ENOMEM; + + subsys = &temp[1]; + + sysname = strchr(subsys, '/'); + if (!sysname) + return -EINVAL; + sysname[0] = '\0'; + sysname = &sysname[1]; + + attr = strchr(sysname, ']'); + if (!attr) + return -EINVAL; + attr[0] = '\0'; + attr = &attr[1]; + if (attr[0] == '/') + attr = &attr[1]; + if (attr[0] == '\0') + attr = NULL; + + if (read_value && !attr) + return -EINVAL; + + r = sd_device_new_from_subsystem_sysname(&dev, subsys, sysname); + if (r < 0) + return r; + + if (read_value) { + r = sd_device_get_sysattr_value(dev, attr, &val); + if (r < 0 && r != -ENOENT) + return r; + if (r == -ENOENT) + result[0] = '\0'; + else + strscpy(result, maxsize, val); + log_debug("value '[%s/%s]%s' is '%s'", subsys, sysname, attr, result); + } else { + r = sd_device_get_syspath(dev, &val); + if (r < 0) + return r; + + strscpyl(result, maxsize, val, attr ? "/" : NULL, attr ?: NULL, NULL); + log_debug("path '[%s/%s]%s' is '%s'", subsys, sysname, strempty(attr), result); + } + return 0; +} diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h index f20e32b4d2..94ec970c50 100644 --- a/src/shared/udev-util.h +++ b/src/shared/udev-util.h @@ -38,3 +38,4 @@ void log_device_uevent(sd_device *device, const char *str); int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos); size_t udev_replace_whitespace(const char *str, char *to, size_t len); size_t udev_replace_chars(char *str, const char *allow); +int udev_resolve_subsys_kernel(const char *string, char *result, size_t maxsize, bool read_value); diff --git a/src/test/test-libudev.c b/src/test/test-libudev.c index 6f72abc007..12bd0d6299 100644 --- a/src/test/test-libudev.c +++ b/src/test/test-libudev.c @@ -345,38 +345,6 @@ static void test_hwdb(struct udev *udev, const char *modalias) { assert_se(hwdb == NULL); } -static void test_util_resolve_subsys_kernel_one(const char *str, bool read_value, int retval, const char *expected) { - char result[UTIL_PATH_SIZE] = ""; - int r; - - r = util_resolve_subsys_kernel(str, result, sizeof(result), read_value); - log_info("\"%s\" → expect: \"%s\", %d, actual: \"%s\", %d", str, strnull(expected), retval, result, r); - assert_se(r == retval); - if (r >= 0) - assert_se(streq(result, expected)); -} - -static void test_util_resolve_subsys_kernel(void) { - log_info("/* %s */", __func__); - - test_util_resolve_subsys_kernel_one("hoge", false, -EINVAL, NULL); - test_util_resolve_subsys_kernel_one("[hoge", false, -EINVAL, NULL); - test_util_resolve_subsys_kernel_one("[hoge/foo", false, -EINVAL, NULL); - test_util_resolve_subsys_kernel_one("[hoge/]", false, -ENODEV, NULL); - - test_util_resolve_subsys_kernel_one("[net/lo]", false, 0, "/sys/devices/virtual/net/lo"); - test_util_resolve_subsys_kernel_one("[net/lo]/", false, 0, "/sys/devices/virtual/net/lo"); - test_util_resolve_subsys_kernel_one("[net/lo]hoge", false, 0, "/sys/devices/virtual/net/lo/hoge"); - test_util_resolve_subsys_kernel_one("[net/lo]/hoge", false, 0, "/sys/devices/virtual/net/lo/hoge"); - - test_util_resolve_subsys_kernel_one("[net/lo]", true, -EINVAL, NULL); - test_util_resolve_subsys_kernel_one("[net/lo]/", true, -EINVAL, NULL); - test_util_resolve_subsys_kernel_one("[net/lo]hoge", true, 0, ""); - test_util_resolve_subsys_kernel_one("[net/lo]/hoge", true, 0, ""); - test_util_resolve_subsys_kernel_one("[net/lo]address", true, 0, "00:00:00:00:00:00"); - test_util_resolve_subsys_kernel_one("[net/lo]/address", true, 0, "00:00:00:00:00:00"); -} - static void test_list(void) { _cleanup_(udev_list_freep) struct udev_list *list = NULL; struct udev_list_entry *e; @@ -519,8 +487,6 @@ static int run(int argc, char *argv[]) { if (arg_monitor) test_monitor(udev); - test_util_resolve_subsys_kernel(); - test_list(); return 0; diff --git a/src/test/test-udev-util.c b/src/test/test-udev-util.c index 50d31f44e0..f34c5c27d3 100644 --- a/src/test/test-udev-util.c +++ b/src/test/test-udev-util.c @@ -235,6 +235,38 @@ static void test_udev_replace_whitespace(void) { test_udev_replace_whitespace_one_len(" hoge hoge ", 0, ""); } +static void test_udev_resolve_subsys_kernel_one(const char *str, bool read_value, int retval, const char *expected) { + char result[PATH_MAX] = ""; + int r; + + r = udev_resolve_subsys_kernel(str, result, sizeof(result), read_value); + log_info("\"%s\" → expect: \"%s\", %d, actual: \"%s\", %d", str, strnull(expected), retval, result, r); + assert_se(r == retval); + if (r >= 0) + assert_se(streq(result, expected)); +} + +static void test_udev_resolve_subsys_kernel(void) { + log_info("/* %s */", __func__); + + test_udev_resolve_subsys_kernel_one("hoge", false, -EINVAL, NULL); + test_udev_resolve_subsys_kernel_one("[hoge", false, -EINVAL, NULL); + test_udev_resolve_subsys_kernel_one("[hoge/foo", false, -EINVAL, NULL); + test_udev_resolve_subsys_kernel_one("[hoge/]", false, -ENODEV, NULL); + + test_udev_resolve_subsys_kernel_one("[net/lo]", false, 0, "/sys/devices/virtual/net/lo"); + test_udev_resolve_subsys_kernel_one("[net/lo]/", false, 0, "/sys/devices/virtual/net/lo"); + test_udev_resolve_subsys_kernel_one("[net/lo]hoge", false, 0, "/sys/devices/virtual/net/lo/hoge"); + test_udev_resolve_subsys_kernel_one("[net/lo]/hoge", false, 0, "/sys/devices/virtual/net/lo/hoge"); + + test_udev_resolve_subsys_kernel_one("[net/lo]", true, -EINVAL, NULL); + test_udev_resolve_subsys_kernel_one("[net/lo]/", true, -EINVAL, NULL); + test_udev_resolve_subsys_kernel_one("[net/lo]hoge", true, 0, ""); + test_udev_resolve_subsys_kernel_one("[net/lo]/hoge", true, 0, ""); + test_udev_resolve_subsys_kernel_one("[net/lo]address", true, 0, "00:00:00:00:00:00"); + test_udev_resolve_subsys_kernel_one("[net/lo]/address", true, 0, "00:00:00:00:00:00"); +} + int main(int argc, char **argv) { test_parse_value(); test_parse_value_with_backslashes(); @@ -253,6 +285,7 @@ int main(int argc, char **argv) { test_parse_value_unicode(); test_udev_replace_whitespace(); + test_udev_resolve_subsys_kernel(); return EXIT_SUCCESS; } diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index f5831ed28d..c36f0bb732 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -346,7 +346,7 @@ static ssize_t udev_event_subst_format( return -EINVAL; /* try to read the value specified by "[dmi/id]product_name" */ - if (util_resolve_subsys_kernel(attr, vbuf, sizeof(vbuf), true) == 0) + if (udev_resolve_subsys_kernel(attr, vbuf, sizeof(vbuf), true) == 0) val = vbuf; /* try to read the attribute the device */ diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 7bfc25fdb5..c050eea56f 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -76,7 +76,7 @@ typedef enum { TK_M_TAG, /* strv, sd_device_get_tag_first(), sd_device_get_tag_next() */ TK_M_SUBSYSTEM, /* string, sd_device_get_subsystem() */ TK_M_DRIVER, /* string, sd_device_get_driver() */ - TK_M_ATTR, /* string, takes filename through attribute, sd_device_get_sysattr_value(), util_resolve_subsys_kernel(), etc. */ + TK_M_ATTR, /* string, takes filename through attribute, sd_device_get_sysattr_value(), udev_resolve_subsys_kernel(), etc. */ TK_M_SYSCTL, /* string, takes kernel parameter through attribute */ /* matches parent parameters */ @@ -1396,7 +1396,7 @@ static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *ev return false; break; case SUBST_TYPE_SUBSYS: - if (util_resolve_subsys_kernel(name, vbuf, sizeof(vbuf), true) < 0) + if (udev_resolve_subsys_kernel(name, vbuf, sizeof(vbuf), true) < 0) return false; value = vbuf; break; @@ -1641,7 +1641,7 @@ static int udev_rule_apply_token_to_event( (void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false); if (!path_is_absolute(buf) && - util_resolve_subsys_kernel(buf, buf, sizeof(buf), false) < 0) { + udev_resolve_subsys_kernel(buf, buf, sizeof(buf), false) < 0) { char tmp[UTIL_PATH_SIZE]; r = sd_device_get_syspath(dev, &val); @@ -2114,7 +2114,7 @@ static int udev_rule_apply_token_to_event( const char *key_name = token->data; char value[UTIL_NAME_SIZE]; - if (util_resolve_subsys_kernel(key_name, buf, sizeof(buf), false) < 0 && + if (udev_resolve_subsys_kernel(key_name, buf, sizeof(buf), false) < 0 && sd_device_get_syspath(dev, &val) >= 0) strscpyl(buf, sizeof(buf), val, "/", key_name, NULL);