1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include "alloc-util.h"
9 #include "device-enumerator-private.h"
10 #include "device-filter.h"
11 #include "device-util.h"
12 #include "dirent-util.h"
15 #include "sort-util.h"
16 #include "string-util.h"
19 typedef enum DeviceEnumerationType
{
20 DEVICE_ENUMERATION_TYPE_DEVICES
,
21 DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
,
22 DEVICE_ENUMERATION_TYPE_ALL
,
23 _DEVICE_ENUMERATION_TYPE_MAX
,
24 _DEVICE_ENUMERATION_TYPE_INVALID
= -EINVAL
,
25 } DeviceEnumerationType
;
27 struct sd_device_enumerator
{
30 DeviceEnumerationType type
;
31 Hashmap
*devices_by_syspath
;
33 size_t n_devices
, current_device_index
;
37 char **prioritized_subsystems
;
39 Set
*nomatch_subsystem
;
40 Hashmap
*match_sysattr
;
41 Hashmap
*nomatch_sysattr
;
42 Hashmap
*match_property
;
47 MatchInitializedType match_initialized
;
50 _public_
int sd_device_enumerator_new(sd_device_enumerator
**ret
) {
51 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*enumerator
= NULL
;
55 enumerator
= new(sd_device_enumerator
, 1);
59 *enumerator
= (sd_device_enumerator
) {
61 .type
= _DEVICE_ENUMERATION_TYPE_INVALID
,
62 .match_initialized
= MATCH_INITIALIZED_COMPAT
,
65 *ret
= TAKE_PTR(enumerator
);
70 static void device_unref_many(sd_device
**devices
, size_t n
) {
71 assert(devices
|| n
== 0);
73 for (size_t i
= 0; i
< n
; i
++)
74 sd_device_unref(devices
[i
]);
77 static void device_enumerator_unref_devices(sd_device_enumerator
*enumerator
) {
80 hashmap_clear_with_destructor(enumerator
->devices_by_syspath
, sd_device_unref
);
81 device_unref_many(enumerator
->devices
, enumerator
->n_devices
);
82 enumerator
->devices
= mfree(enumerator
->devices
);
83 enumerator
->n_devices
= 0;
86 static sd_device_enumerator
*device_enumerator_free(sd_device_enumerator
*enumerator
) {
89 device_enumerator_unref_devices(enumerator
);
91 hashmap_free(enumerator
->devices_by_syspath
);
92 strv_free(enumerator
->prioritized_subsystems
);
93 set_free(enumerator
->match_subsystem
);
94 set_free(enumerator
->nomatch_subsystem
);
95 hashmap_free(enumerator
->match_sysattr
);
96 hashmap_free(enumerator
->nomatch_sysattr
);
97 hashmap_free(enumerator
->match_property
);
98 set_free(enumerator
->match_sysname
);
99 set_free(enumerator
->nomatch_sysname
);
100 set_free(enumerator
->match_tag
);
101 set_free(enumerator
->match_parent
);
103 return mfree(enumerator
);
106 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device_enumerator
, sd_device_enumerator
, device_enumerator_free
);
108 int device_enumerator_add_prioritized_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
) {
114 if (strv_contains(enumerator
->prioritized_subsystems
, subsystem
))
117 r
= strv_extend(&enumerator
->prioritized_subsystems
, subsystem
);
121 enumerator
->scan_uptodate
= false;
126 _public_
int sd_device_enumerator_add_match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
, int match
) {
130 assert_return(enumerator
, -EINVAL
);
131 assert_return(subsystem
, -EINVAL
);
134 set
= &enumerator
->match_subsystem
;
136 set
= &enumerator
->nomatch_subsystem
;
138 r
= set_put_strdup(set
, subsystem
);
142 enumerator
->scan_uptodate
= false;
147 _public_
int sd_device_enumerator_add_match_sysattr(sd_device_enumerator
*enumerator
, const char *sysattr
, const char *value
, int match
) {
151 assert_return(enumerator
, -EINVAL
);
152 assert_return(sysattr
, -EINVAL
);
155 hashmap
= &enumerator
->match_sysattr
;
157 hashmap
= &enumerator
->nomatch_sysattr
;
159 r
= update_match_strv(hashmap
, sysattr
, value
, /* clear_on_null = */ true);
163 enumerator
->scan_uptodate
= false;
168 _public_
int sd_device_enumerator_add_match_property(sd_device_enumerator
*enumerator
, const char *property
, const char *value
) {
171 assert_return(enumerator
, -EINVAL
);
172 assert_return(property
, -EINVAL
);
174 r
= update_match_strv(&enumerator
->match_property
, property
, value
, /* clear_on_null = */ false);
178 enumerator
->scan_uptodate
= false;
183 static int device_enumerator_add_match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
, bool match
) {
186 assert_return(enumerator
, -EINVAL
);
187 assert_return(sysname
, -EINVAL
);
189 r
= set_put_strdup(match
? &enumerator
->match_sysname
: &enumerator
->nomatch_sysname
, sysname
);
193 enumerator
->scan_uptodate
= false;
198 _public_
int sd_device_enumerator_add_match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
199 return device_enumerator_add_match_sysname(enumerator
, sysname
, true);
202 _public_
int sd_device_enumerator_add_nomatch_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
203 return device_enumerator_add_match_sysname(enumerator
, sysname
, false);
206 _public_
int sd_device_enumerator_add_match_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
209 assert_return(enumerator
, -EINVAL
);
210 assert_return(tag
, -EINVAL
);
212 r
= set_put_strdup(&enumerator
->match_tag
, tag
);
216 enumerator
->scan_uptodate
= false;
221 int device_enumerator_add_match_parent_incremental(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
228 r
= sd_device_get_syspath(parent
, &path
);
232 r
= set_put_strdup(&enumerator
->match_parent
, path
);
236 enumerator
->scan_uptodate
= false;
241 _public_
int sd_device_enumerator_add_match_parent(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
242 assert_return(enumerator
, -EINVAL
);
243 assert_return(parent
, -EINVAL
);
245 set_clear(enumerator
->match_parent
);
247 return device_enumerator_add_match_parent_incremental(enumerator
, parent
);
250 _public_
int sd_device_enumerator_allow_uninitialized(sd_device_enumerator
*enumerator
) {
251 assert_return(enumerator
, -EINVAL
);
253 enumerator
->match_initialized
= MATCH_INITIALIZED_ALL
;
255 enumerator
->scan_uptodate
= false;
260 int device_enumerator_add_match_is_initialized(sd_device_enumerator
*enumerator
, MatchInitializedType type
) {
261 assert_return(enumerator
, -EINVAL
);
262 assert_return(type
>= 0 && type
< _MATCH_INITIALIZED_MAX
, -EINVAL
);
264 enumerator
->match_initialized
= type
;
266 enumerator
->scan_uptodate
= false;
271 static int sound_device_compare(const char *devpath_a
, const char *devpath_b
) {
272 const char *sound_a
, *sound_b
;
278 /* For sound cards the control device must be enumerated last to make sure it's the final
279 * device node that gets ACLs applied. Applications rely on this fact and use ACL changes on
280 * the control node as an indicator that the ACL change of the entire sound card completed. The
281 * kernel makes this guarantee when creating those devices, and hence we should too when
282 * enumerating them. */
284 sound_a
= strstrafter(devpath_a
, "/sound/card");
288 sound_a
= strchr(devpath_a
, '/');
292 prefix_len
= sound_a
- devpath_a
;
294 if (!strneq(devpath_a
, devpath_b
, prefix_len
))
297 sound_b
= devpath_b
+ prefix_len
;
299 return CMP(!!startswith(sound_a
, "/controlC"),
300 !!startswith(sound_b
, "/controlC"));
303 static bool devpath_is_late_block(const char *devpath
) {
306 return strstr(devpath
, "/block/md") || strstr(devpath
, "/block/dm-");
309 static int device_compare(sd_device
* const *a
, sd_device
* const *b
) {
310 const char *devpath_a
, *devpath_b
;
318 assert_se(sd_device_get_devpath(*(sd_device
**) a
, &devpath_a
) >= 0);
319 assert_se(sd_device_get_devpath(*(sd_device
**) b
, &devpath_b
) >= 0);
321 r
= sound_device_compare(devpath_a
, devpath_b
);
325 /* md and dm devices are enumerated after all other devices */
326 r
= CMP(devpath_is_late_block(devpath_a
), devpath_is_late_block(devpath_b
));
330 return path_compare(devpath_a
, devpath_b
);
333 static int enumerator_sort_devices(sd_device_enumerator
*enumerator
) {
334 size_t n_sorted
= 0, n
= 0;
341 if (enumerator
->sorted
)
344 devices
= new(sd_device
*, hashmap_size(enumerator
->devices_by_syspath
));
348 STRV_FOREACH(prioritized_subsystem
, enumerator
->prioritized_subsystems
) {
354 HASHMAP_FOREACH_KEY(device
, syspath
, enumerator
->devices_by_syspath
) {
355 _cleanup_free_
char *p
= NULL
;
358 if (sd_device_get_subsystem(device
, &subsys
) < 0)
361 if (!streq(subsys
, *prioritized_subsystem
))
364 devices
[n
++] = sd_device_ref(device
);
367 _cleanup_free_
char *q
= NULL
;
369 r
= path_extract_directory(p
?: syspath
, &q
);
370 if (r
== -EADDRNOTAVAIL
)
375 device
= hashmap_get(enumerator
->devices_by_syspath
, q
);
377 devices
[n
++] = sd_device_ref(device
);
379 free_and_replace(p
, q
);
385 /* We cannot remove multiple entries in the loop HASHMAP_FOREACH_KEY() above. */
386 for (size_t i
= m
; i
< n
; i
++) {
387 r
= sd_device_get_syspath(devices
[i
], &syspath
);
391 assert_se(hashmap_remove(enumerator
->devices_by_syspath
, syspath
) == devices
[i
]);
392 sd_device_unref(devices
[i
]);
399 typesafe_qsort(devices
+ n_sorted
, n
- n_sorted
, device_compare
);
403 HASHMAP_FOREACH(device
, enumerator
->devices_by_syspath
)
404 devices
[n
++] = sd_device_ref(device
);
406 /* Move all devices back to the hashmap. Otherwise, devices added by
407 * udev_enumerate_add_syspath() -> device_enumerator_add_device() may not be listed. */
408 for (size_t i
= 0; i
< n_sorted
; i
++) {
411 r
= sd_device_get_syspath(devices
[i
], &syspath
);
415 r
= hashmap_put(enumerator
->devices_by_syspath
, syspath
, devices
[i
]);
420 sd_device_ref(devices
[i
]);
423 typesafe_qsort(devices
+ n_sorted
, n
- n_sorted
, device_compare
);
425 device_unref_many(enumerator
->devices
, enumerator
->n_devices
);
427 enumerator
->n_devices
= n
;
428 free_and_replace(enumerator
->devices
, devices
);
430 enumerator
->sorted
= true;
434 device_unref_many(devices
, n
);
439 int device_enumerator_add_device(sd_device_enumerator
*enumerator
, sd_device
*device
) {
443 assert_return(enumerator
, -EINVAL
);
444 assert_return(device
, -EINVAL
);
446 r
= sd_device_get_syspath(device
, &syspath
);
450 r
= hashmap_ensure_put(&enumerator
->devices_by_syspath
, &string_hash_ops
, syspath
, device
);
451 if (IN_SET(r
, -EEXIST
, 0))
456 sd_device_ref(device
);
458 enumerator
->sorted
= false;
462 static bool match_property(sd_device_enumerator
*enumerator
, sd_device
*device
) {
463 const char *property_pattern
;
464 char * const *value_patterns
;
469 /* Unlike device_match_sysattr(), this accepts device that has at least one matching property. */
471 if (hashmap_isempty(enumerator
->match_property
))
474 HASHMAP_FOREACH_KEY(value_patterns
, property_pattern
, enumerator
->match_property
) {
475 const char *property
, *value
;
477 FOREACH_DEVICE_PROPERTY(device
, property
, value
) {
478 if (fnmatch(property_pattern
, property
, 0) != 0)
481 if (strv_fnmatch(value_patterns
, value
))
489 static bool match_tag(sd_device_enumerator
*enumerator
, sd_device
*device
) {
495 SET_FOREACH(tag
, enumerator
->match_tag
)
496 if (!sd_device_has_tag(device
, tag
))
502 static bool match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
506 return set_fnmatch(enumerator
->match_sysname
, enumerator
->nomatch_sysname
, sysname
);
509 static int match_initialized(sd_device_enumerator
*enumerator
, sd_device
*device
) {
515 if (enumerator
->match_initialized
== MATCH_INITIALIZED_ALL
)
518 r
= sd_device_get_is_initialized(device
);
519 if (r
== -ENOENT
) /* this is necessarily racey, so ignore missing devices */
524 if (enumerator
->match_initialized
== MATCH_INITIALIZED_COMPAT
) {
525 /* only devices that have no devnode/ifindex or have a db entry are accepted. */
529 if (sd_device_get_devnum(device
, NULL
) >= 0)
532 if (sd_device_get_ifindex(device
, NULL
) >= 0)
538 return (enumerator
->match_initialized
== MATCH_INITIALIZED_NO
) == (r
== 0);
541 static bool match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
) {
547 return set_fnmatch(enumerator
->match_subsystem
, enumerator
->nomatch_subsystem
, subsystem
);
550 typedef enum MatchFlag
{
551 MATCH_SYSNAME
= 1u << 0,
552 MATCH_SUBSYSTEM
= 1u << 1,
553 MATCH_PARENT
= 1u << 2,
556 MATCH_ALL
= (1u << 4) - 1,
559 static int test_matches(
560 sd_device_enumerator
*enumerator
,
569 if (FLAGS_SET(flags
, MATCH_SYSNAME
)) {
572 r
= sd_device_get_sysname(device
, &sysname
);
576 if (!match_sysname(enumerator
, sysname
))
580 if (FLAGS_SET(flags
, MATCH_SUBSYSTEM
)) {
581 const char *subsystem
;
583 r
= sd_device_get_subsystem(device
, &subsystem
);
589 if (!match_subsystem(enumerator
, subsystem
))
593 if (FLAGS_SET(flags
, MATCH_PARENT
) &&
594 !device_match_parent(device
, enumerator
->match_parent
, NULL
))
597 if (FLAGS_SET(flags
, MATCH_TAG
) &&
598 !match_tag(enumerator
, device
))
601 r
= match_initialized(enumerator
, device
);
605 if (!match_property(enumerator
, device
))
608 if (!device_match_sysattr(device
, enumerator
->match_sysattr
, enumerator
->nomatch_sysattr
))
614 static int enumerator_add_parent_devices(
615 sd_device_enumerator
*enumerator
,
625 k
= sd_device_get_parent(device
, &device
);
626 if (k
== -ENOENT
) /* Reached the top? */
633 k
= test_matches(enumerator
, device
, flags
);
641 k
= device_enumerator_add_device(enumerator
, device
);
646 if (k
== 0) /* Exists already? Then no need to go further up. */
653 int device_enumerator_add_parent_devices(sd_device_enumerator
*enumerator
, sd_device
*device
) {
654 return enumerator_add_parent_devices(enumerator
, device
, MATCH_ALL
& (~MATCH_PARENT
));
657 static bool relevant_sysfs_subdir(const struct dirent
*de
) {
660 if (de
->d_name
[0] == '.')
663 /* Also filter out regular files and such, i.e. stuff that definitely isn't a kobject path. (Note
664 * that we rely on the fact that sysfs fills in d_type here, i.e. doesn't do DT_UNKNOWN) */
665 return IN_SET(de
->d_type
, DT_DIR
, DT_LNK
);
668 static int enumerator_scan_dir_and_add_devices(
669 sd_device_enumerator
*enumerator
,
672 const char *subdir2
) {
674 _cleanup_closedir_
DIR *dir
= NULL
;
681 path
= strjoina("/sys/", basedir
, "/");
684 path
= strjoina(path
, subdir1
, "/");
687 path
= strjoina(path
, subdir2
, "/");
691 bool ignore
= errno
== ENOENT
;
693 /* this is necessarily racey, so ignore missing directories */
694 log_debug_errno(errno
,
695 "sd-device-enumerator: Failed to open directory %s%s: %m",
696 path
, ignore
? ", ignoring" : "");
697 return ignore
? 0 : -errno
;
700 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
701 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
702 char syspath
[strlen(path
) + 1 + strlen(de
->d_name
) + 1];
704 if (!relevant_sysfs_subdir(de
))
707 if (!match_sysname(enumerator
, de
->d_name
))
710 (void) sprintf(syspath
, "%s%s", path
, de
->d_name
);
712 k
= sd_device_new_from_syspath(&device
, syspath
);
715 /* this is necessarily racey, so ignore missing devices */
721 k
= test_matches(enumerator
, device
, MATCH_ALL
& (~MATCH_SYSNAME
)); /* sysname is already tested. */
728 k
= device_enumerator_add_device(enumerator
, device
);
732 /* Also include all potentially matching parent devices in the enumeration. These are things
733 * like root busses — e.g. /sys/devices/pci0000:00/ or /sys/devices/pnp0/, which ar not
734 * linked from /sys/class/ or /sys/bus/, hence pick them up explicitly here. */
735 k
= enumerator_add_parent_devices(enumerator
, device
, MATCH_ALL
);
743 static int enumerator_scan_dir(
744 sd_device_enumerator
*enumerator
,
747 const char *subsystem
) {
749 _cleanup_closedir_
DIR *dir
= NULL
;
753 path
= strjoina("/sys/", basedir
);
757 bool ignore
= errno
== ENOENT
;
759 log_debug_errno(errno
,
760 "sd-device-enumerator: Failed to open directory %s%s: %m",
761 path
, ignore
? ", ignoring" : "");
762 return ignore
? 0 : -errno
;
765 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
768 if (!relevant_sysfs_subdir(de
))
771 if (!match_subsystem(enumerator
, subsystem
?: de
->d_name
))
774 k
= enumerator_scan_dir_and_add_devices(enumerator
, basedir
, de
->d_name
, subdir
);
782 static int enumerator_scan_devices_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
783 _cleanup_closedir_
DIR *dir
= NULL
;
790 path
= strjoina("/run/udev/tags/", tag
);
794 bool ignore
= errno
== ENOENT
;
796 log_debug_errno(errno
,
797 "sd-device-enumerator: Failed to open directory %s%s: %m",
798 path
, ignore
? ", ignoring" : "");
799 return ignore
? 0 : -errno
;
802 /* TODO: filter away subsystems? */
804 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
805 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
808 if (de
->d_name
[0] == '.')
811 k
= sd_device_new_from_device_id(&device
, de
->d_name
);
814 /* this is necessarily racy, so ignore missing devices */
820 /* Generated from tag, hence not necessary to check tag again. */
821 k
= test_matches(enumerator
, device
, MATCH_ALL
& (~MATCH_TAG
));
827 k
= device_enumerator_add_device(enumerator
, device
);
837 static int enumerator_scan_devices_tags(sd_device_enumerator
*enumerator
) {
843 SET_FOREACH(tag
, enumerator
->match_tag
) {
846 k
= enumerator_scan_devices_tag(enumerator
, tag
);
854 static int parent_add_child(sd_device_enumerator
*enumerator
, const char *path
, MatchFlag flags
) {
855 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
858 r
= sd_device_new_from_syspath(&device
, path
);
860 /* this is necessarily racy, so ignore missing devices */
865 r
= test_matches(enumerator
, device
, flags
);
869 return device_enumerator_add_device(enumerator
, device
);
872 static int parent_crawl_children(sd_device_enumerator
*enumerator
, const char *path
, Set
**stack
) {
873 _cleanup_closedir_
DIR *dir
= NULL
;
882 bool ignore
= errno
== ENOENT
;
884 log_debug_errno(errno
,
885 "sd-device-enumerator: Failed to open directory %s%s: %m",
886 path
, ignore
? ", ignoring" : "");
887 return ignore
? 0 : -errno
;
890 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
891 _cleanup_free_
char *child
= NULL
;
894 if (de
->d_name
[0] == '.')
897 if (de
->d_type
!= DT_DIR
)
900 child
= path_join(path
, de
->d_name
);
904 /* Let's check sysname filter earlier. The other tests require the sd-device object created
905 * from the path, thus much costly. */
906 if (match_sysname(enumerator
, de
->d_name
)) {
907 k
= parent_add_child(enumerator
, child
, MATCH_ALL
& (~(MATCH_SYSNAME
|MATCH_PARENT
)));
912 k
= set_ensure_consume(stack
, &path_hash_ops_free
, TAKE_PTR(child
));
920 static int enumerator_scan_devices_children(sd_device_enumerator
*enumerator
) {
921 _cleanup_set_free_ Set
*stack
= NULL
;
927 SET_FOREACH(path
, enumerator
->match_parent
) {
928 k
= parent_add_child(enumerator
, path
, MATCH_ALL
& (~MATCH_PARENT
));
932 k
= parent_crawl_children(enumerator
, path
, &stack
);
938 _cleanup_free_
char *p
= NULL
;
940 p
= set_steal_first(stack
);
944 k
= parent_crawl_children(enumerator
, p
, &stack
);
950 static int enumerator_scan_devices_all(sd_device_enumerator
*enumerator
) {
953 k
= enumerator_scan_dir(enumerator
, "bus", "devices", NULL
);
955 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan /sys/bus: %m");
957 k
= enumerator_scan_dir(enumerator
, "class", NULL
, NULL
);
959 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan /sys/class: %m");
964 int device_enumerator_scan_devices(sd_device_enumerator
*enumerator
) {
969 if (enumerator
->scan_uptodate
&&
970 enumerator
->type
== DEVICE_ENUMERATION_TYPE_DEVICES
)
973 device_enumerator_unref_devices(enumerator
);
975 if (!set_isempty(enumerator
->match_tag
)) {
976 k
= enumerator_scan_devices_tags(enumerator
);
979 } else if (enumerator
->match_parent
) {
980 k
= enumerator_scan_devices_children(enumerator
);
984 k
= enumerator_scan_devices_all(enumerator
);
989 enumerator
->scan_uptodate
= true;
990 enumerator
->type
= DEVICE_ENUMERATION_TYPE_DEVICES
;
995 _public_ sd_device
*sd_device_enumerator_get_device_first(sd_device_enumerator
*enumerator
) {
996 assert_return(enumerator
, NULL
);
998 if (device_enumerator_scan_devices(enumerator
) < 0)
1001 if (enumerator_sort_devices(enumerator
) < 0)
1004 enumerator
->current_device_index
= 0;
1006 if (enumerator
->n_devices
== 0)
1009 return enumerator
->devices
[0];
1012 _public_ sd_device
*sd_device_enumerator_get_device_next(sd_device_enumerator
*enumerator
) {
1013 assert_return(enumerator
, NULL
);
1015 if (!enumerator
->scan_uptodate
||
1016 !enumerator
->sorted
||
1017 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_DEVICES
||
1018 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
1021 return enumerator
->devices
[++enumerator
->current_device_index
];
1024 int device_enumerator_scan_subsystems(sd_device_enumerator
*enumerator
) {
1029 if (enumerator
->scan_uptodate
&&
1030 enumerator
->type
== DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
)
1033 device_enumerator_unref_devices(enumerator
);
1036 if (match_subsystem(enumerator
, "module")) {
1037 k
= enumerator_scan_dir_and_add_devices(enumerator
, "module", NULL
, NULL
);
1039 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan modules: %m");
1042 /* subsystems (only buses support coldplug) */
1043 if (match_subsystem(enumerator
, "subsystem")) {
1044 k
= enumerator_scan_dir_and_add_devices(enumerator
, "bus", NULL
, NULL
);
1046 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan subsystems: %m");
1049 /* subsystem drivers */
1050 if (match_subsystem(enumerator
, "drivers")) {
1051 k
= enumerator_scan_dir(enumerator
, "bus", "drivers", "drivers");
1053 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan drivers: %m");
1056 enumerator
->scan_uptodate
= true;
1057 enumerator
->type
= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
;
1062 _public_ sd_device
*sd_device_enumerator_get_subsystem_first(sd_device_enumerator
*enumerator
) {
1063 assert_return(enumerator
, NULL
);
1065 if (device_enumerator_scan_subsystems(enumerator
) < 0)
1068 if (enumerator_sort_devices(enumerator
) < 0)
1071 enumerator
->current_device_index
= 0;
1073 if (enumerator
->n_devices
== 0)
1076 return enumerator
->devices
[0];
1079 _public_ sd_device
*sd_device_enumerator_get_subsystem_next(sd_device_enumerator
*enumerator
) {
1080 assert_return(enumerator
, NULL
);
1082 if (!enumerator
->scan_uptodate
||
1083 !enumerator
->sorted
||
1084 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
||
1085 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
1088 return enumerator
->devices
[++enumerator
->current_device_index
];
1091 int device_enumerator_scan_devices_and_subsystems(sd_device_enumerator
*enumerator
) {
1096 if (enumerator
->scan_uptodate
&&
1097 enumerator
->type
== DEVICE_ENUMERATION_TYPE_ALL
)
1100 device_enumerator_unref_devices(enumerator
);
1102 if (!set_isempty(enumerator
->match_tag
))
1103 r
= enumerator_scan_devices_tags(enumerator
);
1104 else if (enumerator
->match_parent
)
1105 r
= enumerator_scan_devices_children(enumerator
);
1109 r
= enumerator_scan_devices_all(enumerator
);
1111 if (match_subsystem(enumerator
, "module")) {
1112 k
= enumerator_scan_dir_and_add_devices(enumerator
, "module", NULL
, NULL
);
1114 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan modules: %m");
1116 if (match_subsystem(enumerator
, "subsystem")) {
1117 k
= enumerator_scan_dir_and_add_devices(enumerator
, "bus", NULL
, NULL
);
1119 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan subsystems: %m");
1122 if (match_subsystem(enumerator
, "drivers")) {
1123 k
= enumerator_scan_dir(enumerator
, "bus", "drivers", "drivers");
1125 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan drivers: %m");
1129 enumerator
->scan_uptodate
= true;
1130 enumerator
->type
= DEVICE_ENUMERATION_TYPE_ALL
;
1135 sd_device
*device_enumerator_get_first(sd_device_enumerator
*enumerator
) {
1136 assert_return(enumerator
, NULL
);
1138 if (!enumerator
->scan_uptodate
)
1141 if (enumerator_sort_devices(enumerator
) < 0)
1144 enumerator
->current_device_index
= 0;
1146 if (enumerator
->n_devices
== 0)
1149 return enumerator
->devices
[0];
1152 sd_device
*device_enumerator_get_next(sd_device_enumerator
*enumerator
) {
1153 assert_return(enumerator
, NULL
);
1155 if (!enumerator
->scan_uptodate
||
1156 !enumerator
->sorted
||
1157 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
1160 return enumerator
->devices
[++enumerator
->current_device_index
];
1163 sd_device
**device_enumerator_get_devices(sd_device_enumerator
*enumerator
, size_t *ret_n_devices
) {
1165 assert(ret_n_devices
);
1167 if (!enumerator
->scan_uptodate
)
1170 if (enumerator_sort_devices(enumerator
) < 0)
1173 *ret_n_devices
= enumerator
->n_devices
;
1174 return enumerator
->devices
;