]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-device-enumerator,monitor: fix sysattr match
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 8 Aug 2022 13:03:35 +0000 (22:03 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 8 Aug 2022 16:17:00 +0000 (01:17 +0900)
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.

src/libsystemd/sd-device/device-enumerator.c
src/libsystemd/sd-device/device-monitor.c
src/libsystemd/sd-device/device-util.c
src/libsystemd/sd-device/device-util.h

index 39f769c35cf65bd240363219a1f069b9916dd8fa..1f18b843f21753b4489798afaa6b8efdb6b1bbbf 100644 (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;
 
index e8913c3d1f8a3c3433d8bfdf384b78f76949f891..98163058be5d6c2aeed72a27d7e4ec8e8f86ae5a 100644 (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) {
index 616c16c1fc4f47e87aada43e151200b28639ed4c..e2209a0b60956eeb92fd4d827e3298e96684ff04 100644 (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;
index 4eda2abaf366c7b67144393b16680188db22a0e1..6dae8ef6f2f2b7dbea353828757e6921964e0aa0 100644 (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);