1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
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
= -EINVAL
,
25 } DeviceEnumerationType
;
27 struct sd_device_enumerator
{
30 DeviceEnumerationType type
;
32 size_t n_devices
, 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
) {
68 for (size_t i
= 0; i
< enumerator
->n_devices
; i
++)
69 sd_device_unref(enumerator
->devices
[i
]);
71 free(enumerator
->devices
);
72 set_free(enumerator
->match_subsystem
);
73 set_free(enumerator
->nomatch_subsystem
);
74 hashmap_free(enumerator
->match_sysattr
);
75 hashmap_free(enumerator
->nomatch_sysattr
);
76 hashmap_free(enumerator
->match_property
);
77 set_free(enumerator
->match_sysname
);
78 set_free(enumerator
->match_tag
);
79 set_free(enumerator
->match_parent
);
81 return mfree(enumerator
);
84 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_device_enumerator
, sd_device_enumerator
, device_enumerator_free
);
86 _public_
int sd_device_enumerator_add_match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
, int match
) {
90 assert_return(enumerator
, -EINVAL
);
91 assert_return(subsystem
, -EINVAL
);
94 set
= &enumerator
->match_subsystem
;
96 set
= &enumerator
->nomatch_subsystem
;
98 r
= set_put_strdup(set
, subsystem
);
102 enumerator
->scan_uptodate
= false;
107 _public_
int sd_device_enumerator_add_match_sysattr(sd_device_enumerator
*enumerator
, const char *sysattr
, const char *value
, int match
) {
111 assert_return(enumerator
, -EINVAL
);
112 assert_return(sysattr
, -EINVAL
);
115 hashmap
= &enumerator
->match_sysattr
;
117 hashmap
= &enumerator
->nomatch_sysattr
;
119 /* Do not use string_has_ops_free_free or hashmap_put_strdup() here, as this may be called
120 * multiple times with the same sysattr but different value. */
121 r
= hashmap_put_strdup_full(hashmap
, &trivial_hash_ops_free_free
, sysattr
, value
);
125 enumerator
->scan_uptodate
= false;
130 _public_
int sd_device_enumerator_add_match_property(sd_device_enumerator
*enumerator
, const char *property
, const char *value
) {
133 assert_return(enumerator
, -EINVAL
);
134 assert_return(property
, -EINVAL
);
136 /* Do not use string_has_ops_free_free or hashmap_put_strdup() here, as this may be called
137 * multiple times with the same property but different value. */
138 r
= hashmap_put_strdup_full(&enumerator
->match_property
, &trivial_hash_ops_free_free
, property
, value
);
142 enumerator
->scan_uptodate
= false;
147 _public_
int sd_device_enumerator_add_match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
150 assert_return(enumerator
, -EINVAL
);
151 assert_return(sysname
, -EINVAL
);
153 r
= set_put_strdup(&enumerator
->match_sysname
, sysname
);
157 enumerator
->scan_uptodate
= false;
162 _public_
int sd_device_enumerator_add_match_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
165 assert_return(enumerator
, -EINVAL
);
166 assert_return(tag
, -EINVAL
);
168 r
= set_put_strdup(&enumerator
->match_tag
, tag
);
172 enumerator
->scan_uptodate
= false;
177 int device_enumerator_add_match_parent_incremental(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
184 r
= sd_device_get_syspath(parent
, &path
);
188 r
= set_put_strdup(&enumerator
->match_parent
, path
);
192 enumerator
->scan_uptodate
= false;
197 _public_
int sd_device_enumerator_add_match_parent(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
198 assert_return(enumerator
, -EINVAL
);
199 assert_return(parent
, -EINVAL
);
201 set_clear(enumerator
->match_parent
);
203 return device_enumerator_add_match_parent_incremental(enumerator
, parent
);
206 _public_
int sd_device_enumerator_allow_uninitialized(sd_device_enumerator
*enumerator
) {
207 assert_return(enumerator
, -EINVAL
);
209 enumerator
->match_allow_uninitialized
= true;
211 enumerator
->scan_uptodate
= false;
216 int device_enumerator_add_match_is_initialized(sd_device_enumerator
*enumerator
) {
217 assert_return(enumerator
, -EINVAL
);
219 enumerator
->match_allow_uninitialized
= false;
221 enumerator
->scan_uptodate
= false;
226 static int device_compare(sd_device
* const *_a
, sd_device
* const *_b
) {
227 sd_device
*a
= *(sd_device
**)_a
, *b
= *(sd_device
**)_b
;
228 const char *devpath_a
, *devpath_b
, *sound_a
;
229 bool delay_a
, delay_b
;
232 assert_se(sd_device_get_devpath(a
, &devpath_a
) >= 0);
233 assert_se(sd_device_get_devpath(b
, &devpath_b
) >= 0);
235 sound_a
= strstr(devpath_a
, "/sound/card");
237 /* For sound cards the control device must be enumerated last to
238 * make sure it's the final device node that gets ACLs applied.
239 * Applications rely on this fact and use ACL changes on the
240 * control node as an indicator that the ACL change of the
241 * entire sound card completed. The kernel makes this guarantee
242 * when creating those devices, and hence we should too when
243 * enumerating them. */
244 sound_a
+= STRLEN("/sound/card");
245 sound_a
= strchr(sound_a
, '/');
250 prefix_len
= sound_a
- devpath_a
;
252 if (strneq(devpath_a
, devpath_b
, prefix_len
)) {
255 sound_b
= devpath_b
+ prefix_len
;
257 r
= CMP(!!startswith(sound_a
, "/controlC"),
258 !!startswith(sound_b
, "/controlC"));
265 /* md and dm devices are enumerated after all other devices */
266 delay_a
= strstr(devpath_a
, "/block/md") || strstr(devpath_a
, "/block/dm-");
267 delay_b
= strstr(devpath_b
, "/block/md") || strstr(devpath_b
, "/block/dm-");
268 r
= CMP(delay_a
, delay_b
);
272 return strcmp(devpath_a
, devpath_b
);
275 int device_enumerator_add_device(sd_device_enumerator
*enumerator
, sd_device
*device
) {
276 assert_return(enumerator
, -EINVAL
);
277 assert_return(device
, -EINVAL
);
279 if (!GREEDY_REALLOC(enumerator
->devices
, enumerator
->n_devices
+ 1))
282 enumerator
->devices
[enumerator
->n_devices
++] = sd_device_ref(device
);
287 static bool match_property(sd_device_enumerator
*enumerator
, sd_device
*device
) {
288 const char *property
;
294 if (hashmap_isempty(enumerator
->match_property
))
297 HASHMAP_FOREACH_KEY(value
, property
, enumerator
->match_property
) {
298 const char *property_dev
, *value_dev
;
300 FOREACH_DEVICE_PROPERTY(device
, property_dev
, value_dev
) {
301 if (fnmatch(property
, property_dev
, 0) != 0)
304 if (!value
&& !value_dev
)
307 if (!value
|| !value_dev
)
310 if (fnmatch(value
, value_dev
, 0) == 0)
318 static bool match_tag(sd_device_enumerator
*enumerator
, sd_device
*device
) {
324 SET_FOREACH(tag
, enumerator
->match_tag
)
325 if (!sd_device_has_tag(device
, tag
))
331 static bool match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
332 const char *sysname_match
;
337 if (set_isempty(enumerator
->match_sysname
))
340 SET_FOREACH(sysname_match
, enumerator
->match_sysname
)
341 if (fnmatch(sysname_match
, sysname
, 0) == 0)
347 static int enumerator_scan_dir_and_add_devices(sd_device_enumerator
*enumerator
, const char *basedir
, const char *subdir1
, const char *subdir2
) {
348 _cleanup_closedir_
DIR *dir
= NULL
;
355 path
= strjoina("/sys/", basedir
, "/");
358 path
= strjoina(path
, subdir1
, "/");
361 path
= strjoina(path
, subdir2
, "/");
365 /* this is necessarily racey, so ignore missing directories */
366 return (errno
== ENOENT
&& (subdir1
|| subdir2
)) ? 0 : -errno
;
368 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
369 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
370 char syspath
[strlen(path
) + 1 + strlen(de
->d_name
) + 1];
373 if (de
->d_name
[0] == '.')
376 if (!match_sysname(enumerator
, de
->d_name
))
379 (void) sprintf(syspath
, "%s%s", path
, de
->d_name
);
381 k
= sd_device_new_from_syspath(&device
, syspath
);
384 /* this is necessarily racey, so ignore missing devices */
390 initialized
= sd_device_get_is_initialized(device
);
391 if (initialized
< 0) {
392 if (initialized
!= -ENOENT
)
393 /* this is necessarily racey, so ignore missing devices */
400 * All devices with a device node or network interfaces
401 * possibly need udev to adjust the device node permission
402 * or context, or rename the interface before it can be
403 * reliably used from other processes.
405 * For now, we can only check these types of devices, we
406 * might not store a database, and have no way to find out
407 * for all other types of devices.
409 if (!enumerator
->match_allow_uninitialized
&&
411 (sd_device_get_devnum(device
, NULL
) >= 0 ||
412 sd_device_get_ifindex(device
, NULL
) >= 0))
415 if (!device_match_parent(device
, enumerator
->match_parent
, NULL
))
418 if (!match_tag(enumerator
, device
))
421 if (!match_property(enumerator
, device
))
424 if (!device_match_sysattr(device
, enumerator
->match_sysattr
, enumerator
->nomatch_sysattr
))
427 k
= device_enumerator_add_device(enumerator
, device
);
435 static bool match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
) {
436 const char *subsystem_match
;
443 SET_FOREACH(subsystem_match
, enumerator
->nomatch_subsystem
)
444 if (fnmatch(subsystem_match
, subsystem
, 0) == 0)
447 if (set_isempty(enumerator
->match_subsystem
))
450 SET_FOREACH(subsystem_match
, enumerator
->match_subsystem
)
451 if (fnmatch(subsystem_match
, subsystem
, 0) == 0)
457 static int enumerator_scan_dir(sd_device_enumerator
*enumerator
, const char *basedir
, const char *subdir
, const char *subsystem
) {
458 _cleanup_closedir_
DIR *dir
= NULL
;
462 path
= strjoina("/sys/", basedir
);
468 log_debug("sd-device-enumerator: Scanning %s", path
);
470 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
473 if (de
->d_name
[0] == '.')
476 if (!match_subsystem(enumerator
, subsystem
? : de
->d_name
))
479 k
= enumerator_scan_dir_and_add_devices(enumerator
, basedir
, de
->d_name
, subdir
);
487 static int enumerator_scan_devices_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
488 _cleanup_closedir_
DIR *dir
= NULL
;
495 path
= strjoina("/run/udev/tags/", tag
);
500 return log_debug_errno(errno
, "sd-device-enumerator: Failed to open tags directory %s: %m", path
);
504 /* TODO: filter away subsystems? */
506 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
507 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
508 const char *subsystem
, *sysname
;
511 if (de
->d_name
[0] == '.')
514 k
= sd_device_new_from_device_id(&device
, de
->d_name
);
517 /* this is necessarily racy, so ignore missing devices */
523 k
= sd_device_get_subsystem(device
, &subsystem
);
526 /* this is necessarily racy, so ignore missing devices */
531 if (!match_subsystem(enumerator
, subsystem
))
534 k
= sd_device_get_sysname(device
, &sysname
);
540 if (!match_sysname(enumerator
, sysname
))
543 if (!device_match_parent(device
, enumerator
->match_parent
, NULL
))
546 if (!match_property(enumerator
, device
))
549 if (!device_match_sysattr(device
, enumerator
->match_sysattr
, enumerator
->nomatch_sysattr
))
552 k
= device_enumerator_add_device(enumerator
, device
);
562 static int enumerator_scan_devices_tags(sd_device_enumerator
*enumerator
) {
568 SET_FOREACH(tag
, enumerator
->match_tag
) {
571 k
= enumerator_scan_devices_tag(enumerator
, tag
);
579 static int parent_add_child(sd_device_enumerator
*enumerator
, const char *path
) {
580 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
581 const char *subsystem
, *sysname
;
584 r
= sd_device_new_from_syspath(&device
, path
);
586 /* this is necessarily racy, so ignore missing devices */
591 r
= sd_device_get_subsystem(device
, &subsystem
);
597 if (!match_subsystem(enumerator
, subsystem
))
600 r
= sd_device_get_sysname(device
, &sysname
);
604 if (!match_sysname(enumerator
, sysname
))
607 if (!match_property(enumerator
, device
))
610 if (!device_match_sysattr(device
, enumerator
->match_sysattr
, enumerator
->nomatch_sysattr
))
613 r
= device_enumerator_add_device(enumerator
, device
);
620 static int parent_crawl_children(sd_device_enumerator
*enumerator
, const char *path
, unsigned maxdepth
) {
621 _cleanup_closedir_
DIR *dir
= NULL
;
626 return log_debug_errno(errno
, "sd-device-enumerator: Failed to open parent directory %s: %m", path
);
628 FOREACH_DIRENT_ALL(de
, dir
, return -errno
) {
629 _cleanup_free_
char *child
= NULL
;
632 if (de
->d_name
[0] == '.')
635 if (de
->d_type
!= DT_DIR
)
638 child
= path_join(path
, de
->d_name
);
642 k
= parent_add_child(enumerator
, child
);
647 parent_crawl_children(enumerator
, child
, maxdepth
- 1);
649 log_debug("sd-device-enumerator: Max depth reached, %s: ignoring devices", child
);
655 static int enumerator_scan_devices_children(sd_device_enumerator
*enumerator
) {
659 SET_FOREACH(path
, enumerator
->match_parent
) {
660 k
= parent_add_child(enumerator
, path
);
664 k
= parent_crawl_children(enumerator
, path
, DEVICE_ENUMERATE_MAX_DEPTH
);
672 static int enumerator_scan_devices_all(sd_device_enumerator
*enumerator
) {
675 log_debug("sd-device-enumerator: Scan all dirs");
677 if (access("/sys/subsystem", F_OK
) >= 0) {
678 /* we have /subsystem/, forget all the old stuff */
679 r
= enumerator_scan_dir(enumerator
, "subsystem", "devices", NULL
);
681 return log_debug_errno(r
, "sd-device-enumerator: Failed to scan /sys/subsystem: %m");
685 k
= enumerator_scan_dir(enumerator
, "bus", "devices", NULL
);
687 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan /sys/bus: %m");
689 k
= enumerator_scan_dir(enumerator
, "class", NULL
, NULL
);
691 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan /sys/class: %m");
697 static void device_enumerator_dedup_devices(sd_device_enumerator
*enumerator
) {
698 sd_device
**a
, **b
, **end
;
702 if (enumerator
->n_devices
<= 1)
705 a
= enumerator
->devices
+ 1;
706 b
= enumerator
->devices
;
707 end
= enumerator
->devices
+ enumerator
->n_devices
;
709 for (; a
< end
; a
++) {
710 const char *devpath_a
, *devpath_b
;
712 assert_se(sd_device_get_devpath(*a
, &devpath_a
) >= 0);
713 assert_se(sd_device_get_devpath(*b
, &devpath_b
) >= 0);
715 if (path_equal(devpath_a
, devpath_b
))
721 enumerator
->n_devices
= b
- enumerator
->devices
+ 1;
724 int device_enumerator_scan_devices(sd_device_enumerator
*enumerator
) {
729 if (enumerator
->scan_uptodate
&&
730 enumerator
->type
== DEVICE_ENUMERATION_TYPE_DEVICES
)
733 for (size_t i
= 0; i
< enumerator
->n_devices
; i
++)
734 sd_device_unref(enumerator
->devices
[i
]);
736 enumerator
->n_devices
= 0;
738 if (!set_isempty(enumerator
->match_tag
)) {
739 k
= enumerator_scan_devices_tags(enumerator
);
742 } else if (enumerator
->match_parent
) {
743 k
= enumerator_scan_devices_children(enumerator
);
747 k
= enumerator_scan_devices_all(enumerator
);
752 typesafe_qsort(enumerator
->devices
, enumerator
->n_devices
, device_compare
);
753 device_enumerator_dedup_devices(enumerator
);
755 enumerator
->scan_uptodate
= true;
756 enumerator
->type
= DEVICE_ENUMERATION_TYPE_DEVICES
;
761 _public_ sd_device
*sd_device_enumerator_get_device_first(sd_device_enumerator
*enumerator
) {
764 assert_return(enumerator
, NULL
);
766 r
= device_enumerator_scan_devices(enumerator
);
770 enumerator
->current_device_index
= 0;
772 if (enumerator
->n_devices
== 0)
775 return enumerator
->devices
[0];
778 _public_ sd_device
*sd_device_enumerator_get_device_next(sd_device_enumerator
*enumerator
) {
779 assert_return(enumerator
, NULL
);
781 if (!enumerator
->scan_uptodate
||
782 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_DEVICES
||
783 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
786 return enumerator
->devices
[++enumerator
->current_device_index
];
789 int device_enumerator_scan_subsystems(sd_device_enumerator
*enumerator
) {
790 const char *subsysdir
;
795 if (enumerator
->scan_uptodate
&&
796 enumerator
->type
== DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
)
799 for (size_t i
= 0; i
< enumerator
->n_devices
; i
++)
800 sd_device_unref(enumerator
->devices
[i
]);
802 enumerator
->n_devices
= 0;
805 if (match_subsystem(enumerator
, "module")) {
806 k
= enumerator_scan_dir_and_add_devices(enumerator
, "module", NULL
, NULL
);
808 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan modules: %m");
811 if (access("/sys/subsystem", F_OK
) >= 0)
812 subsysdir
= "subsystem";
816 /* subsystems (only buses support coldplug) */
817 if (match_subsystem(enumerator
, "subsystem")) {
818 k
= enumerator_scan_dir_and_add_devices(enumerator
, subsysdir
, NULL
, NULL
);
820 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan subsystems: %m");
823 /* subsystem drivers */
824 if (match_subsystem(enumerator
, "drivers")) {
825 k
= enumerator_scan_dir(enumerator
, subsysdir
, "drivers", "drivers");
827 r
= log_debug_errno(k
, "sd-device-enumerator: Failed to scan drivers: %m");
830 typesafe_qsort(enumerator
->devices
, enumerator
->n_devices
, device_compare
);
831 device_enumerator_dedup_devices(enumerator
);
833 enumerator
->scan_uptodate
= true;
834 enumerator
->type
= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
;
839 _public_ sd_device
*sd_device_enumerator_get_subsystem_first(sd_device_enumerator
*enumerator
) {
842 assert_return(enumerator
, NULL
);
844 r
= device_enumerator_scan_subsystems(enumerator
);
848 enumerator
->current_device_index
= 0;
850 if (enumerator
->n_devices
== 0)
853 return enumerator
->devices
[0];
856 _public_ sd_device
*sd_device_enumerator_get_subsystem_next(sd_device_enumerator
*enumerator
) {
857 assert_return(enumerator
, NULL
);
859 if (!enumerator
->scan_uptodate
||
860 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
||
861 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
864 return enumerator
->devices
[++enumerator
->current_device_index
];
867 sd_device
*device_enumerator_get_first(sd_device_enumerator
*enumerator
) {
868 assert_return(enumerator
, NULL
);
870 if (!enumerator
->scan_uptodate
)
873 enumerator
->current_device_index
= 0;
875 if (enumerator
->n_devices
== 0)
878 return enumerator
->devices
[0];
881 sd_device
*device_enumerator_get_next(sd_device_enumerator
*enumerator
) {
882 assert_return(enumerator
, NULL
);
884 if (!enumerator
->scan_uptodate
||
885 enumerator
->current_device_index
+ 1 >= enumerator
->n_devices
)
888 return enumerator
->devices
[++enumerator
->current_device_index
];
891 sd_device
**device_enumerator_get_devices(sd_device_enumerator
*enumerator
, size_t *ret_n_devices
) {
893 assert(ret_n_devices
);
895 if (!enumerator
->scan_uptodate
)
898 *ret_n_devices
= enumerator
->n_devices
;
899 return enumerator
->devices
;