#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);
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) {
*enumerator = (sd_device_enumerator) {
.n_ref = 1,
.type = _DEVICE_ENUMERATION_TYPE_INVALID,
+ .match_initialized = MATCH_INITIALIZED_COMPAT,
};
*ret = TAKE_PTR(enumerator);
_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;
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);
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;
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;