From d25d4f189c242ab792439a804a0da47934499dfa Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 25 Apr 2022 11:07:54 +0900 Subject: [PATCH 1/4] set: introduce set_fnmatch() --- src/basic/hashmap.c | 25 ++++++++++++++++++++++++ src/basic/set.h | 2 ++ src/test/test-set.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index 1855367072..e33d6c3073 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #include +#include #include #include #include @@ -2070,3 +2071,27 @@ bool set_equal(Set *a, Set *b) { return true; } + +static bool set_fnmatch_one(Set *patterns, const char *needle) { + const char *p; + + assert(needle); + + SET_FOREACH(p, patterns) + if (fnmatch(p, needle, 0) == 0) + return true; + + return false; +} + +bool set_fnmatch(Set *include_patterns, Set *exclude_patterns, const char *needle) { + assert(needle); + + if (set_fnmatch_one(exclude_patterns, needle)) + return false; + + if (set_isempty(include_patterns)) + return true; + + return set_fnmatch_one(include_patterns, needle); +} diff --git a/src/basic/set.h b/src/basic/set.h index 5cae13160b..243a747e98 100644 --- a/src/basic/set.h +++ b/src/basic/set.h @@ -153,3 +153,5 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free); int set_strjoin(Set *s, const char *separator, bool wrap_with_separator, char **ret); bool set_equal(Set *a, Set *b); + +bool set_fnmatch(Set *include_patterns, Set *exclude_patterns, const char *needle); diff --git a/src/test/test-set.c b/src/test/test-set.c index 4dd98ef4f8..5c5c35f3a2 100644 --- a/src/test/test-set.c +++ b/src/test/test-set.c @@ -330,4 +330,50 @@ TEST(set_equal) { assert_se(set_equal(b, a)); } +TEST(set_fnmatch) { + _cleanup_set_free_ Set *match = NULL, *nomatch = NULL; + + assert_se(set_put_strdup(&match, "aaa") >= 0); + assert_se(set_put_strdup(&match, "bbb*") >= 0); + assert_se(set_put_strdup(&match, "*ccc") >= 0); + + assert_se(set_put_strdup(&nomatch, "a*") >= 0); + assert_se(set_put_strdup(&nomatch, "bbb") >= 0); + assert_se(set_put_strdup(&nomatch, "ccc*") >= 0); + + assert_se(set_fnmatch(NULL, NULL, "")); + assert_se(set_fnmatch(NULL, NULL, "hoge")); + + assert_se(set_fnmatch(match, NULL, "aaa")); + assert_se(set_fnmatch(match, NULL, "bbb")); + assert_se(set_fnmatch(match, NULL, "bbbXXX")); + assert_se(set_fnmatch(match, NULL, "ccc")); + assert_se(set_fnmatch(match, NULL, "XXXccc")); + assert_se(!set_fnmatch(match, NULL, "")); + assert_se(!set_fnmatch(match, NULL, "aaaa")); + assert_se(!set_fnmatch(match, NULL, "XXbbb")); + assert_se(!set_fnmatch(match, NULL, "cccXX")); + + assert_se(set_fnmatch(NULL, nomatch, "")); + assert_se(set_fnmatch(NULL, nomatch, "Xa")); + assert_se(set_fnmatch(NULL, nomatch, "bbbb")); + assert_se(set_fnmatch(NULL, nomatch, "XXXccc")); + assert_se(!set_fnmatch(NULL, nomatch, "a")); + assert_se(!set_fnmatch(NULL, nomatch, "aXXXX")); + assert_se(!set_fnmatch(NULL, nomatch, "bbb")); + assert_se(!set_fnmatch(NULL, nomatch, "ccc")); + assert_se(!set_fnmatch(NULL, nomatch, "cccXXX")); + + assert_se(set_fnmatch(match, nomatch, "bbbbb")); + assert_se(set_fnmatch(match, nomatch, "XXccc")); + assert_se(!set_fnmatch(match, nomatch, "")); + assert_se(!set_fnmatch(match, nomatch, "a")); + assert_se(!set_fnmatch(match, nomatch, "aaa")); + assert_se(!set_fnmatch(match, nomatch, "b")); + assert_se(!set_fnmatch(match, nomatch, "bbb")); + assert_se(!set_fnmatch(match, nomatch, "ccc")); + assert_se(!set_fnmatch(match, nomatch, "ccccc")); + assert_se(!set_fnmatch(match, nomatch, "cccXX")); +} + DEFINE_TEST_MAIN(LOG_INFO); From c11810ed30bdcc5277592eb1ecee36457e11bac9 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 25 Apr 2022 11:19:56 +0900 Subject: [PATCH 2/4] sd-device-enumerator: use set_fnmatch() --- src/libsystemd/sd-device/device-enumerator.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c index 757f748927..977f4ef24a 100644 --- a/src/libsystemd/sd-device/device-enumerator.c +++ b/src/libsystemd/sd-device/device-enumerator.c @@ -580,25 +580,12 @@ static int test_matches( } 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; + return set_fnmatch(enumerator->match_subsystem, enumerator->nomatch_subsystem, subsystem); } static int enumerator_add_parent_devices( From 9409710097b56d42bcbd2e373bc368d0e2622079 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 25 Apr 2022 11:20:11 +0900 Subject: [PATCH 3/4] sd-device-enumerator: introduce sd_device_enumerator_add_nomatch_sysname() --- src/libsystemd/libsystemd.sym | 1 + .../sd-device/device-enumerator-private.h | 2 ++ src/libsystemd/sd-device/device-enumerator.c | 25 ++++++++++--------- src/systemd/sd-device.h | 1 + 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index bdf76b467b..ccc321ec33 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -776,4 +776,5 @@ global: sd_device_new_from_devname; sd_device_new_from_path; sd_device_open; + sd_device_enumerator_add_nomatch_sysname; } LIBSYSTEMD_250; diff --git a/src/libsystemd/sd-device/device-enumerator-private.h b/src/libsystemd/sd-device/device-enumerator-private.h index 5aaa384095..cf62fabdad 100644 --- a/src/libsystemd/sd-device/device-enumerator-private.h +++ b/src/libsystemd/sd-device/device-enumerator-private.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include + #include "sd-device.h" typedef enum MatchInitializedType { diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c index 977f4ef24a..3af9e36a5a 100644 --- a/src/libsystemd/sd-device/device-enumerator.c +++ b/src/libsystemd/sd-device/device-enumerator.c @@ -42,6 +42,7 @@ struct sd_device_enumerator { Hashmap *nomatch_sysattr; Hashmap *match_property; Set *match_sysname; + Set *nomatch_sysname; Set *match_tag; Set *match_parent; MatchInitializedType match_initialized; @@ -96,6 +97,7 @@ static sd_device_enumerator *device_enumerator_free(sd_device_enumerator *enumer hashmap_free(enumerator->nomatch_sysattr); hashmap_free(enumerator->match_property); set_free(enumerator->match_sysname); + set_free(enumerator->nomatch_sysname); set_free(enumerator->match_tag); set_free(enumerator->match_parent); @@ -183,13 +185,13 @@ _public_ int sd_device_enumerator_add_match_property(sd_device_enumerator *enume return 1; } -_public_ int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname) { +static int device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname, bool match) { int r; assert_return(enumerator, -EINVAL); assert_return(sysname, -EINVAL); - r = set_put_strdup(&enumerator->match_sysname, sysname); + r = set_put_strdup(match ? &enumerator->match_sysname : &enumerator->nomatch_sysname, sysname); if (r <= 0) return r; @@ -198,6 +200,14 @@ _public_ int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumer return 1; } +_public_ int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname) { + return device_enumerator_add_match_sysname(enumerator, sysname, true); +} + +_public_ int sd_device_enumerator_add_nomatch_sysname(sd_device_enumerator *enumerator, const char *sysname) { + return device_enumerator_add_match_sysname(enumerator, sysname, false); +} + _public_ int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const char *tag) { int r; @@ -500,19 +510,10 @@ static bool match_tag(sd_device_enumerator *enumerator, sd_device *device) { } static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname) { - const char *sysname_match; - assert(enumerator); assert(sysname); - if (set_isempty(enumerator->match_sysname)) - return true; - - SET_FOREACH(sysname_match, enumerator->match_sysname) - if (fnmatch(sysname_match, sysname, 0) == 0) - return true; - - return false; + return set_fnmatch(enumerator->match_sysname, enumerator->nomatch_sysname, sysname); } static int match_initialized(sd_device_enumerator *enumerator, sd_device *device) { diff --git a/src/systemd/sd-device.h b/src/systemd/sd-device.h index f0c3c115e4..2d12288864 100644 --- a/src/systemd/sd-device.h +++ b/src/systemd/sd-device.h @@ -126,6 +126,7 @@ int sd_device_enumerator_add_match_subsystem(sd_device_enumerator *enumerator, c 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_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); int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumerator, sd_device *parent); int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator); From ff56124b119ebc7734c479887f71c0a6f2574b09 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 19 Apr 2022 21:16:53 +0900 Subject: [PATCH 4/4] test: exclude "bdi" subsystem and loop block devices On several CI environments, it seems that some loop block devices and corresponding bdi devices are sometimes removed during the test is running. Let's exclude them. Fixes #22970. --- src/libsystemd/sd-device/test-sd-device.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libsystemd/sd-device/test-sd-device.c b/src/libsystemd/sd-device/test-sd-device.c index 7bc6135406..3bd3761f3b 100644 --- a/src/libsystemd/sd-device/test-sd-device.c +++ b/src/libsystemd/sd-device/test-sd-device.c @@ -182,6 +182,10 @@ TEST(sd_device_enumerator_devices) { assert_se(sd_device_enumerator_new(&e) >= 0); assert_se(sd_device_enumerator_allow_uninitialized(e) >= 0); + /* On some CI environments, it seems some loop block devices and corresponding bdi devices sometimes + * disappear during running this test. Let's exclude them here for stability. */ + assert_se(sd_device_enumerator_add_match_subsystem(e, "bdi", false) >= 0); + assert_se(sd_device_enumerator_add_nomatch_sysname(e, "loop*") >= 0); FOREACH_DEVICE(e, d) test_sd_device_one(d); } @@ -208,6 +212,8 @@ static void test_sd_device_enumerator_filter_subsystem_one( assert_se(sd_device_enumerator_new(&e) >= 0); assert_se(sd_device_enumerator_add_match_subsystem(e, subsystem, true) >= 0); + if (streq(subsystem, "block")) + assert_se(sd_device_enumerator_add_nomatch_sysname(e, "loop*") >= 0); FOREACH_DEVICE(e, d) { const char *syspath; @@ -250,6 +256,9 @@ TEST(sd_device_enumerator_filter_subsystem) { assert_se(subsystems = hashmap_new(&string_hash_ops)); assert_se(sd_device_enumerator_new(&e) >= 0); + /* See comments in TEST(sd_device_enumerator_devices). */ + assert_se(sd_device_enumerator_add_match_subsystem(e, "bdi", false) >= 0); + assert_se(sd_device_enumerator_add_nomatch_sysname(e, "loop*") >= 0); FOREACH_DEVICE(e, d) { const char *syspath, *subsystem;