* 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
#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);
#include "signal-util.h"
#include "string-table.h"
#include "string-util.h"
+#include "strxcpyx.h"
#include "udev-util.h"
#include "utf8.h"
}
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;
+}
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);
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;
if (arg_monitor)
test_monitor(udev);
- test_util_resolve_subsys_kernel();
-
test_list();
return 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) {
test_parse_value();
test_parse_value_with_backslashes();
test_parse_value_unicode();
test_udev_replace_whitespace();
+ test_udev_resolve_subsys_kernel();
return EXIT_SUCCESS;
}
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 */
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 */
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;
(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);
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);