1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include "alloc-util.h"
9 #include "device-enumerator-private.h"
10 #include "device-util.h"
11 #include "dirent-util.h"
14 #include "sort-util.h"
15 #include "string-util.h"
18 #define DEVICE_ENUMERATE_MAX_DEPTH 256
20 typedef enum DeviceEnumerationType
{
21 DEVICE_ENUMERATION_TYPE_DEVICES
,
22 DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
,
23 _DEVICE_ENUMERATION_TYPE_MAX
,
24 _DEVICE_ENUMERATION_TYPE_INVALID
= -1,
25 } DeviceEnumerationType
;
27 struct sd_device_enumerator
{
30 DeviceEnumerationType type
;
32 size_t n_devices
, n_allocated
, current_device_index
;
36 Set
*nomatch_subsystem
;
37 Hashmap
*match_sysattr
;
38 Hashmap
*nomatch_sysattr
;
39 Hashmap
*match_property
;
43 bool match_allow_uninitialized
;
46 _public_
int sd_device_enumerator_new(sd_device_enumerator
**ret
) {
47 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*enumerator
= NULL
;
51 enumerator
= new(sd_device_enumerator
, 1);
55 *enumerator
= (sd_device_enumerator
) {
57 .type
= _DEVICE_ENUMERATION_TYPE_INVALID
,
60 *ret
= TAKE_PTR(enumerator
);
65 static sd_device_enumerator
*device_enumerator_free(sd_device_enumerator
*enumerator
) {
70 for (i
= 0; i
< enumerator
->n_devices
; i
++)
71 sd_device_unref(enumerator
->devices
[i
]);
73 free(enumerator
->devices
);
74 set_free_free(enumerator
->match_subsystem
);
75 set_free_free(enumerator
->nomatch_subsystem
);
76 hashmap_free_free_free(enumerator
->match_sysattr
);
77 hashmap_free_free_free(enumerator
->nomatch_sysattr
);
78 hashmap_free_free_free(enumerator
->match_property
);
79 set_free_free(enumerator
->match_sysname
);
80 set_free_free(enumerator
->match_tag
);
81 set_free_free(enumerator
->match_parent
);
83 return mfree(enumerator
);
86 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device_enumerator
, sd_device_enumerator
, device_enumerator_free
);
88 _public_
int sd_device_enumerator_add_match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
, int match
) {
92 assert_return(enumerator
, -EINVAL
);
93 assert_return(subsystem
, -EINVAL
);
96 set
= &enumerator
->match_subsystem
;
98 set
= &enumerator
->nomatch_subsystem
;
100 r
= set_ensure_allocated(set
, NULL
);
104 r
= set_put_strdup(*set
, subsystem
);
108 enumerator
->scan_uptodate
= false;
113 _public_
int sd_device_enumerator_add_match_sysattr(sd_device_enumerator
*enumerator
, const char *_sysattr
, const char *_value
, int match
) {
114 _cleanup_free_
char *sysattr
= NULL
, *value
= NULL
;
118 assert_return(enumerator
, -EINVAL
);
119 assert_return(_sysattr
, -EINVAL
);
122 hashmap
= &enumerator
->match_sysattr
;
124 hashmap
= &enumerator
->nomatch_sysattr
;
126 r
= hashmap_ensure_allocated(hashmap
, NULL
);
130 sysattr
= strdup(_sysattr
);
135 value
= strdup(_value
);
140 r
= hashmap_put(*hashmap
, sysattr
, value
);
147 enumerator
->scan_uptodate
= false;
152 _public_
int sd_device_enumerator_add_match_property(sd_device_enumerator
*enumerator
, const char *_property
, const char *_value
) {
153 _cleanup_free_
char *property
= NULL
, *value
= NULL
;
156 assert_return(enumerator
, -EINVAL
);
157 assert_return(_property
, -EINVAL
);
159 r
= hashmap_ensure_allocated(&enumerator
->match_property
, NULL
);
163 property
= strdup(_property
);
168 value
= strdup(_value
);
173 r
= hashmap_put(enumerator
->match_property
, property
, value
);
180 enumerator
->scan_uptodate
= false;
185 _public_
int sd_device_enumerator_add_match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
188 assert_return(enumerator
, -EINVAL
);
189 assert_return(sysname
, -EINVAL
);
191 r
= set_ensure_allocated(&enumerator
->match_sysname
, NULL
);
195 r
= set_put_strdup(enumerator
->match_sysname
, sysname
);
199 enumerator
->scan_uptodate
= false;
204 _public_
int sd_device_enumerator_add_match_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
207 assert_return(enumerator
, -EINVAL
);
208 assert_return(tag
, -EINVAL
);
210 r
= set_ensure_allocated(&enumerator
->match_tag
, NULL
);
214 r
= set_put_strdup(enumerator
->match_tag
, tag
);
218 enumerator
->scan_uptodate
= false;
223 static void device_enumerator_clear_match_parent(sd_device_enumerator
*enumerator
) {
227 set_clear_free(enumerator
->match_parent
);
230 int device_enumerator_add_match_parent_incremental(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
234 assert_return(enumerator
, -EINVAL
);
235 assert_return(parent
, -EINVAL
);
237 r
= sd_device_get_syspath(parent
, &path
);
241 r
= set_ensure_allocated(&enumerator
->match_parent
, NULL
);
245 r
= set_put_strdup(enumerator
->match_parent
, path
);
249 enumerator
->scan_uptodate
= false;
254 _public_
int sd_device_enumerator_add_match_parent(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
255 device_enumerator_clear_match_parent(enumerator
);
256 return device_enumerator_add_match_parent_incremental(enumerator
, parent
);
259 _public_
int sd_device_enumerator_allow_uninitialized(sd_device_enumerator
*enumerator
) {
260 assert_return(enumerator
, -EINVAL
);
262 enumerator
->match_allow_uninitialized
= true;
264 enumerator
->scan_uptodate
= false;
269 int device_enumerator_add_match_is_initialized(sd_device_enumerator
*enumerator
) {
270 assert_return(enumerator
, -EINVAL
);
272 enumerator
->match_allow_uninitialized
= false;
274 enumerator
->scan_uptodate
= false;
279 static int device_compare(sd_device
* const *_a
, sd_device
* const *_b
) {
280 sd_device
*a
= *(sd_device
**)_a
, *b
= *(sd_device
**)_b
;
281 const char *devpath_a
, *devpath_b
, *sound_a
;
282 bool delay_a
, delay_b
;
285 assert_se(sd_device_get_devpath(a
, &devpath_a
) >= 0);
286 assert_se(sd_device_get_devpath(b
, &devpath_b
) >= 0);
288 sound_a
= strstr(devpath_a
, "/sound/card");
290 /* For sound cards the control device must be enumerated last to
291 * make sure it's the final device node that gets ACLs applied.
292 * Applications rely on this fact and use ACL changes on the
293 * control node as an indicator that the ACL change of the
294 * entire sound card completed. The kernel makes this guarantee
295 * when creating those devices, and hence we should too when
296 * enumerating them. */
297 sound_a
+= STRLEN("/sound/card");
298 sound_a
= strchr(sound_a
, '/');
303 prefix_len
= sound_a
- devpath_a
;
305 if (strncmp(devpath_a
, devpath_b
, prefix_len
) == 0) {
308 sound_b
= devpath_b
+ prefix_len
;
310 if (startswith(sound_a
, "/controlC") &&
311 !startswith(sound_b
, "/contolC"))
314 if (!startswith(sound_a
, "/controlC") &&
315 startswith(sound_b
, "/controlC"))
321 /* md and dm devices are enumerated after all other devices */
322 delay_a
= strstr(devpath_a
, "/block/md") || strstr(devpath_a
, "/block/dm-");
323 delay_b
= strstr(devpath_b
, "/block/md") || strstr(devpath_b
, "/block/dm-");
324 r
= CMP(delay_a
, delay_b
);
328 return strcmp(devpath_a
, devpath_b
);
331 int device_enumerator_add_device(sd_device_enumerator
*enumerator
, sd_device
*device
) {
332 assert_return(enumerator
, -EINVAL
);
333 assert_return(device
, -EINVAL
);
335 if (!GREEDY_REALLOC(enumerator
->devices
, enumerator
->n_allocated
, enumerator
->n_devices
+ 1))
338 enumerator
->devices
[enumerator
->n_devices
++] = sd_device_ref(device
);
343 static bool match_sysattr_value(sd_device
*device
, const char *sysattr
, const char *match_value
) {
350 r
= sd_device_get_sysattr_value(device
, sysattr
, &value
);
357 if (fnmatch(match_value
, value
, 0) == 0)
363 static bool match_sysattr(sd_device_enumerator
*enumerator
, sd_device
*device
) {
371 HASHMAP_FOREACH_KEY(value
, sysattr
, enumerator
->nomatch_sysattr
, i
)
372 if (match_sysattr_value(device
, sysattr
, value
))
375 HASHMAP_FOREACH_KEY(value
, sysattr
, enumerator
->match_sysattr
, i
)
376 if (!match_sysattr_value(device
, sysattr
, value
))
382 static bool match_property(sd_device_enumerator
*enumerator
, sd_device
*device
) {
383 const char *property
;
390 if (hashmap_isempty(enumerator
->match_property
))
393 HASHMAP_FOREACH_KEY(value
, property
, enumerator
->match_property
, i
) {
394 const char *property_dev
, *value_dev
;
396 FOREACH_DEVICE_PROPERTY(device
, property_dev
, value_dev
) {
397 if (fnmatch(property
, property_dev
, 0) != 0)
400 if (!value
&& !value_dev
)
403 if (!value
|| !value_dev
)
406 if (fnmatch(value
, value_dev
, 0) == 0)
414 static bool match_tag(sd_device_enumerator
*enumerator
, sd_device
*device
) {
421 SET_FOREACH(tag
, enumerator
->match_tag
, i
)
422 if (!sd_device_has_tag(device
, tag
))
428 static bool match_parent(sd_device_enumerator
*enumerator
, sd_device
*device
) {
429 const char *syspath_parent
, *syspath
;
435 if (set_isempty(enumerator
->match_parent
))
438 assert_se(sd_device_get_syspath(device
, &syspath
) >= 0);
440 SET_FOREACH(syspath_parent
, enumerator
->match_parent
, i
)
441 if (path_startswith(syspath
, syspath_parent
))
447 static bool match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
448 const char *sysname_match
;
454 if (set_isempty(enumerator
->match_sysname
))
457 SET_FOREACH(sysname_match
, enumerator
->match_sysname
, i
)
458 if (fnmatch(sysname_match
, sysname
, 0) == 0)
464 static int enumerator_scan_dir_and_add_devices(sd_device_enumerator
*enumerator
, const char *basedir
, const char *subdir1
, const char *subdir2
) {
465 _cleanup_closedir_
DIR *dir
= NULL
;
473 path
= strjoina("/sys/", basedir
, "/");
476 path
= strjoina(path
, subdir1
, "/");
479 path
= strjoina(path
, subdir2
, "/");
485 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
486 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
487 char syspath
[strlen(path
) + 1 + strlen(dent
->d_name
) + 1];
490 if (dent
->d_name
[0] == '.')
493 if (!match_sysname(enumerator
, dent
->d_name
))
496 (void) sprintf(syspath
, "%s%s", path
, dent
->d_name
);
498 k
= sd_device_new_from_syspath(&device
, syspath
);
501 /* this is necessarily racey, so ignore missing devices */
507 initialized
= sd_device_get_is_initialized(device
);
508 if (initialized
< 0) {
514 * All devices with a device node or network interfaces
515 * possibly need udev to adjust the device node permission
516 * or context, or rename the interface before it can be
517 * reliably used from other processes.
519 * For now, we can only check these types of devices, we
520 * might not store a database, and have no way to find out
521 * for all other types of devices.
523 if (!enumerator
->match_allow_uninitialized
&&
525 (sd_device_get_devnum(device
, NULL
) >= 0 ||
526 sd_device_get_ifindex(device
, NULL
) >= 0))
529 if (!match_parent(enumerator
, device
))
532 if (!match_tag(enumerator
, device
))
535 if (!match_property(enumerator
, device
))
538 if (!match_sysattr(enumerator
, device
))
541 k
= device_enumerator_add_device(enumerator
, device
);
549 static bool match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
) {
550 const char *subsystem_match
;
558 SET_FOREACH(subsystem_match
, enumerator
->nomatch_subsystem
, i
)
559 if (fnmatch(subsystem_match
, subsystem
, 0) == 0)
562 if (set_isempty(enumerator
->match_subsystem
))
565 SET_FOREACH(subsystem_match
, enumerator
->match_subsystem
, i
)
566 if (fnmatch(subsystem_match
, subsystem
, 0) == 0)
572 static int enumerator_scan_dir(sd_device_enumerator
*enumerator
, const char *basedir
, const char *subdir
, const char *subsystem
) {
573 _cleanup_closedir_
DIR *dir
= NULL
;
578 path
= strjoina("/sys/", basedir
);
584 log_debug("sd-device-enumerator: Scanning %s", path
);
586 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
589 if (dent
->d_name
[0] == '.')
592 if (!match_subsystem(enumerator
, subsystem
? : dent
->d_name
))
595 k
= enumerator_scan_dir_and_add_devices(enumerator
, basedir
, dent
->d_name
, subdir
);
603 static int enumerator_scan_devices_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
604 _cleanup_closedir_
DIR *dir
= NULL
;
612 path
= strjoina("/run/udev/tags/", tag
);
617 return log_debug_errno(errno
, "sd-device-enumerator: Failed to open tags directory %s: %m", path
);
621 /* TODO: filter away subsystems? */
623 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
624 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
625 const char *subsystem
, *sysname
;
628 if (dent
->d_name
[0] == '.')
631 k
= sd_device_new_from_device_id(&device
, dent
->d_name
);
634 /* this is necessarily racy, so ignore missing devices */
640 k
= sd_device_get_subsystem(device
, &subsystem
);
646 if (!match_subsystem(enumerator
, subsystem
))
649 k
= sd_device_get_sysname(device
, &sysname
);
655 if (!match_sysname(enumerator
, sysname
))
658 if (!match_parent(enumerator
, device
))
661 if (!match_property(enumerator
, device
))
664 if (!match_sysattr(enumerator
, device
))
667 k
= device_enumerator_add_device(enumerator
, device
);
677 static int enumerator_scan_devices_tags(sd_device_enumerator
*enumerator
) {
684 SET_FOREACH(tag
, enumerator
->match_tag
, i
) {
687 k
= enumerator_scan_devices_tag(enumerator
, tag
);
695 static int parent_add_child(sd_device_enumerator
*enumerator
, const char *path
) {
696 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
697 const char *subsystem
, *sysname
;
700 r
= sd_device_new_from_syspath(&device
, path
);
702 /* this is necessarily racy, so ignore missing devices */
707 r
= sd_device_get_subsystem(device
, &subsystem
);
713 if (!match_subsystem(enumerator
, subsystem
))
716 r
= sd_device_get_sysname(device
, &sysname
);
720 if (!match_sysname(enumerator
, sysname
))
723 if (!match_property(enumerator
, device
))
726 if (!match_sysattr(enumerator
, device
))
729 r
= device_enumerator_add_device(enumerator
, device
);
736 static int parent_crawl_children(sd_device_enumerator
*enumerator
, const char *path
, unsigned maxdepth
) {
737 _cleanup_closedir_
DIR *dir
= NULL
;
743 return log_debug_errno(errno
, "sd-device-enumerator: Failed to open parent directory %s: %m", path
);
745 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
746 _cleanup_free_
char *child
= NULL
;
749 if (dent
->d_name
[0] == '.')
752 if (dent
->d_type
!= DT_DIR
)
755 child
= strjoin(path
, "/", dent
->d_name
);
759 k
= parent_add_child(enumerator
, child
);
764 parent_crawl_children(enumerator
, child
, maxdepth
- 1);
766 log_debug("sd-device-enumerator: Max depth reached, %s: ignoring devices", child
);
772 static int enumerator_scan_devices_children(sd_device_enumerator
*enumerator
) {
777 SET_FOREACH(path
, enumerator
->match_parent
, i
) {
778 k
= parent_add_child(enumerator
, path
);
782 k
= parent_crawl_children(enumerator
, path
, DEVICE_ENUMERATE_MAX_DEPTH
);
790 static int enumerator_scan_devices_all(sd_device_enumerator
*enumerator
) {
793 log_debug("sd-device-enumerator: Scan all dirs");
795 if (access("/sys/subsystem", F_OK
) >= 0) {
796 /* we have /subsystem/, forget all the old stuff */
797 r
= enumerator_scan_dir(enumerator
, "subsystem", "devices", NULL
);
799 return log_debug_errno(r
, "sd-device-enumerator: Failed to scan /sys/subsystem: %m");
803 k
= enumerator_scan_dir(enumerator
, "bus", "devices", NULL
);
805 log_debug_errno(k
, "sd-device-enumerator: Failed to scan /sys/bus: %m");
809 k
= enumerator_scan_dir(enumerator
, "class", NULL
, NULL
);
811 log_debug_errno(k
, "sd-device-enumerator: Failed to scan /sys/class: %m");
819 static void device_enumerator_dedup_devices(sd_device_enumerator
*enumerator
) {
820 sd_device
**a
, **b
, **end
;
824 if (enumerator
->n_devices
<= 1)
827 a
= enumerator
->devices
+ 1;
828 b
= enumerator
->devices
;
829 end
= enumerator
->devices
+ enumerator
->n_devices
;
831 for (; a
< end
; a
++) {
832 const char *devpath_a
, *devpath_b
;
834 assert_se(sd_device_get_devpath(*a
, &devpath_a
) >= 0);
835 assert_se(sd_device_get_devpath(*b
, &devpath_b
) >= 0);
837 if (path_equal(devpath_a
, devpath_b
))
843 enumerator
->n_devices
= b
- enumerator
->devices
+ 1;
846 int device_enumerator_scan_devices(sd_device_enumerator
*enumerator
) {
852 if (enumerator
->scan_uptodate
&&
853 enumerator
->type
== DEVICE_ENUMERATION_TYPE_DEVICES
)
856 for (i
= 0; i
< enumerator
->n_devices
; i
++)
857 sd_device_unref(enumerator
->devices
[i
]);
859 enumerator
->n_devices
= 0;
861 if (!set_isempty(enumerator
->match_tag
)) {
862 k
= enumerator_scan_devices_tags(enumerator
);
865 } else if (enumerator
->match_parent
) {
866 k
= enumerator_scan_devices_children(enumerator
);
870 k
= enumerator_scan_devices_all(enumerator
);
875 typesafe_qsort(enumerator
->devices
, enumerator
->n_devices
, device_compare
);
876 device_enumerator_dedup_devices(enumerator
);
878 enumerator
->scan_uptodate
= true;
879 enumerator
->type
= DEVICE_ENUMERATION_TYPE_DEVICES
;
884 _public_ sd_device
*sd_device_enumerator_get_device_first(sd_device_enumerator
*enumerator
) {
887 assert_return(enumerator
, NULL
);
889 r
= device_enumerator_scan_devices(enumerator
);
893 enumerator
->current_device_index
= 0;
895 if (enumerator
->n_devices
== 0)
898 return enumerator
->devices
[0];
901 _public_ sd_device
*sd_device_enumerator_get_device_next(sd_device_enumerator
*enumerator
) {
902 assert_return(enumerator
, NULL
);
904 if (!enumerator
->scan_uptodate
||
905 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_DEVICES
||
906 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
909 return enumerator
->devices
[++enumerator
->current_device_index
];
912 int device_enumerator_scan_subsystems(sd_device_enumerator
*enumerator
) {
913 const char *subsysdir
;
919 if (enumerator
->scan_uptodate
&&
920 enumerator
->type
== DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
)
923 for (i
= 0; i
< enumerator
->n_devices
; i
++)
924 sd_device_unref(enumerator
->devices
[i
]);
926 enumerator
->n_devices
= 0;
929 if (match_subsystem(enumerator
, "module")) {
930 k
= enumerator_scan_dir_and_add_devices(enumerator
, "module", NULL
, NULL
);
932 log_debug_errno(k
, "sd-device-enumerator: Failed to scan modules: %m");
937 if (access("/sys/subsystem", F_OK
) >= 0)
938 subsysdir
= "subsystem";
942 /* subsystems (only buses support coldplug) */
943 if (match_subsystem(enumerator
, "subsystem")) {
944 k
= enumerator_scan_dir_and_add_devices(enumerator
, subsysdir
, NULL
, NULL
);
946 log_debug_errno(k
, "sd-device-enumerator: Failed to scan subsystems: %m");
951 /* subsystem drivers */
952 if (match_subsystem(enumerator
, "drivers")) {
953 k
= enumerator_scan_dir(enumerator
, subsysdir
, "drivers", "drivers");
955 log_debug_errno(k
, "sd-device-enumerator: Failed to scan drivers: %m");
960 typesafe_qsort(enumerator
->devices
, enumerator
->n_devices
, device_compare
);
961 device_enumerator_dedup_devices(enumerator
);
963 enumerator
->scan_uptodate
= true;
964 enumerator
->type
= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
;
969 _public_ sd_device
*sd_device_enumerator_get_subsystem_first(sd_device_enumerator
*enumerator
) {
972 assert_return(enumerator
, NULL
);
974 r
= device_enumerator_scan_subsystems(enumerator
);
978 enumerator
->current_device_index
= 0;
980 if (enumerator
->n_devices
== 0)
983 return enumerator
->devices
[0];
986 _public_ sd_device
*sd_device_enumerator_get_subsystem_next(sd_device_enumerator
*enumerator
) {
987 assert_return(enumerator
, NULL
);
989 if (!enumerator
->scan_uptodate
||
990 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
||
991 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
994 return enumerator
->devices
[++enumerator
->current_device_index
];
997 sd_device
*device_enumerator_get_first(sd_device_enumerator
*enumerator
) {
998 assert_return(enumerator
, NULL
);
1000 if (!enumerator
->scan_uptodate
)
1003 enumerator
->current_device_index
= 0;
1005 if (enumerator
->n_devices
== 0)
1008 return enumerator
->devices
[0];
1011 sd_device
*device_enumerator_get_next(sd_device_enumerator
*enumerator
) {
1012 assert_return(enumerator
, NULL
);
1014 if (!enumerator
->scan_uptodate
||
1015 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
1018 return enumerator
->devices
[++enumerator
->current_device_index
];
1021 sd_device
**device_enumerator_get_devices(sd_device_enumerator
*enumerator
, size_t *ret_n_devices
) {
1023 assert(ret_n_devices
);
1025 if (!enumerator
->scan_uptodate
)
1028 *ret_n_devices
= enumerator
->n_devices
;
1029 return enumerator
->devices
;