diff options
author | Lennart Poettering <lennart@poettering.net> | 2022-04-11 23:13:40 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2022-04-13 14:41:05 +0200 |
commit | 00dfbf35fde43a8106bd0132109ac25ec2033b09 (patch) | |
tree | 7cdc6bc55bdd968c436c1385e523b83953f21658 /src/libsystemd/sd-device | |
parent | 0b859c9773a14f12d512447c27e3caf274456498 (diff) | |
download | systemd-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.c | 83 |
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( |