udev: move util_resolve_subsys_kernel() to udev-util.c
This commit is contained in:
parent
393fcaf733
commit
1223227f95
|
@ -18,63 +18,6 @@
|
||||||
* Utilities useful when dealing with devices and device node names.
|
* 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:
|
* udev_util_encode_string:
|
||||||
* @str: input string to be encoded
|
* @str: input string to be encoded
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#define UTIL_PATH_SIZE 1024
|
#define UTIL_PATH_SIZE 1024
|
||||||
#define UTIL_NAME_SIZE 512
|
#define UTIL_NAME_SIZE 512
|
||||||
#define UTIL_LINE_SIZE 16384
|
#define UTIL_LINE_SIZE 16384
|
||||||
int util_resolve_subsys_kernel(const char *string, char *result, size_t maxsize, bool read_value);
|
|
||||||
|
|
||||||
/* Cleanup functions */
|
/* Cleanup functions */
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev*, udev_unref);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev*, udev_unref);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "signal-util.h"
|
#include "signal-util.h"
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
#include "strxcpyx.h"
|
||||||
#include "udev-util.h"
|
#include "udev-util.h"
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
|
|
||||||
|
@ -471,3 +472,67 @@ size_t udev_replace_chars(char *str, const char *allow) {
|
||||||
}
|
}
|
||||||
return replaced;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
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_whitespace(const char *str, char *to, size_t len);
|
||||||
size_t udev_replace_chars(char *str, const char *allow);
|
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);
|
||||||
|
|
|
@ -345,38 +345,6 @@ static void test_hwdb(struct udev *udev, const char *modalias) {
|
||||||
assert_se(hwdb == NULL);
|
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) {
|
static void test_list(void) {
|
||||||
_cleanup_(udev_list_freep) struct udev_list *list = NULL;
|
_cleanup_(udev_list_freep) struct udev_list *list = NULL;
|
||||||
struct udev_list_entry *e;
|
struct udev_list_entry *e;
|
||||||
|
@ -519,8 +487,6 @@ static int run(int argc, char *argv[]) {
|
||||||
if (arg_monitor)
|
if (arg_monitor)
|
||||||
test_monitor(udev);
|
test_monitor(udev);
|
||||||
|
|
||||||
test_util_resolve_subsys_kernel();
|
|
||||||
|
|
||||||
test_list();
|
test_list();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -235,6 +235,38 @@ static void test_udev_replace_whitespace(void) {
|
||||||
test_udev_replace_whitespace_one_len(" hoge hoge ", 0, "");
|
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) {
|
int main(int argc, char **argv) {
|
||||||
test_parse_value();
|
test_parse_value();
|
||||||
test_parse_value_with_backslashes();
|
test_parse_value_with_backslashes();
|
||||||
|
@ -253,6 +285,7 @@ int main(int argc, char **argv) {
|
||||||
test_parse_value_unicode();
|
test_parse_value_unicode();
|
||||||
|
|
||||||
test_udev_replace_whitespace();
|
test_udev_replace_whitespace();
|
||||||
|
test_udev_resolve_subsys_kernel();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,7 +346,7 @@ static ssize_t udev_event_subst_format(
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* try to read the value specified by "[dmi/id]product_name" */
|
/* 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;
|
val = vbuf;
|
||||||
|
|
||||||
/* try to read the attribute the device */
|
/* try to read the attribute the device */
|
||||||
|
|
|
@ -76,7 +76,7 @@ typedef enum {
|
||||||
TK_M_TAG, /* strv, sd_device_get_tag_first(), sd_device_get_tag_next() */
|
TK_M_TAG, /* strv, sd_device_get_tag_first(), sd_device_get_tag_next() */
|
||||||
TK_M_SUBSYSTEM, /* string, sd_device_get_subsystem() */
|
TK_M_SUBSYSTEM, /* string, sd_device_get_subsystem() */
|
||||||
TK_M_DRIVER, /* string, sd_device_get_driver() */
|
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 */
|
TK_M_SYSCTL, /* string, takes kernel parameter through attribute */
|
||||||
|
|
||||||
/* matches parent parameters */
|
/* matches parent parameters */
|
||||||
|
@ -1396,7 +1396,7 @@ static bool token_match_attr(UdevRuleToken *token, sd_device *dev, UdevEvent *ev
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case SUBST_TYPE_SUBSYS:
|
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;
|
return false;
|
||||||
value = vbuf;
|
value = vbuf;
|
||||||
break;
|
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);
|
(void) udev_event_apply_format(event, token->value, buf, sizeof(buf), false);
|
||||||
if (!path_is_absolute(buf) &&
|
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];
|
char tmp[UTIL_PATH_SIZE];
|
||||||
|
|
||||||
r = sd_device_get_syspath(dev, &val);
|
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;
|
const char *key_name = token->data;
|
||||||
char value[UTIL_NAME_SIZE];
|
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)
|
sd_device_get_syspath(dev, &val) >= 0)
|
||||||
strscpyl(buf, sizeof(buf), val, "/", key_name, NULL);
|
strscpyl(buf, sizeof(buf), val, "/", key_name, NULL);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue