sd-device-enumerator,monitor: fix sysattr match

Previously, if sd_device_enumerator_add_match_sysattr() is called for
the same sysattr with different values, then no device passed the filter.

Now, the accepted values (or patterns) are stored in strv, and if the
sysattr value of a device matches with the strv, then the device passes
the filter.
This commit is contained in:
Yu Watanabe
2022-08-09 01:17:00 +09:00
parent 52be2b43f5
commit 585f2035b3
4 changed files with 68 additions and 17 deletions
+1 -3
View File
@@ -157,9 +157,7 @@ _public_ int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumer
else
hashmap = &enumerator->nomatch_sysattr;
/* Do not use string_has_ops_free_free or hashmap_put_strdup() here, as this may be called
* multiple times with the same sysattr but different value. */
r = hashmap_put_strdup_full(hashmap, &trivial_hash_ops_free_free, sysattr, value);
r = update_match_strv(hashmap, sysattr, value);
if (r <= 0)
return r;
+1 -1
View File
@@ -787,7 +787,7 @@ _public_ int sd_device_monitor_filter_add_match_sysattr(sd_device_monitor *m, co
hashmap = &m->nomatch_sysattr_filter;
/* TODO: unset m->filter_uptodate on success when we support this filter on BPF. */
return hashmap_put_strdup_full(hashmap, &trivial_hash_ops_free_free, sysattr, value);
return update_match_strv(hashmap, sysattr, value);
}
_public_ int sd_device_monitor_filter_add_match_parent(sd_device_monitor *m, sd_device *device, int match) {
+65 -13
View File
@@ -5,7 +5,65 @@
#include "device-util.h"
#include "path-util.h"
static bool device_match_sysattr_value(sd_device *device, const char *sysattr, const char *match_value) {
int update_match_strv(Hashmap **match_strv, const char *key, const char *value) {
char **strv;
int r;
assert(match_strv);
assert(key);
strv = hashmap_get(*match_strv, key);
if (strv) {
if (!value) {
char **v;
if (strv_isempty(strv))
return 0;
/* Accept all value. Clear previous assignment. */
v = new0(char*, 1);
if (!v)
return -ENOMEM;
strv_free_and_replace(strv, v);
} else {
if (strv_contains(strv, value))
return 0;
r = strv_extend(&strv, value);
if (r < 0)
return r;
}
r = hashmap_update(*match_strv, key, strv);
if (r < 0)
return r;
} else {
_cleanup_strv_free_ char **strv_alloc = NULL;
_cleanup_free_ char *key_alloc = NULL;
key_alloc = strdup(key);
if (!key_alloc)
return -ENOMEM;
strv_alloc = strv_new(value);
if (!strv_alloc)
return -ENOMEM;
r = hashmap_ensure_put(match_strv, &string_hash_ops_free_strv_free, key_alloc, strv_alloc);
if (r < 0)
return r;
TAKE_PTR(key_alloc);
TAKE_PTR(strv_alloc);
}
return 1;
}
static bool device_match_sysattr_value(sd_device *device, const char *sysattr, char * const *patterns) {
const char *value;
assert(device);
@@ -14,27 +72,21 @@ static bool device_match_sysattr_value(sd_device *device, const char *sysattr, c
if (sd_device_get_sysattr_value(device, sysattr, &value) < 0)
return false;
if (!match_value)
return true;
if (fnmatch(match_value, value, 0) == 0)
return true;
return false;
return strv_fnmatch_or_empty(patterns, value, 0);
}
bool device_match_sysattr(sd_device *device, Hashmap *match_sysattr, Hashmap *nomatch_sysattr) {
char * const *patterns;
const char *sysattr;
const char *value;
assert(device);
HASHMAP_FOREACH_KEY(value, sysattr, match_sysattr)
if (!device_match_sysattr_value(device, sysattr, value))
HASHMAP_FOREACH_KEY(patterns, sysattr, match_sysattr)
if (!device_match_sysattr_value(device, sysattr, patterns))
return false;
HASHMAP_FOREACH_KEY(value, sysattr, nomatch_sysattr)
if (device_match_sysattr_value(device, sysattr, value))
HASHMAP_FOREACH_KEY(patterns, sysattr, nomatch_sysattr)
if (device_match_sysattr_value(device, sysattr, patterns))
return false;
return true;
+1
View File
@@ -82,5 +82,6 @@
#define log_device_warning_errno(device, error, ...) log_device_full_errno(device, LOG_WARNING, error, __VA_ARGS__)
#define log_device_error_errno(device, error, ...) log_device_full_errno(device, LOG_ERR, error, __VA_ARGS__)
int update_match_strv(Hashmap **match_strv, const char *key, const char *value);
bool device_match_sysattr(sd_device *device, Hashmap *match_sysattr, Hashmap *nomatch_sysattr);
bool device_match_parent(sd_device *device, Set *match_parent, Set *nomatch_parent);