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:
@@ -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;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user