Hashmap *match_sysattr;
Hashmap *nomatch_sysattr;
Hashmap *match_property;
+ Hashmap *match_property_required;
Set *match_sysname;
Set *nomatch_sysname;
Set *match_tag;
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);
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;
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) {
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))
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;
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);