1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 #include "alloc-util.h"
6 #include "device-enumerator-private.h"
7 #include "device-util.h"
8 #include "dirent-util.h"
11 #include "string-util.h"
15 #define DEVICE_ENUMERATE_MAX_DEPTH 256
17 typedef enum DeviceEnumerationType
{
18 DEVICE_ENUMERATION_TYPE_DEVICES
,
19 DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
,
20 _DEVICE_ENUMERATION_TYPE_MAX
,
21 _DEVICE_ENUMERATION_TYPE_INVALID
= -1,
22 } DeviceEnumerationType
;
24 struct sd_device_enumerator
{
27 DeviceEnumerationType type
;
29 size_t n_devices
, n_allocated
, current_device_index
;
33 Set
*nomatch_subsystem
;
34 Hashmap
*match_sysattr
;
35 Hashmap
*nomatch_sysattr
;
36 Hashmap
*match_property
;
39 sd_device
*match_parent
;
40 bool match_allow_uninitialized
;
43 _public_
int sd_device_enumerator_new(sd_device_enumerator
**ret
) {
44 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*enumerator
= NULL
;
48 enumerator
= new(sd_device_enumerator
, 1);
52 *enumerator
= (sd_device_enumerator
) {
54 .type
= _DEVICE_ENUMERATION_TYPE_INVALID
,
57 *ret
= TAKE_PTR(enumerator
);
62 static sd_device_enumerator
*device_enumerator_free(sd_device_enumerator
*enumerator
) {
67 for (i
= 0; i
< enumerator
->n_devices
; i
++)
68 sd_device_unref(enumerator
->devices
[i
]);
70 free(enumerator
->devices
);
71 set_free_free(enumerator
->match_subsystem
);
72 set_free_free(enumerator
->nomatch_subsystem
);
73 hashmap_free_free_free(enumerator
->match_sysattr
);
74 hashmap_free_free_free(enumerator
->nomatch_sysattr
);
75 hashmap_free_free_free(enumerator
->match_property
);
76 set_free_free(enumerator
->match_sysname
);
77 set_free_free(enumerator
->match_tag
);
78 sd_device_unref(enumerator
->match_parent
);
80 return mfree(enumerator
);
83 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device_enumerator
, sd_device_enumerator
, device_enumerator_free
);
85 _public_
int sd_device_enumerator_add_match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
, int match
) {
89 assert_return(enumerator
, -EINVAL
);
90 assert_return(subsystem
, -EINVAL
);
93 set
= &enumerator
->match_subsystem
;
95 set
= &enumerator
->nomatch_subsystem
;
97 r
= set_ensure_allocated(set
, NULL
);
101 r
= set_put_strdup(*set
, subsystem
);
105 enumerator
->scan_uptodate
= false;
110 _public_
int sd_device_enumerator_add_match_sysattr(sd_device_enumerator
*enumerator
, const char *_sysattr
, const char *_value
, int match
) {
111 _cleanup_free_
char *sysattr
= NULL
, *value
= NULL
;
115 assert_return(enumerator
, -EINVAL
);
116 assert_return(_sysattr
, -EINVAL
);
119 hashmap
= &enumerator
->match_sysattr
;
121 hashmap
= &enumerator
->nomatch_sysattr
;
123 r
= hashmap_ensure_allocated(hashmap
, NULL
);
127 sysattr
= strdup(_sysattr
);
132 value
= strdup(_value
);
137 r
= hashmap_put(*hashmap
, sysattr
, value
);
144 enumerator
->scan_uptodate
= false;
149 _public_
int sd_device_enumerator_add_match_property(sd_device_enumerator
*enumerator
, const char *_property
, const char *_value
) {
150 _cleanup_free_
char *property
= NULL
, *value
= NULL
;
153 assert_return(enumerator
, -EINVAL
);
154 assert_return(_property
, -EINVAL
);
156 r
= hashmap_ensure_allocated(&enumerator
->match_property
, NULL
);
160 property
= strdup(_property
);
165 value
= strdup(_value
);
170 r
= hashmap_put(enumerator
->match_property
, property
, value
);
177 enumerator
->scan_uptodate
= false;
182 _public_
int sd_device_enumerator_add_match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
185 assert_return(enumerator
, -EINVAL
);
186 assert_return(sysname
, -EINVAL
);
188 r
= set_ensure_allocated(&enumerator
->match_sysname
, NULL
);
192 r
= set_put_strdup(enumerator
->match_sysname
, sysname
);
196 enumerator
->scan_uptodate
= false;
201 _public_
int sd_device_enumerator_add_match_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
204 assert_return(enumerator
, -EINVAL
);
205 assert_return(tag
, -EINVAL
);
207 r
= set_ensure_allocated(&enumerator
->match_tag
, NULL
);
211 r
= set_put_strdup(enumerator
->match_tag
, tag
);
215 enumerator
->scan_uptodate
= false;
220 _public_
int sd_device_enumerator_add_match_parent(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
221 assert_return(enumerator
, -EINVAL
);
222 assert_return(parent
, -EINVAL
);
224 sd_device_unref(enumerator
->match_parent
);
225 enumerator
->match_parent
= sd_device_ref(parent
);
227 enumerator
->scan_uptodate
= false;
232 _public_
int sd_device_enumerator_allow_uninitialized(sd_device_enumerator
*enumerator
) {
233 assert_return(enumerator
, -EINVAL
);
235 enumerator
->match_allow_uninitialized
= true;
237 enumerator
->scan_uptodate
= false;
242 int device_enumerator_add_match_is_initialized(sd_device_enumerator
*enumerator
) {
243 assert_return(enumerator
, -EINVAL
);
245 enumerator
->match_allow_uninitialized
= false;
247 enumerator
->scan_uptodate
= false;
252 static int device_compare(sd_device
* const *_a
, sd_device
* const *_b
) {
253 sd_device
*a
= *(sd_device
**)_a
, *b
= *(sd_device
**)_b
;
254 const char *devpath_a
, *devpath_b
, *sound_a
;
255 bool delay_a
, delay_b
;
258 assert_se(sd_device_get_devpath(a
, &devpath_a
) >= 0);
259 assert_se(sd_device_get_devpath(b
, &devpath_b
) >= 0);
261 sound_a
= strstr(devpath_a
, "/sound/card");
263 /* For sound cards the control device must be enumerated last to
264 * make sure it's the final device node that gets ACLs applied.
265 * Applications rely on this fact and use ACL changes on the
266 * control node as an indicator that the ACL change of the
267 * entire sound card completed. The kernel makes this guarantee
268 * when creating those devices, and hence we should too when
269 * enumerating them. */
270 sound_a
+= STRLEN("/sound/card");
271 sound_a
= strchr(sound_a
, '/');
276 prefix_len
= sound_a
- devpath_a
;
278 if (strncmp(devpath_a
, devpath_b
, prefix_len
) == 0) {
281 sound_b
= devpath_b
+ prefix_len
;
283 if (startswith(sound_a
, "/controlC") &&
284 !startswith(sound_b
, "/contolC"))
287 if (!startswith(sound_a
, "/controlC") &&
288 startswith(sound_b
, "/controlC"))
294 /* md and dm devices are enumerated after all other devices */
295 delay_a
= strstr(devpath_a
, "/block/md") || strstr(devpath_a
, "/block/dm-");
296 delay_b
= strstr(devpath_b
, "/block/md") || strstr(devpath_b
, "/block/dm-");
297 r
= CMP(delay_a
, delay_b
);
301 return strcmp(devpath_a
, devpath_b
);
304 int device_enumerator_add_device(sd_device_enumerator
*enumerator
, sd_device
*device
) {
305 assert_return(enumerator
, -EINVAL
);
306 assert_return(device
, -EINVAL
);
308 if (!GREEDY_REALLOC(enumerator
->devices
, enumerator
->n_allocated
, enumerator
->n_devices
+ 1))
311 enumerator
->devices
[enumerator
->n_devices
++] = sd_device_ref(device
);
316 static bool match_sysattr_value(sd_device
*device
, const char *sysattr
, const char *match_value
) {
323 r
= sd_device_get_sysattr_value(device
, sysattr
, &value
);
330 if (fnmatch(match_value
, value
, 0) == 0)
336 static bool match_sysattr(sd_device_enumerator
*enumerator
, sd_device
*device
) {
344 HASHMAP_FOREACH_KEY(value
, sysattr
, enumerator
->nomatch_sysattr
, i
)
345 if (match_sysattr_value(device
, sysattr
, value
))
348 HASHMAP_FOREACH_KEY(value
, sysattr
, enumerator
->match_sysattr
, i
)
349 if (!match_sysattr_value(device
, sysattr
, value
))
355 static bool match_property(sd_device_enumerator
*enumerator
, sd_device
*device
) {
356 const char *property
;
363 if (hashmap_isempty(enumerator
->match_property
))
366 HASHMAP_FOREACH_KEY(value
, property
, enumerator
->match_property
, i
) {
367 const char *property_dev
, *value_dev
;
369 FOREACH_DEVICE_PROPERTY(device
, property_dev
, value_dev
) {
370 if (fnmatch(property
, property_dev
, 0) != 0)
373 if (!value
&& !value_dev
)
376 if (!value
|| !value_dev
)
379 if (fnmatch(value
, value_dev
, 0) == 0)
387 static bool match_tag(sd_device_enumerator
*enumerator
, sd_device
*device
) {
394 SET_FOREACH(tag
, enumerator
->match_tag
, i
)
395 if (!sd_device_has_tag(device
, tag
))
401 static bool match_parent(sd_device_enumerator
*enumerator
, sd_device
*device
) {
402 const char *devpath
, *devpath_dev
;
408 if (!enumerator
->match_parent
)
411 r
= sd_device_get_devpath(enumerator
->match_parent
, &devpath
);
414 r
= sd_device_get_devpath(device
, &devpath_dev
);
417 return startswith(devpath_dev
, devpath
);
420 static bool match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
421 const char *sysname_match
;
427 if (set_isempty(enumerator
->match_sysname
))
430 SET_FOREACH(sysname_match
, enumerator
->match_sysname
, i
)
431 if (fnmatch(sysname_match
, sysname
, 0) == 0)
437 static int enumerator_scan_dir_and_add_devices(sd_device_enumerator
*enumerator
, const char *basedir
, const char *subdir1
, const char *subdir2
) {
438 _cleanup_closedir_
DIR *dir
= NULL
;
446 path
= strjoina("/sys/", basedir
, "/");
449 path
= strjoina(path
, subdir1
, "/");
452 path
= strjoina(path
, subdir2
, "/");
458 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
459 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
460 char syspath
[strlen(path
) + 1 + strlen(dent
->d_name
) + 1];
462 int ifindex
, initialized
, k
;
464 if (dent
->d_name
[0] == '.')
467 if (!match_sysname(enumerator
, dent
->d_name
))
470 (void) sprintf(syspath
, "%s%s", path
, dent
->d_name
);
472 k
= sd_device_new_from_syspath(&device
, syspath
);
475 /* this is necessarily racey, so ignore missing devices */
481 k
= sd_device_get_is_initialized(device
, &initialized
);
488 * All devices with a device node or network interfaces
489 * possibly need udev to adjust the device node permission
490 * or context, or rename the interface before it can be
491 * reliably used from other processes.
493 * For now, we can only check these types of devices, we
494 * might not store a database, and have no way to find out
495 * for all other types of devices.
497 if (!enumerator
->match_allow_uninitialized
&&
499 (sd_device_get_devnum(device
, &devnum
) >= 0 ||
500 sd_device_get_ifindex(device
, &ifindex
) >= 0))
503 if (!match_parent(enumerator
, device
))
506 if (!match_tag(enumerator
, device
))
509 if (!match_property(enumerator
, device
))
512 if (!match_sysattr(enumerator
, device
))
515 k
= device_enumerator_add_device(enumerator
, device
);
523 static bool match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
) {
524 const char *subsystem_match
;
532 SET_FOREACH(subsystem_match
, enumerator
->nomatch_subsystem
, i
)
533 if (fnmatch(subsystem_match
, subsystem
, 0) == 0)
536 if (set_isempty(enumerator
->match_subsystem
))
539 SET_FOREACH(subsystem_match
, enumerator
->match_subsystem
, i
)
540 if (fnmatch(subsystem_match
, subsystem
, 0) == 0)
546 static int enumerator_scan_dir(sd_device_enumerator
*enumerator
, const char *basedir
, const char *subdir
, const char *subsystem
) {
547 _cleanup_closedir_
DIR *dir
= NULL
;
552 path
= strjoina("/sys/", basedir
);
558 log_debug(" device-enumerator: scanning %s", path
);
560 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
563 if (dent
->d_name
[0] == '.')
566 if (!match_subsystem(enumerator
, subsystem
? : dent
->d_name
))
569 k
= enumerator_scan_dir_and_add_devices(enumerator
, basedir
, dent
->d_name
, subdir
);
577 static int enumerator_scan_devices_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
578 _cleanup_closedir_
DIR *dir
= NULL
;
586 path
= strjoina("/run/udev/tags/", tag
);
593 return log_error_errno(errno
, "sd-device-enumerator: could not open tags directory %s: %m", path
);
596 /* TODO: filter away subsystems? */
598 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
599 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
600 const char *subsystem
, *sysname
;
603 if (dent
->d_name
[0] == '.')
606 k
= sd_device_new_from_device_id(&device
, dent
->d_name
);
609 /* this is necessarily racy, so ignore missing devices */
615 k
= sd_device_get_subsystem(device
, &subsystem
);
621 if (!match_subsystem(enumerator
, subsystem
))
624 k
= sd_device_get_sysname(device
, &sysname
);
630 if (!match_sysname(enumerator
, sysname
))
633 if (!match_parent(enumerator
, device
))
636 if (!match_property(enumerator
, device
))
639 if (!match_sysattr(enumerator
, device
))
642 k
= device_enumerator_add_device(enumerator
, device
);
652 static int enumerator_scan_devices_tags(sd_device_enumerator
*enumerator
) {
659 SET_FOREACH(tag
, enumerator
->match_tag
, i
) {
662 k
= enumerator_scan_devices_tag(enumerator
, tag
);
670 static int parent_add_child(sd_device_enumerator
*enumerator
, const char *path
) {
671 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
672 const char *subsystem
, *sysname
;
675 r
= sd_device_new_from_syspath(&device
, path
);
677 /* this is necessarily racy, so ignore missing devices */
682 r
= sd_device_get_subsystem(device
, &subsystem
);
688 if (!match_subsystem(enumerator
, subsystem
))
691 r
= sd_device_get_sysname(device
, &sysname
);
695 if (!match_sysname(enumerator
, sysname
))
698 if (!match_property(enumerator
, device
))
701 if (!match_sysattr(enumerator
, device
))
704 r
= device_enumerator_add_device(enumerator
, device
);
711 static int parent_crawl_children(sd_device_enumerator
*enumerator
, const char *path
, unsigned maxdepth
) {
712 _cleanup_closedir_
DIR *dir
= NULL
;
718 return log_debug_errno(errno
, "sd-device-enumerate: could not open parent directory %s: %m", path
);
720 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
721 _cleanup_free_
char *child
= NULL
;
724 if (dent
->d_name
[0] == '.')
727 if (dent
->d_type
!= DT_DIR
)
730 child
= strjoin(path
, "/", dent
->d_name
);
734 k
= parent_add_child(enumerator
, child
);
739 parent_crawl_children(enumerator
, child
, maxdepth
- 1);
741 log_debug("device-enumerate: max depth reached, %s: ignoring devices", child
);
747 static int enumerator_scan_devices_children(sd_device_enumerator
*enumerator
) {
751 r
= sd_device_get_syspath(enumerator
->match_parent
, &path
);
755 k
= parent_add_child(enumerator
, path
);
759 k
= parent_crawl_children(enumerator
, path
, DEVICE_ENUMERATE_MAX_DEPTH
);
766 static int enumerator_scan_devices_all(sd_device_enumerator
*enumerator
) {
769 log_debug("device-enumerator: scan all dirs");
771 if (access("/sys/subsystem", F_OK
) >= 0) {
772 /* we have /subsystem/, forget all the old stuff */
773 r
= enumerator_scan_dir(enumerator
, "subsystem", "devices", NULL
);
775 return log_debug_errno(r
, "device-enumerator: failed to scan /sys/subsystem: %m");
779 k
= enumerator_scan_dir(enumerator
, "bus", "devices", NULL
);
781 log_debug_errno(k
, "device-enumerator: failed to scan /sys/bus: %m");
785 k
= enumerator_scan_dir(enumerator
, "class", NULL
, NULL
);
787 log_debug_errno(k
, "device-enumerator: failed to scan /sys/class: %m");
795 static void device_enumerator_dedup_devices(sd_device_enumerator
*enumerator
) {
796 sd_device
**a
, **b
, **end
;
800 if (enumerator
->n_devices
<= 1)
803 a
= enumerator
->devices
+ 1;
804 b
= enumerator
->devices
;
805 end
= enumerator
->devices
+ enumerator
->n_devices
;
807 for (; a
< end
; a
++) {
808 const char *devpath_a
, *devpath_b
;
810 assert_se(sd_device_get_devpath(*a
, &devpath_a
) >= 0);
811 assert_se(sd_device_get_devpath(*b
, &devpath_b
) >= 0);
813 if (path_equal(devpath_a
, devpath_b
))
819 enumerator
->n_devices
= b
- enumerator
->devices
+ 1;
822 int device_enumerator_scan_devices(sd_device_enumerator
*enumerator
) {
828 if (enumerator
->scan_uptodate
&&
829 enumerator
->type
== DEVICE_ENUMERATION_TYPE_DEVICES
)
832 for (i
= 0; i
< enumerator
->n_devices
; i
++)
833 sd_device_unref(enumerator
->devices
[i
]);
835 enumerator
->n_devices
= 0;
837 if (!set_isempty(enumerator
->match_tag
)) {
838 k
= enumerator_scan_devices_tags(enumerator
);
841 } else if (enumerator
->match_parent
) {
842 k
= enumerator_scan_devices_children(enumerator
);
846 k
= enumerator_scan_devices_all(enumerator
);
851 typesafe_qsort(enumerator
->devices
, enumerator
->n_devices
, device_compare
);
852 device_enumerator_dedup_devices(enumerator
);
854 enumerator
->scan_uptodate
= true;
855 enumerator
->type
= DEVICE_ENUMERATION_TYPE_DEVICES
;
860 _public_ sd_device
*sd_device_enumerator_get_device_first(sd_device_enumerator
*enumerator
) {
863 assert_return(enumerator
, NULL
);
865 r
= device_enumerator_scan_devices(enumerator
);
869 enumerator
->current_device_index
= 0;
871 if (enumerator
->n_devices
== 0)
874 return enumerator
->devices
[0];
877 _public_ sd_device
*sd_device_enumerator_get_device_next(sd_device_enumerator
*enumerator
) {
878 assert_return(enumerator
, NULL
);
880 if (!enumerator
->scan_uptodate
||
881 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_DEVICES
||
882 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
885 return enumerator
->devices
[++enumerator
->current_device_index
];
888 int device_enumerator_scan_subsystems(sd_device_enumerator
*enumerator
) {
889 const char *subsysdir
;
895 if (enumerator
->scan_uptodate
&&
896 enumerator
->type
== DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
)
899 for (i
= 0; i
< enumerator
->n_devices
; i
++)
900 sd_device_unref(enumerator
->devices
[i
]);
902 enumerator
->n_devices
= 0;
905 if (match_subsystem(enumerator
, "module")) {
906 k
= enumerator_scan_dir_and_add_devices(enumerator
, "module", NULL
, NULL
);
908 log_debug_errno(k
, "device-enumerator: failed to scan modules: %m");
913 if (access("/sys/subsystem", F_OK
) >= 0)
914 subsysdir
= "subsystem";
918 /* subsystems (only buses support coldplug) */
919 if (match_subsystem(enumerator
, "subsystem")) {
920 k
= enumerator_scan_dir_and_add_devices(enumerator
, subsysdir
, NULL
, NULL
);
922 log_debug_errno(k
, "device-enumerator: failed to scan subsystems: %m");
927 /* subsystem drivers */
928 if (match_subsystem(enumerator
, "drivers")) {
929 k
= enumerator_scan_dir(enumerator
, subsysdir
, "drivers", "drivers");
931 log_debug_errno(k
, "device-enumerator: failed to scan drivers: %m");
936 typesafe_qsort(enumerator
->devices
, enumerator
->n_devices
, device_compare
);
937 device_enumerator_dedup_devices(enumerator
);
939 enumerator
->scan_uptodate
= true;
940 enumerator
->type
= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
;
945 _public_ sd_device
*sd_device_enumerator_get_subsystem_first(sd_device_enumerator
*enumerator
) {
948 assert_return(enumerator
, NULL
);
950 r
= device_enumerator_scan_subsystems(enumerator
);
954 enumerator
->current_device_index
= 0;
956 if (enumerator
->n_devices
== 0)
959 return enumerator
->devices
[0];
962 _public_ sd_device
*sd_device_enumerator_get_subsystem_next(sd_device_enumerator
*enumerator
) {
963 assert_return(enumerator
, NULL
);
965 if (!enumerator
->scan_uptodate
||
966 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
||
967 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
970 return enumerator
->devices
[++enumerator
->current_device_index
];
973 sd_device
*device_enumerator_get_first(sd_device_enumerator
*enumerator
) {
974 assert_return(enumerator
, NULL
);
976 if (!enumerator
->scan_uptodate
)
979 enumerator
->current_device_index
= 0;
981 if (enumerator
->n_devices
== 0)
984 return enumerator
->devices
[0];
987 sd_device
*device_enumerator_get_next(sd_device_enumerator
*enumerator
) {
988 assert_return(enumerator
, NULL
);
990 if (!enumerator
->scan_uptodate
||
991 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
994 return enumerator
->devices
[++enumerator
->current_device_index
];
997 sd_device
**device_enumerator_get_devices(sd_device_enumerator
*enumerator
, size_t *ret_n_devices
) {
999 assert(ret_n_devices
);
1001 if (!enumerator
->scan_uptodate
)
1004 *ret_n_devices
= enumerator
->n_devices
;
1005 return enumerator
->devices
;