From fcc53527159bc628628163ebedad6e991260120a Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Wed, 18 Jun 2025 09:26:52 +0200 Subject: [PATCH] Revert "sd-device: use sd_device_get_sysattr_value() to read uevent file" Revert systemd commit 17dc9ec4b6e8 ("sd-device: use sd_device_get_sysattr_value() to read uevent file"). In the NM codebase sd_device_get_sysattr_value() is currently commented out because it depends on file chase.c which is not imported. Importing that file would require another long chain of imports. Therefore, revert the commit. This reverts commit 17dc9ec4b6e82fc2a4f9809011e154f538eb8b9c. Fixes: 6a4e6fab403b ('merge: branch 'systemd' into jv/systemd-merge') --- .../src/libsystemd/sd-device/sd-device.c | 89 +++++++++++++------ 1 file changed, 63 insertions(+), 26 deletions(-) diff --git a/src/libnm-systemd-core/src/libsystemd/sd-device/sd-device.c b/src/libnm-systemd-core/src/libsystemd/sd-device/sd-device.c index 13368493d7..43c601fcaa 100644 --- a/src/libnm-systemd-core/src/libsystemd/sd-device/sd-device.c +++ b/src/libnm-systemd-core/src/libsystemd/sd-device/sd-device.c @@ -805,52 +805,89 @@ static int handle_uevent_line( } 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; - const char *uevent; - r = sd_device_get_sysattr_value(device, "uevent", &uevent); - if (ERRNO_IS_NEG_PRIVILEGE(r) || ERRNO_IS_NEG_DEVICE_ABSENT(r)) + path = strjoina(syspath, "/uevent"); + + r = read_full_virtual_file(path, &uevent, &uevent_len); + if (r == -EACCES || 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: %m"); + return log_device_debug_errno(device, r, "sd-device: Failed to read uevent file '%s': %m", path); - _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"); + for (size_t i = 0; i < uevent_len; i++) + switch (state) { + case PRE_KEY: + if (!strchr(NEWLINE, uevent[i])) { + key = &uevent[i]; - 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 = KEY; + } + + break; + case KEY: + if (uevent[i] == '=') { + uevent[i] = '\0'; + + 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'; + + 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); + + state = PRE_KEY; + } + + break; + default: + assert_not_reached(); } - *eq = '\0'; - - 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' and/or 'MINOR=%s' from uevent, ignoring: %m", - major, strna(minor)); + log_device_debug_errno(device, r, "sd-device: Failed to set 'MAJOR=%s' or 'MINOR=%s' from '%s', ignoring: %m", major, strna(minor), path); } if (device_in_subsystem(device, "drivers")) {