]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-device-enumerator: support to list only initialized or uninitialized devices
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 8 Mar 2022 04:58:02 +0000 (13:58 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 22 Mar 2022 06:27:06 +0000 (15:27 +0900)
src/libsystemd/sd-device/device-enumerator-private.h
src/libsystemd/sd-device/device-enumerator.c
src/libudev/libudev-enumerate.c

index d74198822ca35c51488fd694594a53da5f80d62b..54fc13c43b220d408cd12638427b414936d50418 100644 (file)
@@ -3,11 +3,20 @@
 
 #include "sd-device.h"
 
+typedef enum MatchInitializedType {
+        MATCH_INITIALIZED_NO,     /* only devices without a db entry */
+        MATCH_INITIALIZED_YES,    /* only devices with a db entry */
+        MATCH_INITIALIZED_ALL,    /* all devices */
+        MATCH_INITIALIZED_COMPAT, /* only devices that have no devnode/ifindex or have a db entry */
+        _MATCH_INITIALIZED_MAX,
+        _MATCH_INITIALIZED_INVALID = -EINVAL,
+} MatchInitializedType;
+
 int device_enumerator_scan_devices(sd_device_enumerator *enumeartor);
 int device_enumerator_scan_subsystems(sd_device_enumerator *enumeartor);
 int device_enumerator_scan_devices_and_subsystems(sd_device_enumerator *enumerator);
 int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device);
-int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator);
+int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator, MatchInitializedType type);
 int device_enumerator_add_match_parent_incremental(sd_device_enumerator *enumerator, sd_device *parent);
 int device_enumerator_add_prioritized_subsystem(sd_device_enumerator *enumerator, const char *subsystem);
 sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator);
index df8753dec9b43fb1ba7defd29991b5438d5822d1..1379764156ee73f84959654a048d9122e1d1aed8 100644 (file)
@@ -44,7 +44,7 @@ struct sd_device_enumerator {
         Set *match_sysname;
         Set *match_tag;
         Set *match_parent;
-        bool match_allow_uninitialized;
+        MatchInitializedType match_initialized;
 };
 
 _public_ int sd_device_enumerator_new(sd_device_enumerator **ret) {
@@ -59,6 +59,7 @@ _public_ int sd_device_enumerator_new(sd_device_enumerator **ret) {
         *enumerator = (sd_device_enumerator) {
                 .n_ref = 1,
                 .type = _DEVICE_ENUMERATION_TYPE_INVALID,
+                .match_initialized = MATCH_INITIALIZED_COMPAT,
         };
 
         *ret = TAKE_PTR(enumerator);
@@ -244,17 +245,18 @@ _public_ int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumera
 _public_ int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator) {
         assert_return(enumerator, -EINVAL);
 
-        enumerator->match_allow_uninitialized = true;
+        enumerator->match_initialized = MATCH_INITIALIZED_ALL;
 
         enumerator->scan_uptodate = false;
 
         return 1;
 }
 
-int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator) {
+int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator, MatchInitializedType type) {
         assert_return(enumerator, -EINVAL);
+        assert_return(type >= 0 && type < _MATCH_INITIALIZED_MAX, -EINVAL);
 
-        enumerator->match_allow_uninitialized = false;
+        enumerator->match_initialized = type;
 
         enumerator->scan_uptodate = false;
 
@@ -513,10 +515,42 @@ static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname)
         return false;
 }
 
+static int match_initialized(sd_device_enumerator *enumerator, sd_device *device) {
+        int r;
+
+        assert(enumerator);
+        assert(device);
+
+        if (enumerator->match_initialized == MATCH_INITIALIZED_ALL)
+                return true;
+
+        r = sd_device_get_is_initialized(device);
+        if (r == -ENOENT) /* this is necessarily racey, so ignore missing devices */
+                return false;
+        if (r < 0)
+                return r;
+
+        if (enumerator->match_initialized == MATCH_INITIALIZED_COMPAT) {
+                /* only devices that have no devnode/ifindex or have a db entry are accepted. */
+                if (r > 0)
+                        return true;
+
+                if (sd_device_get_devnum(device, NULL) >= 0)
+                        return true;
+
+                if (sd_device_get_ifindex(device, NULL) >= 0)
+                        return true;
+
+                return false;
+        }
+
+        return (enumerator->match_initialized == MATCH_INITIALIZED_NO) == (r == 0);
+}
+
 static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator, const char *basedir, const char *subdir1, const char *subdir2) {
         _cleanup_closedir_ DIR *dir = NULL;
         char *path;
-        int r = 0;
+        int k, r = 0;
 
         assert(enumerator);
         assert(basedir);
@@ -537,7 +571,6 @@ static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator,
         FOREACH_DIRENT_ALL(de, dir, return -errno) {
                 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
                 char syspath[strlen(path) + 1 + strlen(de->d_name) + 1];
-                int initialized, k;
 
                 if (de->d_name[0] == '.')
                         continue;
@@ -556,31 +589,13 @@ static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator,
                         continue;
                 }
 
-                initialized = sd_device_get_is_initialized(device);
-                if (initialized < 0) {
-                        if (initialized != -ENOENT)
-                                /* this is necessarily racey, so ignore missing devices */
-                                r = initialized;
-
+                k = match_initialized(enumerator, device);
+                if (k <= 0) {
+                        if (k < 0)
+                                r = k;
                         continue;
                 }
 
-                /*
-                 * All devices with a device node or network interfaces
-                 * possibly need udev to adjust the device node permission
-                 * or context, or rename the interface before it can be
-                 * reliably used from other processes.
-                 *
-                 * For now, we can only check these types of devices, we
-                 * might not store a database, and have no way to find out
-                 * for all other types of devices.
-                 */
-                if (!enumerator->match_allow_uninitialized &&
-                    !initialized &&
-                    (sd_device_get_devnum(device, NULL) >= 0 ||
-                     sd_device_get_ifindex(device, NULL) >= 0))
-                        continue;
-
                 if (!device_match_parent(device, enumerator->match_parent, NULL))
                         continue;
 
index 2dc695bd03f9813c0b4b3d7e61525cc04b20fd05..d71a31c566a75397c004f44224c5e0a1819e8525 100644 (file)
@@ -365,7 +365,7 @@ _public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev
 
         assert_return(udev_enumerate, -EINVAL);
 
-        r = device_enumerator_add_match_is_initialized(udev_enumerate->enumerator);
+        r = device_enumerator_add_match_is_initialized(udev_enumerate->enumerator, MATCH_INITIALIZED_COMPAT);
         if (r < 0)
                 return r;