sd-device-enumerator: support to list only initialized or uninitialized devices

This commit is contained in:
Yu Watanabe 2022-03-08 13:58:02 +09:00
parent 2336bde964
commit d8b50e5df7
3 changed files with 54 additions and 30 deletions

View 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);

View 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;

View 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;