udev: move util_resolve_subsys_kernel() to udev-util.c

This commit is contained in:
Yu Watanabe 2020-12-14 16:40:10 +09:00
parent 393fcaf733
commit 1223227f95
8 changed files with 104 additions and 97 deletions

View File

@ -18,63 +18,6 @@
* Utilities useful when dealing with devices and device node names.
*/
/* handle "[<SUBSYSTEM>/<KERNEL>]<attribute>" 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

View File

@ -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);

View File

@ -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 "[<SUBSYSTEM>/<KERNEL>]<attribute>" 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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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 */

View File

@ -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);