1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-26 03:22:00 +03:00

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
This commit is contained in:
Daan De Meyer 2023-10-09 16:06:50 +02:00
parent 9f3ed6fd19
commit fe2a6dce6c
4 changed files with 66 additions and 8 deletions

View File

@ -832,4 +832,5 @@ global:
LIBSYSTEMD_255 {
global:
sd_id128_get_app_specific;
sd_device_enumerator_add_match_property_required;
} LIBSYSTEMD_254;

View File

@ -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))

View File

@ -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;

View File

@ -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);