summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-device
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2022-04-11 23:13:40 +0200
committerLennart Poettering <lennart@poettering.net>2022-04-13 14:41:05 +0200
commit00dfbf35fde43a8106bd0132109ac25ec2033b09 (patch)
tree7cdc6bc55bdd968c436c1385e523b83953f21658 /src/libsystemd/sd-device
parent0b859c9773a14f12d512447c27e3caf274456498 (diff)
downloadsystemd-00dfbf35fde43a8106bd0132109ac25ec2033b09.tar.gz
sd-device: include parent devices in enumeration
Diffstat (limited to 'src/libsystemd/sd-device')
-rw-r--r--src/libsystemd/sd-device/device-enumerator.c83
1 files changed, 66 insertions, 17 deletions
diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c
index 9345cbea6c..97f4ee356c 100644
--- a/src/libsystemd/sd-device/device-enumerator.c
+++ b/src/libsystemd/sd-device/device-enumerator.c
@@ -577,6 +577,28 @@ static int test_matches(
return true;
}
+static bool match_subsystem(sd_device_enumerator *enumerator, const char *subsystem) {
+ const char *subsystem_match;
+
+ assert(enumerator);
+
+ if (!subsystem)
+ return false;
+
+ SET_FOREACH(subsystem_match, enumerator->nomatch_subsystem)
+ if (fnmatch(subsystem_match, subsystem, 0) == 0)
+ return false;
+
+ if (set_isempty(enumerator->match_subsystem))
+ return true;
+
+ SET_FOREACH(subsystem_match, enumerator->match_subsystem)
+ if (fnmatch(subsystem_match, subsystem, 0) == 0)
+ return true;
+
+ return false;
+}
+
static bool relevant_sysfs_subdir(const struct dirent *de) {
assert(de);
@@ -617,6 +639,7 @@ static int enumerator_scan_dir_and_add_devices(
FOREACH_DIRENT_ALL(de, dir, return -errno) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
char syspath[strlen(path) + 1 + strlen(de->d_name) + 1];
+ sd_device *upwards;
if (!relevant_sysfs_subdir(de))
continue;
@@ -645,31 +668,57 @@ static int enumerator_scan_dir_and_add_devices(
k = device_enumerator_add_device(enumerator, device);
if (k < 0)
r = k;
- }
- return r;
-}
+ /* Also include all potentially matching parent devices in the enumeration. These are things
+ * like root busses — e.g. /sys/devices/pci0000:00/ or /sys/devices/pnp0/, which ar not
+ * linked from /sys/class/ or /sys/bus/, hence pick them up explicitly here. */
+ upwards = device;
+ for (;;) {
+ const char *ss, *usn;
-static bool match_subsystem(sd_device_enumerator *enumerator, const char *subsystem) {
- const char *subsystem_match;
+ k = sd_device_get_parent(upwards, &upwards);
+ if (k == -ENOENT) /* Reached the top? */
+ break;
+ if (k < 0) {
+ r = k;
+ break;
+ }
- assert(enumerator);
+ k = sd_device_get_subsystem(upwards, &ss);
+ if (k == -ENOENT) /* Has no subsystem? */
+ continue;
+ if (k < 0) {
+ r = k;
+ break;
+ }
- if (!subsystem)
- return false;
+ if (!match_subsystem(enumerator, ss))
+ continue;
- SET_FOREACH(subsystem_match, enumerator->nomatch_subsystem)
- if (fnmatch(subsystem_match, subsystem, 0) == 0)
- return false;
+ k = sd_device_get_sysname(upwards, &usn);
+ if (k < 0) {
+ r = k;
+ break;
+ }
- if (set_isempty(enumerator->match_subsystem))
- return true;
+ if (!match_sysname(enumerator, usn))
+ continue;
- SET_FOREACH(subsystem_match, enumerator->match_subsystem)
- if (fnmatch(subsystem_match, subsystem, 0) == 0)
- return true;
+ k = test_matches(enumerator, upwards);
+ if (k < 0)
+ break;
+ if (k == 0)
+ continue;
- return false;
+ k = device_enumerator_add_device(enumerator, upwards);
+ if (k < 0)
+ r = k;
+ else if (k == 0) /* Exists already? Then no need to go further up. */
+ break;
+ }
+ }
+
+ return r;
}
static int enumerator_scan_dir(