From: Daan De Meyer Date: Mon, 9 Oct 2023 14:06:50 +0000 (+0200) Subject: sd-device: Support matching all properties X-Git-Tag: v255-rc1~270 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fe2a6dce6ced9ed57b1790ad21526e1214fa2998;p=thirdparty%2Fsystemd.git sd-device: Support matching all properties Let's support enumerating over devices that match all of the given properties instead of any of the given properties by adding a new function sd_device_enumerator_add_match_property_required() which specifies properties that should all be matched instead of just one. Fixes #28372 --- diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 56a8831f0fe..4113920ee04 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -832,4 +832,5 @@ global: LIBSYSTEMD_255 { global: sd_id128_get_app_specific; + sd_device_enumerator_add_match_property_required; } LIBSYSTEMD_254; diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c index 766fadd22c5..15c5c42ade7 100644 --- a/src/libsystemd/sd-device/device-enumerator.c +++ b/src/libsystemd/sd-device/device-enumerator.c @@ -40,6 +40,7 @@ struct sd_device_enumerator { Hashmap *match_sysattr; Hashmap *nomatch_sysattr; Hashmap *match_property; + Hashmap *match_property_required; Set *match_sysname; Set *nomatch_sysname; Set *match_tag; @@ -95,6 +96,7 @@ static sd_device_enumerator *device_enumerator_free(sd_device_enumerator *enumer hashmap_free(enumerator->match_sysattr); hashmap_free(enumerator->nomatch_sysattr); hashmap_free(enumerator->match_property); + hashmap_free(enumerator->match_property_required); set_free(enumerator->match_sysname); set_free(enumerator->nomatch_sysname); set_free(enumerator->match_tag); @@ -180,6 +182,21 @@ _public_ int sd_device_enumerator_add_match_property(sd_device_enumerator *enume return 1; } +_public_ int sd_device_enumerator_add_match_property_required(sd_device_enumerator *enumerator, const char *property, const char *value) { + int r; + + assert_return(enumerator, -EINVAL); + assert_return(property, -EINVAL); + + r = update_match_strv(&enumerator->match_property_required, property, value, /* clear_on_null = */ false); + if (r <= 0) + return r; + + enumerator->scan_uptodate = false; + + return 1; +} + static int device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname, bool match) { int r; @@ -459,28 +476,38 @@ int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *de return 1; } -static bool match_property(sd_device_enumerator *enumerator, sd_device *device) { +static bool match_property(Hashmap *properties, sd_device *device, bool match_all) { const char *property_pattern; char * const *value_patterns; - assert(enumerator); assert(device); /* Unlike device_match_sysattr(), this accepts device that has at least one matching property. */ - if (hashmap_isempty(enumerator->match_property)) + if (hashmap_isempty(properties)) return true; - HASHMAP_FOREACH_KEY(value_patterns, property_pattern, enumerator->match_property) + HASHMAP_FOREACH_KEY(value_patterns, property_pattern, properties) { + bool match = false; + FOREACH_DEVICE_PROPERTY(device, property, value) { if (fnmatch(property_pattern, property, 0) != 0) continue; - if (strv_fnmatch(value_patterns, value)) - return true; + match = strv_fnmatch(value_patterns, value); + if (match) { + if (!match_all) + return true; + + break; + } } - return false; + if (!match && match_all) + return false; + } + + return match_all; } static bool match_tag(sd_device_enumerator *enumerator, sd_device *device) { @@ -599,7 +626,10 @@ static int test_matches( if (r <= 0) return r; - if (!match_property(enumerator, device)) + if (!match_property(enumerator->match_property, device, /* match_all = */ false)) + return false; + + if (!match_property(enumerator->match_property_required, device, /* match_all = */ true)) return false; if (!device_match_sysattr(device, enumerator->match_sysattr, enumerator->nomatch_sysattr)) diff --git a/src/libsystemd/sd-device/test-sd-device.c b/src/libsystemd/sd-device/test-sd-device.c index 43376a20360..bce99b55186 100644 --- a/src/libsystemd/sd-device/test-sd-device.c +++ b/src/libsystemd/sd-device/test-sd-device.c @@ -399,6 +399,32 @@ TEST(sd_device_enumerator_add_match_property) { assert_se(ifindex == 1); } +TEST(sd_device_enumerator_add_match_property_required) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + sd_device *dev; + int ifindex; + + assert_se(sd_device_enumerator_new(&e) >= 0); + assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0); + assert_se(sd_device_enumerator_add_match_subsystem(e, "net", true) >= 0); + assert_se(sd_device_enumerator_add_match_sysattr(e, "ifindex", "1", true) >= 0); + assert_se(sd_device_enumerator_add_match_property_required(e, "IFINDE*", "1*") >= 0); + + /* Only one required match which should be satisfied. */ + dev = sd_device_enumerator_get_device_first(e); + assert_se(dev); + assert_se(sd_device_get_ifindex(dev, &ifindex) >= 0); + assert_se(ifindex == 1); + + /* Now let's add a bunch of garbage properties which should not be satisfied. */ + assert_se(sd_device_enumerator_add_match_property_required(e, "IFINDE*", "hoge") >= 0); + assert_se(sd_device_enumerator_add_match_property_required(e, "IFINDE*", NULL) >= 0); + assert_se(sd_device_enumerator_add_match_property_required(e, "AAAAA", "BBBB") >= 0); + assert_se(sd_device_enumerator_add_match_property_required(e, "FOOOO", NULL) >= 0); + + assert_se(!sd_device_enumerator_get_device_first(e)); +} + static void check_parent_match(sd_device_enumerator *e, sd_device *dev) { const char *syspath; bool found = false; diff --git a/src/systemd/sd-device.h b/src/systemd/sd-device.h index e3d647f75d1..b67ec0f34dc 100644 --- a/src/systemd/sd-device.h +++ b/src/systemd/sd-device.h @@ -129,6 +129,7 @@ sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator *enumera int sd_device_enumerator_add_match_subsystem(sd_device_enumerator *enumerator, const char *subsystem, int match); int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumerator, const char *sysattr, const char *value, int match); int sd_device_enumerator_add_match_property(sd_device_enumerator *enumerator, const char *property, const char *value); +int sd_device_enumerator_add_match_property_required(sd_device_enumerator *enumerator, const char *property, const char *value); int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname); int sd_device_enumerator_add_nomatch_sysname(sd_device_enumerator *enumerator, const char *sysname); int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const char *tag);