1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
7 #include "alloc-util.h"
8 #include "device-enumerator-private.h"
9 #include "device-filter.h"
10 #include "device-util.h"
11 #include "dirent-util.h"
14 #include "path-util.h"
16 #include "sort-util.h"
17 #include "string-util.h"
20 typedef enum DeviceEnumerationType
{
21 DEVICE_ENUMERATION_TYPE_DEVICES
,
22 DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
,
23 DEVICE_ENUMERATION_TYPE_ALL
,
24 _DEVICE_ENUMERATION_TYPE_MAX
,
25 _DEVICE_ENUMERATION_TYPE_INVALID
= -EINVAL
,
26 } DeviceEnumerationType
;
28 typedef enum MatchFlag
{
30 MATCH_BASIC
= 1u << 0,
31 MATCH_SYSNAME
= 1u << 1,
32 MATCH_SUBSYSTEM
= 1u << 2,
33 MATCH_PARENT
= 1u << 3,
36 MATCH_ALL
= (1u << 5) - 1,
39 struct sd_device_enumerator
{
42 DeviceEnumerationType type
;
43 Hashmap
*devices_by_syspath
;
45 size_t n_devices
, current_device_index
;
49 char **prioritized_subsystems
;
51 Set
*nomatch_subsystem
;
52 Hashmap
*match_sysattr
;
53 Hashmap
*nomatch_sysattr
;
54 Hashmap
*match_property
;
55 Hashmap
*match_property_required
;
60 MatchInitializedType match_initialized
;
61 MatchFlag parent_match_flags
;
64 _public_
int sd_device_enumerator_new(sd_device_enumerator
**ret
) {
65 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*enumerator
= NULL
;
69 enumerator
= new(sd_device_enumerator
, 1);
73 *enumerator
= (sd_device_enumerator
) {
75 .type
= _DEVICE_ENUMERATION_TYPE_INVALID
,
76 .match_initialized
= MATCH_INITIALIZED_COMPAT
,
77 .parent_match_flags
= MATCH_ALL
,
80 *ret
= TAKE_PTR(enumerator
);
85 static void device_unref_many(sd_device
**devices
, size_t n
) {
86 assert(devices
|| n
== 0);
88 for (size_t i
= 0; i
< n
; i
++)
89 sd_device_unref(devices
[i
]);
92 static void device_enumerator_unref_devices(sd_device_enumerator
*enumerator
) {
95 hashmap_clear(enumerator
->devices_by_syspath
);
96 device_unref_many(enumerator
->devices
, enumerator
->n_devices
);
97 enumerator
->devices
= mfree(enumerator
->devices
);
98 enumerator
->n_devices
= 0;
101 static sd_device_enumerator
*device_enumerator_free(sd_device_enumerator
*enumerator
) {
104 device_enumerator_unref_devices(enumerator
);
106 hashmap_free(enumerator
->devices_by_syspath
);
107 strv_free(enumerator
->prioritized_subsystems
);
108 set_free(enumerator
->match_subsystem
);
109 set_free(enumerator
->nomatch_subsystem
);
110 hashmap_free(enumerator
->match_sysattr
);
111 hashmap_free(enumerator
->nomatch_sysattr
);
112 hashmap_free(enumerator
->match_property
);
113 hashmap_free(enumerator
->match_property_required
);
114 set_free(enumerator
->match_sysname
);
115 set_free(enumerator
->nomatch_sysname
);
116 set_free(enumerator
->match_tag
);
117 set_free(enumerator
->match_parent
);
119 return mfree(enumerator
);
122 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device_enumerator
, sd_device_enumerator
, device_enumerator_free
);
124 int device_enumerator_add_prioritized_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
) {
130 if (strv_contains(enumerator
->prioritized_subsystems
, subsystem
))
133 r
= strv_extend(&enumerator
->prioritized_subsystems
, subsystem
);
137 enumerator
->scan_uptodate
= false;
142 _public_
int sd_device_enumerator_add_match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
, int match
) {
146 assert_return(enumerator
, -EINVAL
);
147 assert_return(subsystem
, -EINVAL
);
150 set
= &enumerator
->match_subsystem
;
152 set
= &enumerator
->nomatch_subsystem
;
154 r
= set_put_strdup(set
, subsystem
);
158 enumerator
->scan_uptodate
= false;
163 _public_
int sd_device_enumerator_add_match_sysattr(sd_device_enumerator
*enumerator
, const char *sysattr
, const char *value
, int match
) {
167 assert_return(enumerator
, -EINVAL
);
168 assert_return(sysattr
, -EINVAL
);
171 hashmap
= &enumerator
->match_sysattr
;
173 hashmap
= &enumerator
->nomatch_sysattr
;
175 r
= update_match_strv(hashmap
, sysattr
, value
, /* clear_on_null = */ true);
179 enumerator
->scan_uptodate
= false;
184 _public_
int sd_device_enumerator_add_match_property(sd_device_enumerator
*enumerator
, const char *property
, const char *value
) {
187 assert_return(enumerator
, -EINVAL
);
188 assert_return(property
, -EINVAL
);
190 r
= update_match_strv(&enumerator
->match_property
, property
, value
, /* clear_on_null = */ false);
194 enumerator
->scan_uptodate
= false;
199 _public_
int sd_device_enumerator_add_match_property_required(sd_device_enumerator
*enumerator
, const char *property
, const char *value
) {
202 assert_return(enumerator
, -EINVAL
);
203 assert_return(property
, -EINVAL
);
205 r
= update_match_strv(&enumerator
->match_property_required
, property
, value
, /* clear_on_null = */ false);
209 enumerator
->scan_uptodate
= false;
214 static int device_enumerator_add_match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
, bool match
) {
217 assert_return(enumerator
, -EINVAL
);
218 assert_return(sysname
, -EINVAL
);
220 r
= set_put_strdup(match
? &enumerator
->match_sysname
: &enumerator
->nomatch_sysname
, sysname
);
224 enumerator
->scan_uptodate
= false;
229 _public_
int sd_device_enumerator_add_match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
230 return device_enumerator_add_match_sysname(enumerator
, sysname
, true);
233 _public_
int sd_device_enumerator_add_nomatch_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
234 return device_enumerator_add_match_sysname(enumerator
, sysname
, false);
237 _public_
int sd_device_enumerator_add_match_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
240 assert_return(enumerator
, -EINVAL
);
241 assert_return(tag
, -EINVAL
);
243 r
= set_put_strdup(&enumerator
->match_tag
, tag
);
247 enumerator
->scan_uptodate
= false;
252 int device_enumerator_add_match_parent_incremental(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
259 r
= sd_device_get_syspath(parent
, &path
);
263 r
= set_put_strdup(&enumerator
->match_parent
, path
);
267 enumerator
->scan_uptodate
= false;
272 _public_
int sd_device_enumerator_add_match_parent(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
273 assert_return(enumerator
, -EINVAL
);
274 assert_return(parent
, -EINVAL
);
276 set_clear(enumerator
->match_parent
);
278 return device_enumerator_add_match_parent_incremental(enumerator
, parent
);
281 _public_
int sd_device_enumerator_allow_uninitialized(sd_device_enumerator
*enumerator
) {
282 assert_return(enumerator
, -EINVAL
);
284 enumerator
->match_initialized
= MATCH_INITIALIZED_ALL
;
286 enumerator
->scan_uptodate
= false;
290 _public_
int sd_device_enumerator_add_all_parents(sd_device_enumerator
*enumerator
) {
291 assert_return(enumerator
, -EINVAL
);
293 enumerator
->parent_match_flags
= MATCH_NONE
;
295 enumerator
->scan_uptodate
= false;
300 int device_enumerator_add_match_is_initialized(sd_device_enumerator
*enumerator
, MatchInitializedType type
) {
301 assert_return(enumerator
, -EINVAL
);
302 assert_return(type
>= 0 && type
< _MATCH_INITIALIZED_MAX
, -EINVAL
);
304 enumerator
->match_initialized
= type
;
306 enumerator
->scan_uptodate
= false;
311 static int sound_device_compare(const char *devpath_a
, const char *devpath_b
) {
312 const char *sound_a
, *sound_b
;
318 /* For sound cards the control device must be enumerated last to make sure it's the final
319 * device node that gets ACLs applied. Applications rely on this fact and use ACL changes on
320 * the control node as an indicator that the ACL change of the entire sound card completed. The
321 * kernel makes this guarantee when creating those devices, and hence we should too when
322 * enumerating them. */
324 sound_a
= strstrafter(devpath_a
, "/sound/card");
328 sound_a
= strchr(devpath_a
, '/');
332 prefix_len
= sound_a
- devpath_a
;
334 if (!strneq(devpath_a
, devpath_b
, prefix_len
))
337 sound_b
= devpath_b
+ prefix_len
;
339 return CMP(!!startswith(sound_a
, "/controlC"),
340 !!startswith(sound_b
, "/controlC"));
343 static bool devpath_is_late_block(const char *devpath
) {
346 return strstr(devpath
, "/block/md") || strstr(devpath
, "/block/dm-");
349 static int device_compare(sd_device
* const *a
, sd_device
* const *b
) {
350 const char *devpath_a
, *devpath_b
;
358 assert_se(sd_device_get_devpath(*(sd_device
**) a
, &devpath_a
) >= 0);
359 assert_se(sd_device_get_devpath(*(sd_device
**) b
, &devpath_b
) >= 0);
361 r
= sound_device_compare(devpath_a
, devpath_b
);
365 /* md and dm devices are enumerated after all other devices */
366 r
= CMP(devpath_is_late_block(devpath_a
), devpath_is_late_block(devpath_b
));
370 return path_compare(devpath_a
, devpath_b
);
373 static int enumerator_sort_devices(sd_device_enumerator
*enumerator
) {
374 size_t n_sorted
= 0, n
= 0;
381 if (enumerator
->sorted
)
384 devices
= new(sd_device
*, hashmap_size(enumerator
->devices_by_syspath
));
388 STRV_FOREACH(prioritized_subsystem
, enumerator
->prioritized_subsystems
) {
394 HASHMAP_FOREACH_KEY(device
, syspath
, enumerator
->devices_by_syspath
) {
395 _cleanup_free_
char *p
= NULL
;
397 r
= device_in_subsystem(device
, *prioritized_subsystem
);
403 devices
[n
++] = sd_device_ref(device
);
406 _cleanup_free_
char *q
= NULL
;
408 r
= path_extract_directory(p
?: syspath
, &q
);
409 if (r
== -EADDRNOTAVAIL
)
414 device
= hashmap_get(enumerator
->devices_by_syspath
, q
);
416 devices
[n
++] = sd_device_ref(device
);
418 free_and_replace(p
, q
);
424 /* We cannot remove multiple entries in the loop HASHMAP_FOREACH_KEY() above. */
425 for (size_t i
= m
; i
< n
; i
++) {
426 r
= sd_device_get_syspath(devices
[i
], &syspath
);
430 assert_se(hashmap_remove(enumerator
->devices_by_syspath
, syspath
) == devices
[i
]);
431 sd_device_unref(devices
[i
]);
438 typesafe_qsort(devices
+ n_sorted
, n
- n_sorted
, device_compare
);
442 HASHMAP_FOREACH(device
, enumerator
->devices_by_syspath
)
443 devices
[n
++] = sd_device_ref(device
);
445 /* Move all devices back to the hashmap. Otherwise, devices added by
446 * udev_enumerate_add_syspath() -> device_enumerator_add_device() may not be listed. */
447 for (size_t i
= 0; i
< n_sorted
; i
++) {
450 r
= sd_device_get_syspath(devices
[i
], &syspath
);
454 r
= hashmap_put(enumerator
->devices_by_syspath
, syspath
, devices
[i
]);
459 sd_device_ref(devices
[i
]);
462 typesafe_qsort(devices
+ n_sorted
, n
- n_sorted
, device_compare
);
464 device_unref_many(enumerator
->devices
, enumerator
->n_devices
);
466 enumerator
->n_devices
= n
;
467 free_and_replace(enumerator
->devices
, devices
);
469 enumerator
->sorted
= true;
473 device_unref_many(devices
, n
);
478 DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
479 device_hash_ops_by_syspath
,
480 char, path_hash_func
, path_compare
,
481 sd_device
, sd_device_unref
);
483 int device_enumerator_add_device(sd_device_enumerator
*enumerator
, sd_device
*device
) {
487 assert_return(enumerator
, -EINVAL
);
488 assert_return(device
, -EINVAL
);
490 r
= sd_device_get_syspath(device
, &syspath
);
494 r
= hashmap_ensure_put(&enumerator
->devices_by_syspath
, &device_hash_ops_by_syspath
, syspath
, device
);
495 if (IN_SET(r
, -EEXIST
, 0))
500 sd_device_ref(device
);
502 enumerator
->sorted
= false;
506 static bool match_property(Hashmap
*properties
, sd_device
*device
, bool match_all
) {
507 const char *property_pattern
;
508 char * const *value_patterns
;
512 /* Unlike device_match_sysattr(), this accepts device that has at least one matching property. */
514 if (hashmap_isempty(properties
))
517 HASHMAP_FOREACH_KEY(value_patterns
, property_pattern
, properties
) {
520 FOREACH_DEVICE_PROPERTY(device
, property
, value
) {
521 if (fnmatch(property_pattern
, property
, 0) != 0)
524 match
= strv_fnmatch(value_patterns
, value
);
533 if (!match
&& match_all
)
540 static bool match_tag(sd_device_enumerator
*enumerator
, sd_device
*device
) {
546 SET_FOREACH(tag
, enumerator
->match_tag
)
547 if (!sd_device_has_tag(device
, tag
))
553 static bool match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
557 return set_fnmatch(enumerator
->match_sysname
, enumerator
->nomatch_sysname
, sysname
);
560 static int match_initialized(sd_device_enumerator
*enumerator
, sd_device
*device
) {
566 if (enumerator
->match_initialized
== MATCH_INITIALIZED_ALL
)
569 r
= sd_device_get_is_initialized(device
);
570 if (r
== -ENOENT
) /* this is necessarily racey, so ignore missing devices */
575 if (enumerator
->match_initialized
== MATCH_INITIALIZED_COMPAT
) {
576 /* only devices that have no devnode/ifindex or have a db entry are accepted. */
580 if (sd_device_get_devnum(device
, NULL
) >= 0)
583 if (sd_device_get_ifindex(device
, NULL
) >= 0)
589 return (enumerator
->match_initialized
== MATCH_INITIALIZED_NO
) == (r
== 0);
592 static bool match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
) {
598 return set_fnmatch(enumerator
->match_subsystem
, enumerator
->nomatch_subsystem
, subsystem
);
601 static int test_matches(
602 sd_device_enumerator
*enumerator
,
611 if (FLAGS_SET(flags
, MATCH_SYSNAME
)) {
614 r
= sd_device_get_sysname(device
, &sysname
);
618 if (!match_sysname(enumerator
, sysname
))
622 if (FLAGS_SET(flags
, MATCH_SUBSYSTEM
)) {
623 const char *subsystem
;
625 r
= sd_device_get_subsystem(device
, &subsystem
);
631 if (!match_subsystem(enumerator
, subsystem
))
635 if (FLAGS_SET(flags
, MATCH_PARENT
) &&
636 !device_match_parent(device
, enumerator
->match_parent
, NULL
))
639 if (FLAGS_SET(flags
, MATCH_TAG
) &&
640 !match_tag(enumerator
, device
))
643 if (FLAGS_SET(flags
, MATCH_BASIC
)) {
644 r
= match_initialized(enumerator
, device
);
648 if (!match_property(enumerator
->match_property
, device
, /* match_all = */ false))
651 if (!match_property(enumerator
->match_property_required
, device
, /* match_all = */ true))
654 if (!device_match_sysattr(device
, enumerator
->match_sysattr
, enumerator
->nomatch_sysattr
))
661 static int enumerator_add_parent_devices(
662 sd_device_enumerator
*enumerator
,
672 r
= sd_device_get_parent(device
, &device
);
673 if (r
== -ENOENT
) /* Reached the top? */
678 r
= test_matches(enumerator
, device
, flags
);
684 r
= device_enumerator_add_device(enumerator
, device
);
685 if (r
<= 0) /* r == 0 means the device already exists, then no need to go further up. */
690 int device_enumerator_add_parent_devices(sd_device_enumerator
*enumerator
, sd_device
*device
) {
691 return enumerator_add_parent_devices(enumerator
, device
, MATCH_ALL
& (~MATCH_PARENT
));
694 static bool relevant_sysfs_subdir(const struct dirent
*de
) {
697 if (de
->d_name
[0] == '.')
700 /* Also filter out regular files and such, i.e. stuff that definitely isn't a kobject path. (Note
701 * that we rely on the fact that sysfs fills in d_type here, i.e. doesn't do DT_UNKNOWN) */
702 return IN_SET(de
->d_type
, DT_DIR
, DT_LNK
);
705 static int enumerator_scan_dir_and_add_devices(
706 sd_device_enumerator
*enumerator
,
709 const char *subdir2
) {
711 _cleanup_closedir_
DIR *dir
= NULL
;
718 path
= strjoina("/sys/", basedir
, "/");
721 path
= strjoina(path
, subdir1
, "/");
724 path
= strjoina(path
, subdir2
, "/");
728 /* This is necessarily racey, so ignore missing directories */
732 return log_debug_errno(errno
, "sd-device-enumerator: Failed to open directory '%s': %m", path
);
735 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
736 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
737 char syspath
[strlen(path
) + 1 + strlen(de
->d_name
) + 1];
739 if (!relevant_sysfs_subdir(de
))
742 if (!match_sysname(enumerator
, de
->d_name
))
745 (void) sprintf(syspath
, "%s%s", path
, de
->d_name
);
747 k
= sd_device_new_from_syspath(&device
, syspath
);
750 /* this is necessarily racey, so ignore missing devices */
756 k
= test_matches(enumerator
, device
, MATCH_ALL
& (~MATCH_SYSNAME
)); /* sysname is already tested. */
763 k
= device_enumerator_add_device(enumerator
, device
);
767 /* Also include all potentially matching parent devices in the enumeration. These are things
768 * like root busses — e.g. /sys/devices/pci0000:00/ or /sys/devices/pnp0/, which ar not
769 * linked from /sys/class/ or /sys/bus/, hence pick them up explicitly here. */
770 k
= enumerator_add_parent_devices(enumerator
, device
, enumerator
->parent_match_flags
);
778 static int enumerator_scan_dir(
779 sd_device_enumerator
*enumerator
,
782 const char *subsystem
) {
784 _cleanup_closedir_
DIR *dir
= NULL
;
788 path
= strjoina("/sys/", basedir
);
795 return log_debug_errno(errno
, "sd-device-enumerator: Failed to open directory '%s': %m", path
);
798 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
801 if (!relevant_sysfs_subdir(de
))
804 if (!match_subsystem(enumerator
, subsystem
?: de
->d_name
))
807 k
= enumerator_scan_dir_and_add_devices(enumerator
, basedir
, de
->d_name
, subdir
);
815 static int enumerator_scan_devices_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
816 _cleanup_closedir_
DIR *dir
= NULL
;
823 path
= strjoina("/run/udev/tags/", tag
);
830 return log_debug_errno(errno
, "sd-device-enumerator: Failed to open directory '%s': %m", path
);
833 /* TODO: filter away subsystems? */
835 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
836 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
839 if (de
->d_name
[0] == '.')
842 k
= sd_device_new_from_device_id(&device
, de
->d_name
);
845 /* this is necessarily racy, so ignore missing devices */
851 /* Generated from tag, hence not necessary to check tag again. */
852 k
= test_matches(enumerator
, device
, MATCH_ALL
& (~MATCH_TAG
));
858 k
= device_enumerator_add_device(enumerator
, device
);
868 static int enumerator_scan_devices_tags(sd_device_enumerator
*enumerator
) {
874 SET_FOREACH(tag
, enumerator
->match_tag
) {
877 k
= enumerator_scan_devices_tag(enumerator
, tag
);
885 static int parent_add_child(sd_device_enumerator
*enumerator
, const char *path
, MatchFlag flags
) {
886 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
889 r
= sd_device_new_from_syspath(&device
, path
);
891 /* this is necessarily racy, so ignore missing devices */
896 r
= test_matches(enumerator
, device
, flags
);
900 return device_enumerator_add_device(enumerator
, device
);
903 static int parent_crawl_children(sd_device_enumerator
*enumerator
, const char *path
, Set
**stack
) {
904 _cleanup_closedir_
DIR *dir
= NULL
;
916 return log_debug_errno(errno
, "sd-device-enumerator: Failed to open directory '%s': %m", path
);
919 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
920 _cleanup_free_
char *child
= NULL
;
923 if (de
->d_name
[0] == '.')
926 if (de
->d_type
!= DT_DIR
)
929 child
= path_join(path
, de
->d_name
);
933 /* Let's check sysname filter earlier. The other tests require the sd-device object created
934 * from the path, thus much costly. */
935 if (match_sysname(enumerator
, de
->d_name
)) {
936 k
= parent_add_child(enumerator
, child
, MATCH_ALL
& (~(MATCH_SYSNAME
|MATCH_PARENT
)));
941 k
= set_ensure_consume(stack
, &path_hash_ops_free
, TAKE_PTR(child
));
949 static int enumerator_scan_devices_children(sd_device_enumerator
*enumerator
) {
950 _cleanup_set_free_ Set
*stack
= NULL
;
956 SET_FOREACH(path
, enumerator
->match_parent
) {
957 k
= parent_add_child(enumerator
, path
, MATCH_ALL
& (~MATCH_PARENT
));
961 k
= parent_crawl_children(enumerator
, path
, &stack
);
967 _cleanup_free_
char *p
= NULL
;
969 p
= set_steal_first(stack
);
973 k
= parent_crawl_children(enumerator
, p
, &stack
);
979 static int enumerator_scan_devices_all(sd_device_enumerator
*enumerator
) {
982 k
= enumerator_scan_dir(enumerator
, "bus", "devices", NULL
);
984 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan /sys/bus: %m");
986 k
= enumerator_scan_dir(enumerator
, "class", NULL
, NULL
);
988 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan /sys/class: %m");
993 int device_enumerator_scan_devices(sd_device_enumerator
*enumerator
) {
998 if (enumerator
->scan_uptodate
&&
999 enumerator
->type
== DEVICE_ENUMERATION_TYPE_DEVICES
)
1002 device_enumerator_unref_devices(enumerator
);
1004 if (!set_isempty(enumerator
->match_tag
)) {
1005 k
= enumerator_scan_devices_tags(enumerator
);
1008 } else if (enumerator
->match_parent
) {
1009 k
= enumerator_scan_devices_children(enumerator
);
1013 k
= enumerator_scan_devices_all(enumerator
);
1018 enumerator
->scan_uptodate
= true;
1019 enumerator
->type
= DEVICE_ENUMERATION_TYPE_DEVICES
;
1024 _public_ sd_device
*sd_device_enumerator_get_device_first(sd_device_enumerator
*enumerator
) {
1025 assert_return(enumerator
, NULL
);
1027 if (device_enumerator_scan_devices(enumerator
) < 0)
1030 if (enumerator_sort_devices(enumerator
) < 0)
1033 enumerator
->current_device_index
= 0;
1035 if (enumerator
->n_devices
== 0)
1038 return enumerator
->devices
[0];
1041 _public_ sd_device
*sd_device_enumerator_get_device_next(sd_device_enumerator
*enumerator
) {
1042 assert_return(enumerator
, NULL
);
1044 if (!enumerator
->scan_uptodate
||
1045 !enumerator
->sorted
||
1046 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_DEVICES
||
1047 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
1050 return enumerator
->devices
[++enumerator
->current_device_index
];
1053 int device_enumerator_scan_subsystems(sd_device_enumerator
*enumerator
) {
1058 if (enumerator
->scan_uptodate
&&
1059 enumerator
->type
== DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
)
1062 device_enumerator_unref_devices(enumerator
);
1065 if (match_subsystem(enumerator
, "module")) {
1066 k
= enumerator_scan_dir_and_add_devices(enumerator
, "module", NULL
, NULL
);
1068 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan modules: %m");
1071 /* subsystems (only buses support coldplug) */
1072 if (match_subsystem(enumerator
, "subsystem")) {
1073 k
= enumerator_scan_dir_and_add_devices(enumerator
, "bus", NULL
, NULL
);
1075 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan subsystems: %m");
1078 /* subsystem drivers */
1079 if (match_subsystem(enumerator
, "drivers")) {
1080 k
= enumerator_scan_dir(enumerator
, "bus", "drivers", "drivers");
1082 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan drivers: %m");
1085 enumerator
->scan_uptodate
= true;
1086 enumerator
->type
= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
;
1091 _public_ sd_device
*sd_device_enumerator_get_subsystem_first(sd_device_enumerator
*enumerator
) {
1092 assert_return(enumerator
, NULL
);
1094 if (device_enumerator_scan_subsystems(enumerator
) < 0)
1097 if (enumerator_sort_devices(enumerator
) < 0)
1100 enumerator
->current_device_index
= 0;
1102 if (enumerator
->n_devices
== 0)
1105 return enumerator
->devices
[0];
1108 _public_ sd_device
*sd_device_enumerator_get_subsystem_next(sd_device_enumerator
*enumerator
) {
1109 assert_return(enumerator
, NULL
);
1111 if (!enumerator
->scan_uptodate
||
1112 !enumerator
->sorted
||
1113 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
||
1114 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
1117 return enumerator
->devices
[++enumerator
->current_device_index
];
1120 int device_enumerator_scan_devices_and_subsystems(sd_device_enumerator
*enumerator
) {
1125 if (enumerator
->scan_uptodate
&&
1126 enumerator
->type
== DEVICE_ENUMERATION_TYPE_ALL
)
1129 device_enumerator_unref_devices(enumerator
);
1131 if (!set_isempty(enumerator
->match_tag
))
1132 r
= enumerator_scan_devices_tags(enumerator
);
1133 else if (enumerator
->match_parent
)
1134 r
= enumerator_scan_devices_children(enumerator
);
1138 r
= enumerator_scan_devices_all(enumerator
);
1140 if (match_subsystem(enumerator
, "module")) {
1141 k
= enumerator_scan_dir_and_add_devices(enumerator
, "module", NULL
, NULL
);
1143 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan modules: %m");
1145 if (match_subsystem(enumerator
, "subsystem")) {
1146 k
= enumerator_scan_dir_and_add_devices(enumerator
, "bus", NULL
, NULL
);
1148 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan subsystems: %m");
1151 if (match_subsystem(enumerator
, "drivers")) {
1152 k
= enumerator_scan_dir(enumerator
, "bus", "drivers", "drivers");
1154 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan drivers: %m");
1158 enumerator
->scan_uptodate
= true;
1159 enumerator
->type
= DEVICE_ENUMERATION_TYPE_ALL
;
1164 sd_device
*device_enumerator_get_first(sd_device_enumerator
*enumerator
) {
1165 assert_return(enumerator
, NULL
);
1167 if (!enumerator
->scan_uptodate
)
1170 if (enumerator_sort_devices(enumerator
) < 0)
1173 enumerator
->current_device_index
= 0;
1175 if (enumerator
->n_devices
== 0)
1178 return enumerator
->devices
[0];
1181 sd_device
*device_enumerator_get_next(sd_device_enumerator
*enumerator
) {
1182 assert_return(enumerator
, NULL
);
1184 if (!enumerator
->scan_uptodate
||
1185 !enumerator
->sorted
||
1186 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
1189 return enumerator
->devices
[++enumerator
->current_device_index
];
1192 sd_device
**device_enumerator_get_devices(sd_device_enumerator
*enumerator
, size_t *ret_n_devices
) {
1194 assert(ret_n_devices
);
1196 if (!enumerator
->scan_uptodate
)
1199 if (enumerator_sort_devices(enumerator
) < 0)
1202 *ret_n_devices
= enumerator
->n_devices
;
1203 return enumerator
->devices
;