}
int device_read_uevent_file(sd_device *device) {
- _cleanup_free_ char *uevent = NULL;
- const char *syspath, *key = NULL, *value = NULL, *major = NULL, *minor = NULL;
- char *path;
- size_t uevent_len;
int r;
- enum {
- PRE_KEY,
- KEY,
- PRE_VALUE,
- VALUE,
- INVALID_LINE,
- } state = PRE_KEY;
-
assert(device);
if (device->uevent_loaded || device->sealed)
return 0;
- r = sd_device_get_syspath(device, &syspath);
- if (r < 0)
- return r;
-
device->uevent_loaded = true;
- path = strjoina(syspath, "/uevent");
-
- r = read_full_virtual_file(path, &uevent, &uevent_len);
- if (r == -EACCES || ERRNO_IS_NEG_DEVICE_ABSENT(r))
+ const char *uevent;
+ r = sd_device_get_sysattr_value(device, "uevent", &uevent);
+ if (ERRNO_IS_NEG_PRIVILEGE(r) || ERRNO_IS_NEG_DEVICE_ABSENT(r))
/* The uevent files may be write-only, the device may be already removed, or the device
* may not have the uevent file. */
return 0;
if (r < 0)
- return log_device_debug_errno(device, r, "sd-device: Failed to read uevent file '%s': %m", path);
-
- for (size_t i = 0; i < uevent_len; i++)
- switch (state) {
- case PRE_KEY:
- if (!strchr(NEWLINE, uevent[i])) {
- key = &uevent[i];
-
- state = KEY;
- }
-
- break;
- case KEY:
- if (uevent[i] == '=') {
- uevent[i] = '\0';
+ return log_device_debug_errno(device, r, "sd-device: Failed to read uevent file: %m");
- state = PRE_VALUE;
- } else if (strchr(NEWLINE, uevent[i])) {
- uevent[i] = '\0';
- log_device_debug(device, "sd-device: Invalid uevent line '%s', ignoring", key);
-
- state = PRE_KEY;
- }
-
- break;
- case PRE_VALUE:
- value = &uevent[i];
- state = VALUE;
-
- _fallthrough_; /* to handle empty property */
- case VALUE:
- if (strchr(NEWLINE, uevent[i])) {
- uevent[i] = '\0';
+ _cleanup_strv_free_ char **v = NULL;
+ r = strv_split_newlines_full(&v, uevent, EXTRACT_RETAIN_ESCAPE);
+ if (r < 0)
+ return log_device_debug_errno(device, r, "sd-device: Failed to parse uevent file: %m");
- r = handle_uevent_line(device, key, value, &major, &minor);
- if (r < 0)
- log_device_debug_errno(device, r, "sd-device: Failed to handle uevent entry '%s=%s', ignoring: %m", key, value);
+ const char *major = NULL, *minor = NULL;
+ STRV_FOREACH(s, v) {
+ char *eq = strchr(*s, '=');
+ if (!eq) {
+ log_device_debug(device, "sd-device: Invalid uevent line, ignoring: %s", *s);
+ continue;
+ }
- state = PRE_KEY;
- }
+ *eq = '\0';
- break;
- default:
- assert_not_reached();
- }
+ r = handle_uevent_line(device, *s, eq + 1, &major, &minor);
+ if (r < 0)
+ log_device_debug_errno(device, r,
+ "sd-device: Failed to handle uevent entry '%s=%s', ignoring: %m",
+ *s, eq + 1);
+ }
if (major) {
r = device_set_devnum(device, major, minor);
if (r < 0)
- log_device_debug_errno(device, r, "sd-device: Failed to set 'MAJOR=%s' or 'MINOR=%s' from '%s', ignoring: %m", major, strna(minor), path);
+ log_device_debug_errno(device, r,
+ "sd-device: Failed to set 'MAJOR=%s' and/or 'MINOR=%s' from uevent, ignoring: %m",
+ major, strna(minor));
}
return 0;