diff --git a/src/libsystemd/sd-device/device-enumerator-private.h b/src/libsystemd/sd-device/device-enumerator-private.h index d74198822c..54fc13c43b 100644 --- a/src/libsystemd/sd-device/device-enumerator-private.h +++ b/src/libsystemd/sd-device/device-enumerator-private.h @@ -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); diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c index df8753dec9..1379764156 100644 --- a/src/libsystemd/sd-device/device-enumerator.c +++ b/src/libsystemd/sd-device/device-enumerator.c @@ -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; diff --git a/src/libudev/libudev-enumerate.c b/src/libudev/libudev-enumerate.c index 2dc695bd03..d71a31c566 100644 --- a/src/libudev/libudev-enumerate.c +++ b/src/libudev/libudev-enumerate.c @@ -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;