1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
6 Copyright 2014-2015 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "sd-device.h"
24 #include "alloc-util.h"
25 #include "device-enumerator-private.h"
26 #include "device-util.h"
27 #include "dirent-util.h"
31 #include "string-util.h"
35 #define DEVICE_ENUMERATE_MAX_DEPTH 256
37 typedef enum DeviceEnumerationType
{
38 DEVICE_ENUMERATION_TYPE_DEVICES
,
39 DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
,
40 _DEVICE_ENUMERATION_TYPE_MAX
,
41 _DEVICE_ENUMERATION_TYPE_INVALID
= -1,
42 } DeviceEnumerationType
;
44 struct sd_device_enumerator
{
47 DeviceEnumerationType type
;
52 Set
*nomatch_subsystem
;
53 Hashmap
*match_sysattr
;
54 Hashmap
*nomatch_sysattr
;
55 Hashmap
*match_property
;
58 sd_device
*match_parent
;
59 bool match_allow_uninitialized
;
62 _public_
int sd_device_enumerator_new(sd_device_enumerator
**ret
) {
63 _cleanup_(sd_device_enumerator_unrefp
) sd_device_enumerator
*enumerator
= NULL
;
67 enumerator
= new0(sd_device_enumerator
, 1);
71 enumerator
->n_ref
= 1;
72 enumerator
->type
= _DEVICE_ENUMERATION_TYPE_INVALID
;
80 _public_ sd_device_enumerator
*sd_device_enumerator_ref(sd_device_enumerator
*enumerator
) {
81 assert_return(enumerator
, NULL
);
83 assert_se((++ enumerator
->n_ref
) >= 2);
88 _public_ sd_device_enumerator
*sd_device_enumerator_unref(sd_device_enumerator
*enumerator
) {
89 if (enumerator
&& (-- enumerator
->n_ref
) == 0) {
92 while ((device
= prioq_pop(enumerator
->devices
)))
93 sd_device_unref(device
);
95 prioq_free(enumerator
->devices
);
97 set_free_free(enumerator
->match_subsystem
);
98 set_free_free(enumerator
->nomatch_subsystem
);
99 hashmap_free_free_free(enumerator
->match_sysattr
);
100 hashmap_free_free_free(enumerator
->nomatch_sysattr
);
101 hashmap_free_free_free(enumerator
->match_property
);
102 set_free_free(enumerator
->match_sysname
);
103 set_free_free(enumerator
->match_tag
);
104 sd_device_unref(enumerator
->match_parent
);
112 _public_
int sd_device_enumerator_add_match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
, int match
) {
116 assert_return(enumerator
, -EINVAL
);
117 assert_return(subsystem
, -EINVAL
);
120 set
= &enumerator
->match_subsystem
;
122 set
= &enumerator
->nomatch_subsystem
;
124 r
= set_ensure_allocated(set
, NULL
);
128 r
= set_put_strdup(*set
, subsystem
);
132 enumerator
->scan_uptodate
= false;
137 _public_
int sd_device_enumerator_add_match_sysattr(sd_device_enumerator
*enumerator
, const char *_sysattr
, const char *_value
, int match
) {
138 _cleanup_free_
char *sysattr
= NULL
, *value
= NULL
;
142 assert_return(enumerator
, -EINVAL
);
143 assert_return(_sysattr
, -EINVAL
);
146 hashmap
= &enumerator
->match_sysattr
;
148 hashmap
= &enumerator
->nomatch_sysattr
;
150 r
= hashmap_ensure_allocated(hashmap
, NULL
);
154 sysattr
= strdup(_sysattr
);
159 value
= strdup(_value
);
164 r
= hashmap_put(*hashmap
, sysattr
, value
);
171 enumerator
->scan_uptodate
= false;
176 _public_
int sd_device_enumerator_add_match_property(sd_device_enumerator
*enumerator
, const char *_property
, const char *_value
) {
177 _cleanup_free_
char *property
= NULL
, *value
= NULL
;
180 assert_return(enumerator
, -EINVAL
);
181 assert_return(_property
, -EINVAL
);
183 r
= hashmap_ensure_allocated(&enumerator
->match_property
, NULL
);
187 property
= strdup(_property
);
192 value
= strdup(_value
);
197 r
= hashmap_put(enumerator
->match_property
, property
, value
);
204 enumerator
->scan_uptodate
= false;
209 _public_
int sd_device_enumerator_add_match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
212 assert_return(enumerator
, -EINVAL
);
213 assert_return(sysname
, -EINVAL
);
215 r
= set_ensure_allocated(&enumerator
->match_sysname
, NULL
);
219 r
= set_put_strdup(enumerator
->match_sysname
, sysname
);
223 enumerator
->scan_uptodate
= false;
228 _public_
int sd_device_enumerator_add_match_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
231 assert_return(enumerator
, -EINVAL
);
232 assert_return(tag
, -EINVAL
);
234 r
= set_ensure_allocated(&enumerator
->match_tag
, NULL
);
238 r
= set_put_strdup(enumerator
->match_tag
, tag
);
242 enumerator
->scan_uptodate
= false;
247 _public_
int sd_device_enumerator_add_match_parent(sd_device_enumerator
*enumerator
, sd_device
*parent
) {
248 assert_return(enumerator
, -EINVAL
);
249 assert_return(parent
, -EINVAL
);
251 sd_device_unref(enumerator
->match_parent
);
252 enumerator
->match_parent
= sd_device_ref(parent
);
254 enumerator
->scan_uptodate
= false;
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(const void *_a
, const void *_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
;
284 assert_se(sd_device_get_devpath(a
, &devpath_a
) >= 0);
285 assert_se(sd_device_get_devpath(b
, &devpath_b
) >= 0);
287 sound_a
= strstr(devpath_a
, "/sound/card");
289 /* For sound cards the control device must be enumerated last to
290 * make sure it's the final device node that gets ACLs applied.
291 * Applications rely on this fact and use ACL changes on the
292 * control node as an indicator that the ACL change of the
293 * entire sound card completed. The kernel makes this guarantee
294 * when creating those devices, and hence we should too when
295 * enumerating them. */
296 sound_a
+= STRLEN("/sound/card");
297 sound_a
= strchr(sound_a
, '/');
302 prefix_len
= sound_a
- devpath_a
;
304 if (strncmp(devpath_a
, devpath_b
, prefix_len
) == 0) {
307 sound_b
= devpath_b
+ prefix_len
;
309 if (startswith(sound_a
, "/controlC") &&
310 !startswith(sound_b
, "/contolC"))
313 if (!startswith(sound_a
, "/controlC") &&
314 startswith(sound_b
, "/controlC"))
320 /* md and dm devices are enumerated after all other devices */
321 delay_a
= strstr(devpath_a
, "/block/md") || strstr(devpath_a
, "/block/dm-");
322 delay_b
= strstr(devpath_b
, "/block/md") || strstr(devpath_b
, "/block/dm-");
323 if (delay_a
!= delay_b
)
324 return delay_a
- delay_b
;
326 return strcmp(devpath_a
, devpath_b
);
329 int device_enumerator_add_device(sd_device_enumerator
*enumerator
, sd_device
*device
) {
332 assert_return(enumerator
, -EINVAL
);
333 assert_return(device
, -EINVAL
);
335 r
= prioq_ensure_allocated(&enumerator
->devices
, device_compare
);
339 r
= prioq_put(enumerator
->devices
, device
, NULL
);
343 sd_device_ref(device
);
348 static bool match_sysattr_value(sd_device
*device
, const char *sysattr
, const char *match_value
) {
355 r
= sd_device_get_sysattr_value(device
, sysattr
, &value
);
362 if (fnmatch(match_value
, value
, 0) == 0)
368 static bool match_sysattr(sd_device_enumerator
*enumerator
, sd_device
*device
) {
376 HASHMAP_FOREACH_KEY(value
, sysattr
, enumerator
->nomatch_sysattr
, i
)
377 if (match_sysattr_value(device
, sysattr
, value
))
380 HASHMAP_FOREACH_KEY(value
, sysattr
, enumerator
->match_sysattr
, i
)
381 if (!match_sysattr_value(device
, sysattr
, value
))
387 static bool match_property(sd_device_enumerator
*enumerator
, sd_device
*device
) {
388 const char *property
;
395 if (hashmap_isempty(enumerator
->match_property
))
398 HASHMAP_FOREACH_KEY(value
, property
, enumerator
->match_property
, i
) {
399 const char *property_dev
, *value_dev
;
401 FOREACH_DEVICE_PROPERTY(device
, property_dev
, value_dev
) {
402 if (fnmatch(property
, property_dev
, 0) != 0)
405 if (!value
&& !value_dev
)
408 if (!value
|| !value_dev
)
411 if (fnmatch(value
, value_dev
, 0) == 0)
419 static bool match_tag(sd_device_enumerator
*enumerator
, sd_device
*device
) {
426 SET_FOREACH(tag
, enumerator
->match_tag
, i
)
427 if (!sd_device_has_tag(device
, tag
))
433 static bool match_parent(sd_device_enumerator
*enumerator
, sd_device
*device
) {
434 const char *devpath
, *devpath_dev
;
440 if (!enumerator
->match_parent
)
443 r
= sd_device_get_devpath(enumerator
->match_parent
, &devpath
);
446 r
= sd_device_get_devpath(device
, &devpath_dev
);
449 return startswith(devpath_dev
, devpath
);
452 static bool match_sysname(sd_device_enumerator
*enumerator
, const char *sysname
) {
453 const char *sysname_match
;
459 if (set_isempty(enumerator
->match_sysname
))
462 SET_FOREACH(sysname_match
, enumerator
->match_sysname
, i
)
463 if (fnmatch(sysname_match
, sysname
, 0) == 0)
469 static int enumerator_scan_dir_and_add_devices(sd_device_enumerator
*enumerator
, const char *basedir
, const char *subdir1
, const char *subdir2
) {
470 _cleanup_closedir_
DIR *dir
= NULL
;
478 path
= strjoina("/sys/", basedir
, "/");
481 path
= strjoina(path
, subdir1
, "/");
484 path
= strjoina(path
, subdir2
, "/");
490 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
491 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
492 char syspath
[strlen(path
) + 1 + strlen(dent
->d_name
) + 1];
494 int ifindex
, initialized
, k
;
496 if (dent
->d_name
[0] == '.')
499 if (!match_sysname(enumerator
, dent
->d_name
))
502 (void)sprintf(syspath
, "%s%s", path
, dent
->d_name
);
504 k
= sd_device_new_from_syspath(&device
, syspath
);
507 /* this is necessarily racey, so ignore missing devices */
513 k
= sd_device_get_devnum(device
, &devnum
);
519 k
= sd_device_get_ifindex(device
, &ifindex
);
525 k
= sd_device_get_is_initialized(device
, &initialized
);
532 * All devices with a device node or network interfaces
533 * possibly need udev to adjust the device node permission
534 * or context, or rename the interface before it can be
535 * reliably used from other processes.
537 * For now, we can only check these types of devices, we
538 * might not store a database, and have no way to find out
539 * for all other types of devices.
541 if (!enumerator
->match_allow_uninitialized
&&
543 (major(devnum
) > 0 || ifindex
> 0))
546 if (!match_parent(enumerator
, device
))
549 if (!match_tag(enumerator
, device
))
552 if (!match_property(enumerator
, device
))
555 if (!match_sysattr(enumerator
, device
))
558 k
= device_enumerator_add_device(enumerator
, device
);
566 static bool match_subsystem(sd_device_enumerator
*enumerator
, const char *subsystem
) {
567 const char *subsystem_match
;
575 SET_FOREACH(subsystem_match
, enumerator
->nomatch_subsystem
, i
)
576 if (fnmatch(subsystem_match
, subsystem
, 0) == 0)
579 if (set_isempty(enumerator
->match_subsystem
))
582 SET_FOREACH(subsystem_match
, enumerator
->match_subsystem
, i
)
583 if (fnmatch(subsystem_match
, subsystem
, 0) == 0)
589 static int enumerator_scan_dir(sd_device_enumerator
*enumerator
, const char *basedir
, const char *subdir
, const char *subsystem
) {
590 _cleanup_closedir_
DIR *dir
= NULL
;
595 path
= strjoina("/sys/", basedir
);
601 log_debug(" device-enumerator: scanning %s", path
);
603 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
606 if (dent
->d_name
[0] == '.')
609 if (!match_subsystem(enumerator
, subsystem
? : dent
->d_name
))
612 k
= enumerator_scan_dir_and_add_devices(enumerator
, basedir
, dent
->d_name
, subdir
);
620 static int enumerator_scan_devices_tag(sd_device_enumerator
*enumerator
, const char *tag
) {
621 _cleanup_closedir_
DIR *dir
= NULL
;
629 path
= strjoina("/run/udev/tags/", tag
);
636 return log_error_errno(errno
, "sd-device-enumerator: could not open tags directory %s: %m", path
);
639 /* TODO: filter away subsystems? */
641 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
642 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
643 const char *subsystem
, *sysname
;
646 if (dent
->d_name
[0] == '.')
649 k
= sd_device_new_from_device_id(&device
, dent
->d_name
);
652 /* this is necessarily racy, so ignore missing devices */
658 k
= sd_device_get_subsystem(device
, &subsystem
);
664 if (!match_subsystem(enumerator
, subsystem
))
667 k
= sd_device_get_sysname(device
, &sysname
);
673 if (!match_sysname(enumerator
, sysname
))
676 if (!match_parent(enumerator
, device
))
679 if (!match_property(enumerator
, device
))
682 if (!match_sysattr(enumerator
, device
))
685 k
= device_enumerator_add_device(enumerator
, device
);
695 static int enumerator_scan_devices_tags(sd_device_enumerator
*enumerator
) {
702 SET_FOREACH(tag
, enumerator
->match_tag
, i
) {
705 k
= enumerator_scan_devices_tag(enumerator
, tag
);
713 static int parent_add_child(sd_device_enumerator
*enumerator
, const char *path
) {
714 _cleanup_(sd_device_unrefp
) sd_device
*device
= NULL
;
715 const char *subsystem
, *sysname
;
718 r
= sd_device_new_from_syspath(&device
, path
);
720 /* this is necessarily racy, so ignore missing devices */
725 r
= sd_device_get_subsystem(device
, &subsystem
);
731 if (!match_subsystem(enumerator
, subsystem
))
734 r
= sd_device_get_sysname(device
, &sysname
);
738 if (!match_sysname(enumerator
, sysname
))
741 if (!match_property(enumerator
, device
))
744 if (!match_sysattr(enumerator
, device
))
747 r
= device_enumerator_add_device(enumerator
, device
);
754 static int parent_crawl_children(sd_device_enumerator
*enumerator
, const char *path
, unsigned maxdepth
) {
755 _cleanup_closedir_
DIR *dir
= NULL
;
761 return log_debug_errno(errno
, "sd-device-enumerate: could not open parent directory %s: %m", path
);
763 FOREACH_DIRENT_ALL(dent
, dir
, return -errno
) {
764 _cleanup_free_
char *child
= NULL
;
767 if (dent
->d_name
[0] == '.')
770 if (dent
->d_type
!= DT_DIR
)
773 child
= strjoin(path
, "/", dent
->d_name
);
777 k
= parent_add_child(enumerator
, child
);
782 parent_crawl_children(enumerator
, child
, maxdepth
- 1);
784 log_debug("device-enumerate: max depth reached, %s: ignoring devices", child
);
790 static int enumerator_scan_devices_children(sd_device_enumerator
*enumerator
) {
794 r
= sd_device_get_syspath(enumerator
->match_parent
, &path
);
798 k
= parent_add_child(enumerator
, path
);
802 k
= parent_crawl_children(enumerator
, path
, DEVICE_ENUMERATE_MAX_DEPTH
);
809 static int enumerator_scan_devices_all(sd_device_enumerator
*enumerator
) {
812 log_debug("device-enumerator: scan all dirs");
814 if (access("/sys/subsystem", F_OK
) >= 0) {
815 /* we have /subsystem/, forget all the old stuff */
816 r
= enumerator_scan_dir(enumerator
, "subsystem", "devices", NULL
);
818 return log_debug_errno(r
, "device-enumerator: failed to scan /sys/subsystem: %m");
822 k
= enumerator_scan_dir(enumerator
, "bus", "devices", NULL
);
824 log_debug_errno(k
, "device-enumerator: failed to scan /sys/bus: %m");
828 k
= enumerator_scan_dir(enumerator
, "class", NULL
, NULL
);
830 log_debug_errno(k
, "device-enumerator: failed to scan /sys/class: %m");
838 int device_enumerator_scan_devices(sd_device_enumerator
*enumerator
) {
844 if (enumerator
->scan_uptodate
&&
845 enumerator
->type
== DEVICE_ENUMERATION_TYPE_DEVICES
)
848 while ((device
= prioq_pop(enumerator
->devices
)))
849 sd_device_unref(device
);
851 if (!set_isempty(enumerator
->match_tag
)) {
852 k
= enumerator_scan_devices_tags(enumerator
);
855 } else if (enumerator
->match_parent
) {
856 k
= enumerator_scan_devices_children(enumerator
);
860 k
= enumerator_scan_devices_all(enumerator
);
865 enumerator
->scan_uptodate
= true;
870 _public_ sd_device
*sd_device_enumerator_get_device_first(sd_device_enumerator
*enumerator
) {
873 assert_return(enumerator
, NULL
);
875 r
= device_enumerator_scan_devices(enumerator
);
879 enumerator
->type
= DEVICE_ENUMERATION_TYPE_DEVICES
;
881 return prioq_peek(enumerator
->devices
);
884 _public_ sd_device
*sd_device_enumerator_get_device_next(sd_device_enumerator
*enumerator
) {
885 assert_return(enumerator
, NULL
);
887 if (!enumerator
->scan_uptodate
||
888 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_DEVICES
)
891 sd_device_unref(prioq_pop(enumerator
->devices
));
893 return prioq_peek(enumerator
->devices
);
896 int device_enumerator_scan_subsystems(sd_device_enumerator
*enumerator
) {
898 const char *subsysdir
;
903 if (enumerator
->scan_uptodate
&&
904 enumerator
->type
== DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
)
907 while ((device
= prioq_pop(enumerator
->devices
)))
908 sd_device_unref(device
);
911 if (match_subsystem(enumerator
, "module")) {
912 k
= enumerator_scan_dir_and_add_devices(enumerator
, "module", NULL
, NULL
);
914 log_debug_errno(k
, "device-enumerator: failed to scan modules: %m");
919 if (access("/sys/subsystem", F_OK
) >= 0)
920 subsysdir
= "subsystem";
924 /* subsystems (only buses support coldplug) */
925 if (match_subsystem(enumerator
, "subsystem")) {
926 k
= enumerator_scan_dir_and_add_devices(enumerator
, subsysdir
, NULL
, NULL
);
928 log_debug_errno(k
, "device-enumerator: failed to scan subsystems: %m");
933 /* subsystem drivers */
934 if (match_subsystem(enumerator
, "drivers")) {
935 k
= enumerator_scan_dir(enumerator
, subsysdir
, "drivers", "drivers");
937 log_debug_errno(k
, "device-enumerator: failed to scan drivers: %m");
942 enumerator
->scan_uptodate
= true;
947 _public_ sd_device
*sd_device_enumerator_get_subsystem_first(sd_device_enumerator
*enumerator
) {
950 assert_return(enumerator
, NULL
);
952 r
= device_enumerator_scan_subsystems(enumerator
);
956 enumerator
->type
= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
;
958 return prioq_peek(enumerator
->devices
);
961 _public_ sd_device
*sd_device_enumerator_get_subsystem_next(sd_device_enumerator
*enumerator
) {
962 assert_return(enumerator
, NULL
);
964 if (enumerator
->scan_uptodate
||
965 enumerator
->type
!= DEVICE_ENUMERATION_TYPE_SUBSYSTEMS
)
968 sd_device_unref(prioq_pop(enumerator
->devices
));
970 return prioq_peek(enumerator
->devices
);
973 sd_device
*device_enumerator_get_first(sd_device_enumerator
*enumerator
) {
974 assert_return(enumerator
, NULL
);
976 return prioq_peek(enumerator
->devices
);
979 sd_device
*device_enumerator_get_next(sd_device_enumerator
*enumerator
) {
980 assert_return(enumerator
, NULL
);
982 sd_device_unref(prioq_pop(enumerator
->devices
));
984 return prioq_peek(enumerator
->devices
);