return (enumerator->match_initialized == MATCH_INITIALIZED_NO) == (r == 0);
}
+static bool match_subsystem(sd_device_enumerator *enumerator, const char *subsystem) {
+ assert(enumerator);
+
+ if (!subsystem)
+ return false;
+
+ return set_fnmatch(enumerator->match_subsystem, enumerator->nomatch_subsystem, subsystem);
+}
+
+typedef enum MatchFlag {
+ MATCH_SYSNAME = 1u << 0,
+ MATCH_SUBSYSTEM = 1u << 1,
+ MATCH_PARENT = 1u << 2,
+ MATCH_TAG = 1u << 3,
+
+ MATCH_ALL = (1u << 4) - 1,
+} MatchFlag;
+
static int test_matches(
sd_device_enumerator *enumerator,
sd_device *device,
- bool ignore_parent_match) {
+ MatchFlag flags) {
int r;
assert(enumerator);
assert(device);
- /* Checks all matches, except for the sysname match (which the caller should check beforehand) */
+ if (FLAGS_SET(flags, MATCH_SYSNAME)) {
+ const char *sysname;
- r = match_initialized(enumerator, device);
- if (r <= 0)
- return r;
+ r = sd_device_get_sysname(device, &sysname);
+ if (r < 0)
+ return r;
+
+ if (!match_sysname(enumerator, sysname))
+ return false;
+ }
- if (!ignore_parent_match &&
+ if (FLAGS_SET(flags, MATCH_SUBSYSTEM)) {
+ const char *subsystem;
+
+ r = sd_device_get_subsystem(device, &subsystem);
+ if (r == -ENOENT)
+ return false;
+ if (r < 0)
+ return r;
+
+ if (!match_subsystem(enumerator, subsystem))
+ return false;
+ }
+
+ if (FLAGS_SET(flags, MATCH_PARENT) &&
!device_match_parent(device, enumerator->match_parent, NULL))
return false;
- if (!match_tag(enumerator, device))
+ if (FLAGS_SET(flags, MATCH_TAG) &&
+ !match_tag(enumerator, device))
return false;
+ r = match_initialized(enumerator, device);
+ if (r <= 0)
+ return r;
+
if (!match_property(enumerator, device))
return false;
return true;
}
-static bool match_subsystem(sd_device_enumerator *enumerator, const char *subsystem) {
- assert(enumerator);
-
- if (!subsystem)
- return false;
-
- return set_fnmatch(enumerator->match_subsystem, enumerator->nomatch_subsystem, subsystem);
-}
-
static int enumerator_add_parent_devices(
sd_device_enumerator *enumerator,
sd_device *device,
- bool ignore_parent_match) {
+ MatchFlag flags) {
int k, r = 0;
assert(device);
for (;;) {
- const char *ss, *usn;
-
k = sd_device_get_parent(device, &device);
if (k == -ENOENT) /* Reached the top? */
break;
break;
}
- k = sd_device_get_subsystem(device, &ss);
- if (k == -ENOENT) /* Has no subsystem? */
- continue;
- if (k < 0) {
- r = k;
- break;
- }
-
- if (!match_subsystem(enumerator, ss))
- continue;
-
- k = sd_device_get_sysname(device, &usn);
- if (k < 0) {
- r = k;
- break;
- }
-
- if (!match_sysname(enumerator, usn))
- continue;
-
- k = test_matches(enumerator, device, ignore_parent_match);
+ k = test_matches(enumerator, device, flags);
if (k < 0) {
r = k;
break;
}
int device_enumerator_add_parent_devices(sd_device_enumerator *enumerator, sd_device *device) {
- return enumerator_add_parent_devices(enumerator, device, /* ignore_parent_match = */ true);
+ return enumerator_add_parent_devices(enumerator, device, MATCH_ALL & (~MATCH_PARENT));
}
static bool relevant_sysfs_subdir(const struct dirent *de) {
continue;
}
- k = test_matches(enumerator, device, /* ignore_parent_match = */ false);
+ k = test_matches(enumerator, device, MATCH_ALL & (~MATCH_SYSNAME)); /* sysname is already tested. */
if (k <= 0) {
if (k < 0)
r = k;
/* Also include all potentially matching parent devices in the enumeration. These are things
* like root busses — e.g. /sys/devices/pci0000:00/ or /sys/devices/pnp0/, which ar not
* linked from /sys/class/ or /sys/bus/, hence pick them up explicitly here. */
- k = enumerator_add_parent_devices(enumerator, device, /* ignore_parent_match = */ false);
+ k = enumerator_add_parent_devices(enumerator, device, MATCH_ALL);
if (k < 0)
r = k;
}
FOREACH_DIRENT_ALL(de, dir, return -errno) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
- const char *subsystem, *sysname;
int k;
if (de->d_name[0] == '.')
continue;
}
- k = sd_device_get_subsystem(device, &subsystem);
- if (k < 0) {
- if (k != -ENOENT)
- /* this is necessarily racy, so ignore missing devices */
- r = k;
- continue;
- }
-
- if (!match_subsystem(enumerator, subsystem))
- continue;
-
- k = sd_device_get_sysname(device, &sysname);
- if (k < 0) {
+ /* Generated from tag, hence not necessary to check tag again. */
+ k = test_matches(enumerator, device, MATCH_ALL & (~MATCH_TAG));
+ if (k < 0)
r = k;
- continue;
- }
-
- if (!match_sysname(enumerator, sysname))
- continue;
-
- if (!device_match_parent(device, enumerator->match_parent, NULL))
- continue;
-
- if (!match_property(enumerator, device))
- continue;
-
- if (!device_match_sysattr(device, enumerator->match_sysattr, enumerator->nomatch_sysattr))
+ if (k <= 0)
continue;
k = device_enumerator_add_device(enumerator, device);
static int parent_add_child(sd_device_enumerator *enumerator, const char *path) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
- const char *subsystem, *sysname;
int r;
r = sd_device_new_from_syspath(&device, path);
else if (r < 0)
return r;
- r = sd_device_get_subsystem(device, &subsystem);
- if (r == -ENOENT)
- return 0;
- if (r < 0)
- return r;
-
- if (!match_subsystem(enumerator, subsystem))
- return 0;
-
- r = sd_device_get_sysname(device, &sysname);
- if (r < 0)
- return r;
-
- if (!match_sysname(enumerator, sysname))
- return 0;
-
- if (!match_property(enumerator, device))
- return 0;
-
- if (!device_match_sysattr(device, enumerator->match_sysattr, enumerator->nomatch_sysattr))
- return 0;
-
- r = device_enumerator_add_device(enumerator, device);
- if (r < 0)
+ r = test_matches(enumerator, device, MATCH_ALL & (~MATCH_PARENT));
+ if (r <= 0)
return r;
- return 1;
+ return device_enumerator_add_device(enumerator, device);
}
static int parent_crawl_children(sd_device_enumerator *enumerator, const char *path, unsigned maxdepth) {