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
;
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 set_free_free(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 static void device_enumerator_clear_match_parent(sd_device_enumerator
*enumerator
) {
224 set_clear_free(enumerator
->match_parent
);
227 int device_enumerator_add_match_parent_incremental(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
231 assert_return(enumerator
, -EINVAL
);
232 assert_return(parent
, -EINVAL
);
234 r
= sd_device_get_syspath(parent
, &path
);
238 r
= set_ensure_allocated(&enumerator
->match_parent
, NULL
);
242 r
= set_put_strdup(enumerator
->match_parent
, path
);
246 enumerator
->scan_uptodate
= false;
251 _public_
int sd_device_enumerator_add_match_parent(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
252 device_enumerator_clear_match_parent(enumerator
);
253 return device_enumerator_add_match_parent_incremental(enumerator
, parent
);
256 _public_
int sd_device_enumerator_allow_uninitialized(sd_device_enumerator
*enumerator
) {
257 assert_return(enumerator
, -EINVAL
);
259 enumerator
->match_allow_uninitialized
= true;
261 enumerator
->scan_uptodate
= false;
266 int device_enumerator_add_match_is_initialized(sd_device_enumerator
*enumerator
) {
267 assert_return(enumerator
, -EINVAL
);
269 enumerator
->match_allow_uninitialized
= false;
271 enumerator
->scan_uptodate
= false;
276 static int device_compare(sd_device
* const *_a
, sd_device
* const *_b
) {
277 sd_device
*a
= *(sd_device
**)_a
, *b
= *(sd_device
**)_b
;
278 const char *devpath_a
, *devpath_b
, *sound_a
;
279 bool delay_a
, delay_b
;
282 assert_se(sd_device_get_devpath(a
, &devpath_a
) >= 0);
283 assert_se(sd_device_get_devpath(b
, &devpath_b
) >= 0);
285 sound_a
= strstr(devpath_a
, "/sound/card");
287 /* For sound cards the control device must be enumerated last to
288 * make sure it's the final device node that gets ACLs applied.
289 * Applications rely on this fact and use ACL changes on the
290 * control node as an indicator that the ACL change of the
291 * entire sound card completed. The kernel makes this guarantee
292 * when creating those devices, and hence we should too when
293 * enumerating them. */
294 sound_a
+= STRLEN("/sound/card");
295 sound_a
= strchr(sound_a
, '/');
300 prefix_len
= sound_a
- devpath_a
;
302 if (strncmp(devpath_a
, devpath_b
, prefix_len
) == 0) {
305 sound_b
= devpath_b
+ prefix_len
;
307 if (startswith(sound_a
, "/controlC") &&
308 !startswith(sound_b
, "/contolC"))
311 if (!startswith(sound_a
, "/controlC") &&
312 startswith(sound_b
, "/controlC"))
318 /* md and dm devices are enumerated after all other devices */
319 delay_a
= strstr(devpath_a
, "/block/md") || strstr(devpath_a
, "/block/dm-");
320 delay_b
= strstr(devpath_b
, "/block/md") || strstr(devpath_b
, "/block/dm-");
321 r
= CMP(delay_a
, delay_b
);
325 return strcmp(devpath_a
, devpath_b
);
328 int device_enumerator_add_device(sd_device_enumerator
*enumerator
, sd_device
*device
) {
329 assert_return(enumerator
, -EINVAL
);
330 assert_return(device
, -EINVAL
);
332 if (!GREEDY_REALLOC(enumerator
->devices
, enumerator
->n_allocated
, enumerator
->n_devices
+ 1))
335 enumerator
->devices
[enumerator
->n_devices
++] = sd_device_ref(device
);
340 static bool match_sysattr_value(sd_device
*device
, const char *sysattr
, const char *match_value
) {
347 r
= sd_device_get_sysattr_value(device
, sysattr
, &value
);
354 if (fnmatch(match_value
, value
, 0) == 0)
360 static bool match_sysattr(sd_device_enumerator
*enumerator
, sd_device
*device
) {
368 HASHMAP_FOREACH_KEY(value
, sysattr
, enumerator
->nomatch_sysattr
, i
)
369 if (match_sysattr_value(device
, sysattr
, value
))
372 HASHMAP_FOREACH_KEY(value
, sysattr
, enumerator
->match_sysattr
, i
)
373 if (!match_sysattr_value(device
, sysattr
, value
))
379 static bool match_property(sd_device_enumerator
*enumerator
, sd_device
*device
) {
380 const char *property
;
387 if (hashmap_isempty(enumerator
->match_property
))
390 HASHMAP_FOREACH_KEY(value
, property
, enumerator
->match_property
, i
) {
391 const char *property_dev
, *value_dev
;
393 FOREACH_DEVICE_PROPERTY(device
, property_dev
, value_dev
) {
394 if (fnmatch(property
, property_dev
, 0) != 0)
397 if (!value
&& !value_dev
)
400 if (!value
|| !value_dev
)
403 if (fnmatch(value
, value_dev
, 0) == 0)
411 static bool match_tag(sd_device_enumerator
*enumerator
, sd_device
*device
) {
418 SET_FOREACH(tag
, enumerator
->match_tag
, i
)
419 if (!sd_device_has_tag(device
, tag
))
425 static bool match_parent(sd_device_enumerator
*enumerator
, sd_device
*device
) {
426 const char *syspath_parent
, *syspath
;
433 if (set_isempty(enumerator
->match_parent
))
436 r
= sd_device_get_syspath(device
, &syspath
);
439 SET_FOREACH(syspath_parent
, enumerator
->match_parent
, i
)
440 if (path_startswith(syspath
, syspath_parent
))
446 static bool match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
447 const char *sysname_match
;
453 if (set_isempty(enumerator
->match_sysname
))
456 SET_FOREACH(sysname_match
, enumerator
->match_sysname
, i
)
457 if (fnmatch(sysname_match
, sysname
, 0) == 0)
463 static int enumerator_scan_dir_and_add_devices(sd_device_enumerator
*enumerator
, const char *basedir
, const char *subdir1
, const char *subdir2
) {
464 _cleanup_closedir_
DIR *dir
= NULL
;
472 path
= strjoina("/sys/", basedir
, "/");
475 path
= strjoina(path
, subdir1
, "/");
478 path
= strjoina(path
, subdir2
, "/");
484 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
485 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
486 char syspath
[strlen(path
) + 1 + strlen(dent
->d_name
) + 1];
489 if (dent
->d_name
[0] == '.')
492 if (!match_sysname(enumerator
, dent
->d_name
))
495 (void) sprintf(syspath
, "%s%s", path
, dent
->d_name
);
497 k
= sd_device_new_from_syspath(&device
, syspath
);
500 /* this is necessarily racey, so ignore missing devices */
506 initialized
= sd_device_get_is_initialized(device
);
507 if (initialized
< 0) {
513 * All devices with a device node or network interfaces
514 * possibly need udev to adjust the device node permission
515 * or context, or rename the interface before it can be
516 * reliably used from other processes.
518 * For now, we can only check these types of devices, we
519 * might not store a database, and have no way to find out
520 * for all other types of devices.
522 if (!enumerator
->match_allow_uninitialized
&&
524 (sd_device_get_devnum(device
, NULL
) >= 0 ||
525 sd_device_get_ifindex(device
, NULL
) >= 0))
528 if (!match_parent(enumerator
, device
))
531 if (!match_tag(enumerator
, device
))
534 if (!match_property(enumerator
, device
))
537 if (!match_sysattr(enumerator
, device
))
540 k
= device_enumerator_add_device(enumerator
, device
);
548 static bool match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
) {
549 const char *subsystem_match
;
557 SET_FOREACH(subsystem_match
, enumerator
->nomatch_subsystem
, i
)
558 if (fnmatch(subsystem_match
, subsystem
, 0) == 0)
561 if (set_isempty(enumerator
->match_subsystem
))
564 SET_FOREACH(subsystem_match
, enumerator
->match_subsystem
, i
)
565 if (fnmatch(subsystem_match
, subsystem
, 0) == 0)
571 static int enumerator_scan_dir(sd_device_enumerator
*enumerator
, const char *basedir
, const char *subdir
, const char *subsystem
) {
572 _cleanup_closedir_
DIR *dir
= NULL
;
577 path
= strjoina("/sys/", basedir
);
583 log_debug("sd-device-enumerator: Scanning %s", path
);
585 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
588 if (dent
->d_name
[0] == '.')
591 if (!match_subsystem(enumerator
, subsystem
? : dent
->d_name
))
594 k
= enumerator_scan_dir_and_add_devices(enumerator
, basedir
, dent
->d_name
, subdir
);
602 static int enumerator_scan_devices_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
603 _cleanup_closedir_
DIR *dir
= NULL
;
611 path
= strjoina("/run/udev/tags/", tag
);
616 return log_debug_errno(errno
, "sd-device-enumerator: Failed to open tags directory %s: %m", path
);
620 /* TODO: filter away subsystems? */
622 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
623 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
624 const char *subsystem
, *sysname
;
627 if (dent
->d_name
[0] == '.')
630 k
= sd_device_new_from_device_id(&device
, dent
->d_name
);
633 /* this is necessarily racy, so ignore missing devices */
639 k
= sd_device_get_subsystem(device
, &subsystem
);
645 if (!match_subsystem(enumerator
, subsystem
))
648 k
= sd_device_get_sysname(device
, &sysname
);
654 if (!match_sysname(enumerator
, sysname
))
657 if (!match_parent(enumerator
, device
))
660 if (!match_property(enumerator
, device
))
663 if (!match_sysattr(enumerator
, device
))
666 k
= device_enumerator_add_device(enumerator
, device
);
676 static int enumerator_scan_devices_tags(sd_device_enumerator
*enumerator
) {
683 SET_FOREACH(tag
, enumerator
->match_tag
, i
) {
686 k
= enumerator_scan_devices_tag(enumerator
, tag
);
694 static int parent_add_child(sd_device_enumerator
*enumerator
, const char *path
) {
695 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
696 const char *subsystem
, *sysname
;
699 r
= sd_device_new_from_syspath(&device
, path
);
701 /* this is necessarily racy, so ignore missing devices */
706 r
= sd_device_get_subsystem(device
, &subsystem
);
712 if (!match_subsystem(enumerator
, subsystem
))
715 r
= sd_device_get_sysname(device
, &sysname
);
719 if (!match_sysname(enumerator
, sysname
))
722 if (!match_property(enumerator
, device
))
725 if (!match_sysattr(enumerator
, device
))
728 r
= device_enumerator_add_device(enumerator
, device
);
735 static int parent_crawl_children(sd_device_enumerator
*enumerator
, const char *path
, unsigned maxdepth
) {
736 _cleanup_closedir_
DIR *dir
= NULL
;
742 return log_debug_errno(errno
, "sd-device-enumerator: Failed to open parent directory %s: %m", path
);
744 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
745 _cleanup_free_
char *child
= NULL
;
748 if (dent
->d_name
[0] == '.')
751 if (dent
->d_type
!= DT_DIR
)
754 child
= strjoin(path
, "/", dent
->d_name
);
758 k
= parent_add_child(enumerator
, child
);
763 parent_crawl_children(enumerator
, child
, maxdepth
- 1);
765 log_debug("sd-device-enumerator: Max depth reached, %s: ignoring devices", child
);
771 static int enumerator_scan_devices_children(sd_device_enumerator
*enumerator
) {
776 SET_FOREACH(path
, enumerator
->match_parent
, i
) {
777 k
= parent_add_child(enumerator
, path
);
781 k
= parent_crawl_children(enumerator
, path
, DEVICE_ENUMERATE_MAX_DEPTH
);
789 static int enumerator_scan_devices_all(sd_device_enumerator
*enumerator
) {
792 log_debug("sd-device-enumerator: Scan all dirs");
794 if (access("/sys/subsystem", F_OK
) >= 0) {
795 /* we have /subsystem/, forget all the old stuff */
796 r
= enumerator_scan_dir(enumerator
, "subsystem", "devices", NULL
);
798 return log_debug_errno(r
, "sd-device-enumerator: Failed to scan /sys/subsystem: %m");
802 k
= enumerator_scan_dir(enumerator
, "bus", "devices", NULL
);
804 log_debug_errno(k
, "sd-device-enumerator: Failed to scan /sys/bus: %m");
808 k
= enumerator_scan_dir(enumerator
, "class", NULL
, NULL
);
810 log_debug_errno(k
, "sd-device-enumerator: Failed to scan /sys/class: %m");
818 static void device_enumerator_dedup_devices(sd_device_enumerator
*enumerator
) {
819 sd_device
**a
, **b
, **end
;
823 if (enumerator
->n_devices
<= 1)
826 a
= enumerator
->devices
+ 1;
827 b
= enumerator
->devices
;
828 end
= enumerator
->devices
+ enumerator
->n_devices
;
830 for (; a
< end
; a
++) {
831 const char *devpath_a
, *devpath_b
;
833 assert_se(sd_device_get_devpath(*a
, &devpath_a
) >= 0);
834 assert_se(sd_device_get_devpath(*b
, &devpath_b
) >= 0);
836 if (path_equal(devpath_a
, devpath_b
))
842 enumerator
->n_devices
= b
- enumerator
->devices
+ 1;
845 int device_enumerator_scan_devices(sd_device_enumerator
*enumerator
) {
851 if (enumerator
->scan_uptodate
&&
852 enumerator
->type
== DEVICE_ENUMERATION_TYPE_DEVICES
)
855 for (i
= 0; i
< enumerator
->n_devices
; i
++)
856 sd_device_unref(enumerator
->devices
[i
]);
858 enumerator
->n_devices
= 0;
860 if (!set_isempty(enumerator
->match_tag
)) {
861 k
= enumerator_scan_devices_tags(enumerator
);
864 } else if (enumerator
->match_parent
) {
865 k
= enumerator_scan_devices_children(enumerator
);
869 k
= enumerator_scan_devices_all(enumerator
);
874 typesafe_qsort(enumerator
->devices
, enumerator
->n_devices
, device_compare
);
875 device_enumerator_dedup_devices(enumerator
);
877 enumerator
->scan_uptodate
= true;
878 enumerator
->type
= DEVICE_ENUMERATION_TYPE_DEVICES
;
883 _public_ sd_device
*sd_device_enumerator_get_device_first(sd_device_enumerator
*enumerator
) {
886 assert_return(enumerator
, NULL
);
888 r
= device_enumerator_scan_devices(enumerator
);
892 enumerator
->current_device_index
= 0;
894 if (enumerator
->n_devices
== 0)
897 return enumerator
->devices
[0];
900 _public_ sd_device
*sd_device_enumerator_get_device_next(sd_device_enumerator
*enumerator
) {
901 assert_return(enumerator
, NULL
);
903 if (!enumerator
->scan_uptodate
||
904 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_DEVICES
||
905 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
908 return enumerator
->devices
[++enumerator
->current_device_index
];
911 int device_enumerator_scan_subsystems(sd_device_enumerator
*enumerator
) {
912 const char *subsysdir
;
918 if (enumerator
->scan_uptodate
&&
919 enumerator
->type
== DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
)
922 for (i
= 0; i
< enumerator
->n_devices
; i
++)
923 sd_device_unref(enumerator
->devices
[i
]);
925 enumerator
->n_devices
= 0;
928 if (match_subsystem(enumerator
, "module")) {
929 k
= enumerator_scan_dir_and_add_devices(enumerator
, "module", NULL
, NULL
);
931 log_debug_errno(k
, "sd-device-enumerator: Failed to scan modules: %m");
936 if (access("/sys/subsystem", F_OK
) >= 0)
937 subsysdir
= "subsystem";
941 /* subsystems (only buses support coldplug) */
942 if (match_subsystem(enumerator
, "subsystem")) {
943 k
= enumerator_scan_dir_and_add_devices(enumerator
, subsysdir
, NULL
, NULL
);
945 log_debug_errno(k
, "sd-device-enumerator: Failed to scan subsystems: %m");
950 /* subsystem drivers */
951 if (match_subsystem(enumerator
, "drivers")) {
952 k
= enumerator_scan_dir(enumerator
, subsysdir
, "drivers", "drivers");
954 log_debug_errno(k
, "sd-device-enumerator: Failed to scan drivers: %m");
959 typesafe_qsort(enumerator
->devices
, enumerator
->n_devices
, device_compare
);
960 device_enumerator_dedup_devices(enumerator
);
962 enumerator
->scan_uptodate
= true;
963 enumerator
->type
= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
;
968 _public_ sd_device
*sd_device_enumerator_get_subsystem_first(sd_device_enumerator
*enumerator
) {
971 assert_return(enumerator
, NULL
);
973 r
= device_enumerator_scan_subsystems(enumerator
);
977 enumerator
->current_device_index
= 0;
979 if (enumerator
->n_devices
== 0)
982 return enumerator
->devices
[0];
985 _public_ sd_device
*sd_device_enumerator_get_subsystem_next(sd_device_enumerator
*enumerator
) {
986 assert_return(enumerator
, NULL
);
988 if (!enumerator
->scan_uptodate
||
989 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
||
990 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
993 return enumerator
->devices
[++enumerator
->current_device_index
];
996 sd_device
*device_enumerator_get_first(sd_device_enumerator
*enumerator
) {
997 assert_return(enumerator
, NULL
);
999 if (!enumerator
->scan_uptodate
)
1002 enumerator
->current_device_index
= 0;
1004 if (enumerator
->n_devices
== 0)
1007 return enumerator
->devices
[0];
1010 sd_device
*device_enumerator_get_next(sd_device_enumerator
*enumerator
) {
1011 assert_return(enumerator
, NULL
);
1013 if (!enumerator
->scan_uptodate
||
1014 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
1017 return enumerator
->devices
[++enumerator
->current_device_index
];
1020 sd_device
**device_enumerator_get_devices(sd_device_enumerator
*enumerator
, size_t *ret_n_devices
) {
1022 assert(ret_n_devices
);
1024 if (!enumerator
->scan_uptodate
)
1027 *ret_n_devices
= enumerator
->n_devices
;
1028 return enumerator
->devices
;