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"
12 #include "string-util.h"
16 #define DEVICE_ENUMERATE_MAX_DEPTH 256
18 typedef enum DeviceEnumerationType
{
19 DEVICE_ENUMERATION_TYPE_DEVICES
,
20 DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
,
21 _DEVICE_ENUMERATION_TYPE_MAX
,
22 _DEVICE_ENUMERATION_TYPE_INVALID
= -1,
23 } DeviceEnumerationType
;
25 struct sd_device_enumerator
{
28 DeviceEnumerationType type
;
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
= new0(sd_device_enumerator
, 1);
52 enumerator
->n_ref
= 1;
53 enumerator
->type
= _DEVICE_ENUMERATION_TYPE_INVALID
;
55 *ret
= TAKE_PTR(enumerator
);
60 _public_ sd_device_enumerator
*sd_device_enumerator_ref(sd_device_enumerator
*enumerator
) {
61 assert_return(enumerator
, NULL
);
63 assert_se((++ enumerator
->n_ref
) >= 2);
68 _public_ sd_device_enumerator
*sd_device_enumerator_unref(sd_device_enumerator
*enumerator
) {
69 if (enumerator
&& (-- enumerator
->n_ref
) == 0) {
72 while ((device
= prioq_pop(enumerator
->devices
)))
73 sd_device_unref(device
);
75 prioq_free(enumerator
->devices
);
77 set_free_free(enumerator
->match_subsystem
);
78 set_free_free(enumerator
->nomatch_subsystem
);
79 hashmap_free_free_free(enumerator
->match_sysattr
);
80 hashmap_free_free_free(enumerator
->nomatch_sysattr
);
81 hashmap_free_free_free(enumerator
->match_property
);
82 set_free_free(enumerator
->match_sysname
);
83 set_free_free(enumerator
->match_tag
);
84 sd_device_unref(enumerator
->match_parent
);
92 _public_
int sd_device_enumerator_add_match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
, int match
) {
96 assert_return(enumerator
, -EINVAL
);
97 assert_return(subsystem
, -EINVAL
);
100 set
= &enumerator
->match_subsystem
;
102 set
= &enumerator
->nomatch_subsystem
;
104 r
= set_ensure_allocated(set
, NULL
);
108 r
= set_put_strdup(*set
, subsystem
);
112 enumerator
->scan_uptodate
= false;
117 _public_
int sd_device_enumerator_add_match_sysattr(sd_device_enumerator
*enumerator
, const char *_sysattr
, const char *_value
, int match
) {
118 _cleanup_free_
char *sysattr
= NULL
, *value
= NULL
;
122 assert_return(enumerator
, -EINVAL
);
123 assert_return(_sysattr
, -EINVAL
);
126 hashmap
= &enumerator
->match_sysattr
;
128 hashmap
= &enumerator
->nomatch_sysattr
;
130 r
= hashmap_ensure_allocated(hashmap
, NULL
);
134 sysattr
= strdup(_sysattr
);
139 value
= strdup(_value
);
144 r
= hashmap_put(*hashmap
, sysattr
, value
);
151 enumerator
->scan_uptodate
= false;
156 _public_
int sd_device_enumerator_add_match_property(sd_device_enumerator
*enumerator
, const char *_property
, const char *_value
) {
157 _cleanup_free_
char *property
= NULL
, *value
= NULL
;
160 assert_return(enumerator
, -EINVAL
);
161 assert_return(_property
, -EINVAL
);
163 r
= hashmap_ensure_allocated(&enumerator
->match_property
, NULL
);
167 property
= strdup(_property
);
172 value
= strdup(_value
);
177 r
= hashmap_put(enumerator
->match_property
, property
, value
);
184 enumerator
->scan_uptodate
= false;
189 _public_
int sd_device_enumerator_add_match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
192 assert_return(enumerator
, -EINVAL
);
193 assert_return(sysname
, -EINVAL
);
195 r
= set_ensure_allocated(&enumerator
->match_sysname
, NULL
);
199 r
= set_put_strdup(enumerator
->match_sysname
, sysname
);
203 enumerator
->scan_uptodate
= false;
208 _public_
int sd_device_enumerator_add_match_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
211 assert_return(enumerator
, -EINVAL
);
212 assert_return(tag
, -EINVAL
);
214 r
= set_ensure_allocated(&enumerator
->match_tag
, NULL
);
218 r
= set_put_strdup(enumerator
->match_tag
, tag
);
222 enumerator
->scan_uptodate
= false;
227 _public_
int sd_device_enumerator_add_match_parent(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
228 assert_return(enumerator
, -EINVAL
);
229 assert_return(parent
, -EINVAL
);
231 sd_device_unref(enumerator
->match_parent
);
232 enumerator
->match_parent
= sd_device_ref(parent
);
234 enumerator
->scan_uptodate
= false;
239 _public_
int sd_device_enumerator_allow_uninitialized(sd_device_enumerator
*enumerator
) {
240 assert_return(enumerator
, -EINVAL
);
242 enumerator
->match_allow_uninitialized
= true;
244 enumerator
->scan_uptodate
= false;
249 int device_enumerator_add_match_is_initialized(sd_device_enumerator
*enumerator
) {
250 assert_return(enumerator
, -EINVAL
);
252 enumerator
->match_allow_uninitialized
= false;
254 enumerator
->scan_uptodate
= false;
259 static int device_compare(const void *_a
, const void *_b
) {
260 sd_device
*a
= (sd_device
*)_a
, *b
= (sd_device
*)_b
;
261 const char *devpath_a
, *devpath_b
, *sound_a
;
262 bool delay_a
, delay_b
;
264 assert_se(sd_device_get_devpath(a
, &devpath_a
) >= 0);
265 assert_se(sd_device_get_devpath(b
, &devpath_b
) >= 0);
267 sound_a
= strstr(devpath_a
, "/sound/card");
269 /* For sound cards the control device must be enumerated last to
270 * make sure it's the final device node that gets ACLs applied.
271 * Applications rely on this fact and use ACL changes on the
272 * control node as an indicator that the ACL change of the
273 * entire sound card completed. The kernel makes this guarantee
274 * when creating those devices, and hence we should too when
275 * enumerating them. */
276 sound_a
+= STRLEN("/sound/card");
277 sound_a
= strchr(sound_a
, '/');
282 prefix_len
= sound_a
- devpath_a
;
284 if (strncmp(devpath_a
, devpath_b
, prefix_len
) == 0) {
287 sound_b
= devpath_b
+ prefix_len
;
289 if (startswith(sound_a
, "/controlC") &&
290 !startswith(sound_b
, "/contolC"))
293 if (!startswith(sound_a
, "/controlC") &&
294 startswith(sound_b
, "/controlC"))
300 /* md and dm devices are enumerated after all other devices */
301 delay_a
= strstr(devpath_a
, "/block/md") || strstr(devpath_a
, "/block/dm-");
302 delay_b
= strstr(devpath_b
, "/block/md") || strstr(devpath_b
, "/block/dm-");
303 if (delay_a
!= delay_b
)
304 return delay_a
- delay_b
;
306 return strcmp(devpath_a
, devpath_b
);
309 int device_enumerator_add_device(sd_device_enumerator
*enumerator
, sd_device
*device
) {
312 assert_return(enumerator
, -EINVAL
);
313 assert_return(device
, -EINVAL
);
315 r
= prioq_ensure_allocated(&enumerator
->devices
, device_compare
);
319 r
= prioq_put(enumerator
->devices
, device
, NULL
);
323 sd_device_ref(device
);
328 static bool match_sysattr_value(sd_device
*device
, const char *sysattr
, const char *match_value
) {
335 r
= sd_device_get_sysattr_value(device
, sysattr
, &value
);
342 if (fnmatch(match_value
, value
, 0) == 0)
348 static bool match_sysattr(sd_device_enumerator
*enumerator
, sd_device
*device
) {
356 HASHMAP_FOREACH_KEY(value
, sysattr
, enumerator
->nomatch_sysattr
, i
)
357 if (match_sysattr_value(device
, sysattr
, value
))
360 HASHMAP_FOREACH_KEY(value
, sysattr
, enumerator
->match_sysattr
, i
)
361 if (!match_sysattr_value(device
, sysattr
, value
))
367 static bool match_property(sd_device_enumerator
*enumerator
, sd_device
*device
) {
368 const char *property
;
375 if (hashmap_isempty(enumerator
->match_property
))
378 HASHMAP_FOREACH_KEY(value
, property
, enumerator
->match_property
, i
) {
379 const char *property_dev
, *value_dev
;
381 FOREACH_DEVICE_PROPERTY(device
, property_dev
, value_dev
) {
382 if (fnmatch(property
, property_dev
, 0) != 0)
385 if (!value
&& !value_dev
)
388 if (!value
|| !value_dev
)
391 if (fnmatch(value
, value_dev
, 0) == 0)
399 static bool match_tag(sd_device_enumerator
*enumerator
, sd_device
*device
) {
406 SET_FOREACH(tag
, enumerator
->match_tag
, i
)
407 if (!sd_device_has_tag(device
, tag
))
413 static bool match_parent(sd_device_enumerator
*enumerator
, sd_device
*device
) {
414 const char *devpath
, *devpath_dev
;
420 if (!enumerator
->match_parent
)
423 r
= sd_device_get_devpath(enumerator
->match_parent
, &devpath
);
426 r
= sd_device_get_devpath(device
, &devpath_dev
);
429 return startswith(devpath_dev
, devpath
);
432 static bool match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
433 const char *sysname_match
;
439 if (set_isempty(enumerator
->match_sysname
))
442 SET_FOREACH(sysname_match
, enumerator
->match_sysname
, i
)
443 if (fnmatch(sysname_match
, sysname
, 0) == 0)
449 static int enumerator_scan_dir_and_add_devices(sd_device_enumerator
*enumerator
, const char *basedir
, const char *subdir1
, const char *subdir2
) {
450 _cleanup_closedir_
DIR *dir
= NULL
;
458 path
= strjoina("/sys/", basedir
, "/");
461 path
= strjoina(path
, subdir1
, "/");
464 path
= strjoina(path
, subdir2
, "/");
470 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
471 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
472 char syspath
[strlen(path
) + 1 + strlen(dent
->d_name
) + 1];
474 int ifindex
, initialized
, k
;
476 if (dent
->d_name
[0] == '.')
479 if (!match_sysname(enumerator
, dent
->d_name
))
482 (void)sprintf(syspath
, "%s%s", path
, dent
->d_name
);
484 k
= sd_device_new_from_syspath(&device
, syspath
);
487 /* this is necessarily racey, so ignore missing devices */
493 k
= sd_device_get_devnum(device
, &devnum
);
499 k
= sd_device_get_ifindex(device
, &ifindex
);
505 k
= sd_device_get_is_initialized(device
, &initialized
);
512 * All devices with a device node or network interfaces
513 * possibly need udev to adjust the device node permission
514 * or context, or rename the interface before it can be
515 * reliably used from other processes.
517 * For now, we can only check these types of devices, we
518 * might not store a database, and have no way to find out
519 * for all other types of devices.
521 if (!enumerator
->match_allow_uninitialized
&&
523 (major(devnum
) > 0 || ifindex
> 0))
526 if (!match_parent(enumerator
, device
))
529 if (!match_tag(enumerator
, device
))
532 if (!match_property(enumerator
, device
))
535 if (!match_sysattr(enumerator
, device
))
538 k
= device_enumerator_add_device(enumerator
, device
);
546 static bool match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
) {
547 const char *subsystem_match
;
555 SET_FOREACH(subsystem_match
, enumerator
->nomatch_subsystem
, i
)
556 if (fnmatch(subsystem_match
, subsystem
, 0) == 0)
559 if (set_isempty(enumerator
->match_subsystem
))
562 SET_FOREACH(subsystem_match
, enumerator
->match_subsystem
, i
)
563 if (fnmatch(subsystem_match
, subsystem
, 0) == 0)
569 static int enumerator_scan_dir(sd_device_enumerator
*enumerator
, const char *basedir
, const char *subdir
, const char *subsystem
) {
570 _cleanup_closedir_
DIR *dir
= NULL
;
575 path
= strjoina("/sys/", basedir
);
581 log_debug(" device-enumerator: scanning %s", path
);
583 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
586 if (dent
->d_name
[0] == '.')
589 if (!match_subsystem(enumerator
, subsystem
? : dent
->d_name
))
592 k
= enumerator_scan_dir_and_add_devices(enumerator
, basedir
, dent
->d_name
, subdir
);
600 static int enumerator_scan_devices_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
601 _cleanup_closedir_
DIR *dir
= NULL
;
609 path
= strjoina("/run/udev/tags/", tag
);
616 return log_error_errno(errno
, "sd-device-enumerator: could not open tags directory %s: %m", path
);
619 /* TODO: filter away subsystems? */
621 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
622 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
623 const char *subsystem
, *sysname
;
626 if (dent
->d_name
[0] == '.')
629 k
= sd_device_new_from_device_id(&device
, dent
->d_name
);
632 /* this is necessarily racy, so ignore missing devices */
638 k
= sd_device_get_subsystem(device
, &subsystem
);
644 if (!match_subsystem(enumerator
, subsystem
))
647 k
= sd_device_get_sysname(device
, &sysname
);
653 if (!match_sysname(enumerator
, sysname
))
656 if (!match_parent(enumerator
, device
))
659 if (!match_property(enumerator
, device
))
662 if (!match_sysattr(enumerator
, device
))
665 k
= device_enumerator_add_device(enumerator
, device
);
675 static int enumerator_scan_devices_tags(sd_device_enumerator
*enumerator
) {
682 SET_FOREACH(tag
, enumerator
->match_tag
, i
) {
685 k
= enumerator_scan_devices_tag(enumerator
, tag
);
693 static int parent_add_child(sd_device_enumerator
*enumerator
, const char *path
) {
694 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
695 const char *subsystem
, *sysname
;
698 r
= sd_device_new_from_syspath(&device
, path
);
700 /* this is necessarily racy, so ignore missing devices */
705 r
= sd_device_get_subsystem(device
, &subsystem
);
711 if (!match_subsystem(enumerator
, subsystem
))
714 r
= sd_device_get_sysname(device
, &sysname
);
718 if (!match_sysname(enumerator
, sysname
))
721 if (!match_property(enumerator
, device
))
724 if (!match_sysattr(enumerator
, device
))
727 r
= device_enumerator_add_device(enumerator
, device
);
734 static int parent_crawl_children(sd_device_enumerator
*enumerator
, const char *path
, unsigned maxdepth
) {
735 _cleanup_closedir_
DIR *dir
= NULL
;
741 return log_debug_errno(errno
, "sd-device-enumerate: could not open parent directory %s: %m", path
);
743 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
744 _cleanup_free_
char *child
= NULL
;
747 if (dent
->d_name
[0] == '.')
750 if (dent
->d_type
!= DT_DIR
)
753 child
= strjoin(path
, "/", dent
->d_name
);
757 k
= parent_add_child(enumerator
, child
);
762 parent_crawl_children(enumerator
, child
, maxdepth
- 1);
764 log_debug("device-enumerate: max depth reached, %s: ignoring devices", child
);
770 static int enumerator_scan_devices_children(sd_device_enumerator
*enumerator
) {
774 r
= sd_device_get_syspath(enumerator
->match_parent
, &path
);
778 k
= parent_add_child(enumerator
, path
);
782 k
= parent_crawl_children(enumerator
, path
, DEVICE_ENUMERATE_MAX_DEPTH
);
789 static int enumerator_scan_devices_all(sd_device_enumerator
*enumerator
) {
792 log_debug("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
, "device-enumerator: failed to scan /sys/subsystem: %m");
802 k
= enumerator_scan_dir(enumerator
, "bus", "devices", NULL
);
804 log_debug_errno(k
, "device-enumerator: failed to scan /sys/bus: %m");
808 k
= enumerator_scan_dir(enumerator
, "class", NULL
, NULL
);
810 log_debug_errno(k
, "device-enumerator: failed to scan /sys/class: %m");
818 int device_enumerator_scan_devices(sd_device_enumerator
*enumerator
) {
824 if (enumerator
->scan_uptodate
&&
825 enumerator
->type
== DEVICE_ENUMERATION_TYPE_DEVICES
)
828 while ((device
= prioq_pop(enumerator
->devices
)))
829 sd_device_unref(device
);
831 if (!set_isempty(enumerator
->match_tag
)) {
832 k
= enumerator_scan_devices_tags(enumerator
);
835 } else if (enumerator
->match_parent
) {
836 k
= enumerator_scan_devices_children(enumerator
);
840 k
= enumerator_scan_devices_all(enumerator
);
845 enumerator
->scan_uptodate
= true;
850 _public_ sd_device
*sd_device_enumerator_get_device_first(sd_device_enumerator
*enumerator
) {
853 assert_return(enumerator
, NULL
);
855 r
= device_enumerator_scan_devices(enumerator
);
859 enumerator
->type
= DEVICE_ENUMERATION_TYPE_DEVICES
;
861 return prioq_peek(enumerator
->devices
);
864 _public_ sd_device
*sd_device_enumerator_get_device_next(sd_device_enumerator
*enumerator
) {
865 assert_return(enumerator
, NULL
);
867 if (!enumerator
->scan_uptodate
||
868 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_DEVICES
)
871 sd_device_unref(prioq_pop(enumerator
->devices
));
873 return prioq_peek(enumerator
->devices
);
876 int device_enumerator_scan_subsystems(sd_device_enumerator
*enumerator
) {
878 const char *subsysdir
;
883 if (enumerator
->scan_uptodate
&&
884 enumerator
->type
== DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
)
887 while ((device
= prioq_pop(enumerator
->devices
)))
888 sd_device_unref(device
);
891 if (match_subsystem(enumerator
, "module")) {
892 k
= enumerator_scan_dir_and_add_devices(enumerator
, "module", NULL
, NULL
);
894 log_debug_errno(k
, "device-enumerator: failed to scan modules: %m");
899 if (access("/sys/subsystem", F_OK
) >= 0)
900 subsysdir
= "subsystem";
904 /* subsystems (only buses support coldplug) */
905 if (match_subsystem(enumerator
, "subsystem")) {
906 k
= enumerator_scan_dir_and_add_devices(enumerator
, subsysdir
, NULL
, NULL
);
908 log_debug_errno(k
, "device-enumerator: failed to scan subsystems: %m");
913 /* subsystem drivers */
914 if (match_subsystem(enumerator
, "drivers")) {
915 k
= enumerator_scan_dir(enumerator
, subsysdir
, "drivers", "drivers");
917 log_debug_errno(k
, "device-enumerator: failed to scan drivers: %m");
922 enumerator
->scan_uptodate
= true;
927 _public_ sd_device
*sd_device_enumerator_get_subsystem_first(sd_device_enumerator
*enumerator
) {
930 assert_return(enumerator
, NULL
);
932 r
= device_enumerator_scan_subsystems(enumerator
);
936 enumerator
->type
= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
;
938 return prioq_peek(enumerator
->devices
);
941 _public_ sd_device
*sd_device_enumerator_get_subsystem_next(sd_device_enumerator
*enumerator
) {
942 assert_return(enumerator
, NULL
);
944 if (enumerator
->scan_uptodate
||
945 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
)
948 sd_device_unref(prioq_pop(enumerator
->devices
));
950 return prioq_peek(enumerator
->devices
);
953 sd_device
*device_enumerator_get_first(sd_device_enumerator
*enumerator
) {
954 assert_return(enumerator
, NULL
);
956 return prioq_peek(enumerator
->devices
);
959 sd_device
*device_enumerator_get_next(sd_device_enumerator
*enumerator
) {
960 assert_return(enumerator
, NULL
);
962 sd_device_unref(prioq_pop(enumerator
->devices
));
964 return prioq_peek(enumerator
->devices
);