]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-device/device-enumerator.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / libsystemd / sd-device / device-enumerator.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
6 Copyright 2014-2015 Tom Gundersen <teg@jklm.no>
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include "sd-device.h"
23
24 #include "alloc-util.h"
25 #include "device-enumerator-private.h"
26 #include "device-util.h"
27 #include "dirent-util.h"
28 #include "fd-util.h"
29 #include "prioq.h"
30 #include "set.h"
31 #include "string-util.h"
32 #include "strv.h"
33 #include "util.h"
34
35 #define DEVICE_ENUMERATE_MAX_DEPTH 256
36
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;
43
44 struct sd_device_enumerator {
45 unsigned n_ref;
46
47 DeviceEnumerationType type;
48 Prioq *devices;
49 bool scan_uptodate;
50
51 Set *match_subsystem;
52 Set *nomatch_subsystem;
53 Hashmap *match_sysattr;
54 Hashmap *nomatch_sysattr;
55 Hashmap *match_property;
56 Set *match_sysname;
57 Set *match_tag;
58 sd_device *match_parent;
59 bool match_allow_uninitialized;
60 };
61
62 _public_ int sd_device_enumerator_new(sd_device_enumerator **ret) {
63 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *enumerator = NULL;
64
65 assert(ret);
66
67 enumerator = new0(sd_device_enumerator, 1);
68 if (!enumerator)
69 return -ENOMEM;
70
71 enumerator->n_ref = 1;
72 enumerator->type = _DEVICE_ENUMERATION_TYPE_INVALID;
73
74 *ret = enumerator;
75 enumerator = NULL;
76
77 return 0;
78 }
79
80 _public_ sd_device_enumerator *sd_device_enumerator_ref(sd_device_enumerator *enumerator) {
81 assert_return(enumerator, NULL);
82
83 assert_se((++ enumerator->n_ref) >= 2);
84
85 return enumerator;
86 }
87
88 _public_ sd_device_enumerator *sd_device_enumerator_unref(sd_device_enumerator *enumerator) {
89 if (enumerator && (-- enumerator->n_ref) == 0) {
90 sd_device *device;
91
92 while ((device = prioq_pop(enumerator->devices)))
93 sd_device_unref(device);
94
95 prioq_free(enumerator->devices);
96
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);
105
106 free(enumerator);
107 }
108
109 return NULL;
110 }
111
112 _public_ int sd_device_enumerator_add_match_subsystem(sd_device_enumerator *enumerator, const char *subsystem, int match) {
113 Set **set;
114 int r;
115
116 assert_return(enumerator, -EINVAL);
117 assert_return(subsystem, -EINVAL);
118
119 if (match)
120 set = &enumerator->match_subsystem;
121 else
122 set = &enumerator->nomatch_subsystem;
123
124 r = set_ensure_allocated(set, NULL);
125 if (r < 0)
126 return r;
127
128 r = set_put_strdup(*set, subsystem);
129 if (r < 0)
130 return r;
131
132 enumerator->scan_uptodate = false;
133
134 return 0;
135 }
136
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;
139 Hashmap **hashmap;
140 int r;
141
142 assert_return(enumerator, -EINVAL);
143 assert_return(_sysattr, -EINVAL);
144
145 if (match)
146 hashmap = &enumerator->match_sysattr;
147 else
148 hashmap = &enumerator->nomatch_sysattr;
149
150 r = hashmap_ensure_allocated(hashmap, NULL);
151 if (r < 0)
152 return r;
153
154 sysattr = strdup(_sysattr);
155 if (!sysattr)
156 return -ENOMEM;
157
158 if (_value) {
159 value = strdup(_value);
160 if (!value)
161 return -ENOMEM;
162 }
163
164 r = hashmap_put(*hashmap, sysattr, value);
165 if (r < 0)
166 return r;
167
168 sysattr = NULL;
169 value = NULL;
170
171 enumerator->scan_uptodate = false;
172
173 return 0;
174 }
175
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;
178 int r;
179
180 assert_return(enumerator, -EINVAL);
181 assert_return(_property, -EINVAL);
182
183 r = hashmap_ensure_allocated(&enumerator->match_property, NULL);
184 if (r < 0)
185 return r;
186
187 property = strdup(_property);
188 if (!property)
189 return -ENOMEM;
190
191 if (_value) {
192 value = strdup(_value);
193 if (!value)
194 return -ENOMEM;
195 }
196
197 r = hashmap_put(enumerator->match_property, property, value);
198 if (r < 0)
199 return r;
200
201 property = NULL;
202 value = NULL;
203
204 enumerator->scan_uptodate = false;
205
206 return 0;
207 }
208
209 _public_ int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname) {
210 int r;
211
212 assert_return(enumerator, -EINVAL);
213 assert_return(sysname, -EINVAL);
214
215 r = set_ensure_allocated(&enumerator->match_sysname, NULL);
216 if (r < 0)
217 return r;
218
219 r = set_put_strdup(enumerator->match_sysname, sysname);
220 if (r < 0)
221 return r;
222
223 enumerator->scan_uptodate = false;
224
225 return 0;
226 }
227
228 _public_ int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const char *tag) {
229 int r;
230
231 assert_return(enumerator, -EINVAL);
232 assert_return(tag, -EINVAL);
233
234 r = set_ensure_allocated(&enumerator->match_tag, NULL);
235 if (r < 0)
236 return r;
237
238 r = set_put_strdup(enumerator->match_tag, tag);
239 if (r < 0)
240 return r;
241
242 enumerator->scan_uptodate = false;
243
244 return 0;
245 }
246
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);
250
251 sd_device_unref(enumerator->match_parent);
252 enumerator->match_parent = sd_device_ref(parent);
253
254 enumerator->scan_uptodate = false;
255
256 return 0;
257 }
258
259 _public_ int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator) {
260 assert_return(enumerator, -EINVAL);
261
262 enumerator->match_allow_uninitialized = true;
263
264 enumerator->scan_uptodate = false;
265
266 return 0;
267 }
268
269 int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator) {
270 assert_return(enumerator, -EINVAL);
271
272 enumerator->match_allow_uninitialized = false;
273
274 enumerator->scan_uptodate = false;
275
276 return 0;
277 }
278
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;
283
284 assert_se(sd_device_get_devpath(a, &devpath_a) >= 0);
285 assert_se(sd_device_get_devpath(b, &devpath_b) >= 0);
286
287 sound_a = strstr(devpath_a, "/sound/card");
288 if (sound_a) {
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, '/');
298
299 if (sound_a) {
300 unsigned prefix_len;
301
302 prefix_len = sound_a - devpath_a;
303
304 if (strncmp(devpath_a, devpath_b, prefix_len) == 0) {
305 const char *sound_b;
306
307 sound_b = devpath_b + prefix_len;
308
309 if (startswith(sound_a, "/controlC") &&
310 !startswith(sound_b, "/contolC"))
311 return 1;
312
313 if (!startswith(sound_a, "/controlC") &&
314 startswith(sound_b, "/controlC"))
315 return -1;
316 }
317 }
318 }
319
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;
325
326 return strcmp(devpath_a, devpath_b);
327 }
328
329 int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device) {
330 int r;
331
332 assert_return(enumerator, -EINVAL);
333 assert_return(device, -EINVAL);
334
335 r = prioq_ensure_allocated(&enumerator->devices, device_compare);
336 if (r < 0)
337 return r;
338
339 r = prioq_put(enumerator->devices, device, NULL);
340 if (r < 0)
341 return r;
342
343 sd_device_ref(device);
344
345 return 0;
346 }
347
348 static bool match_sysattr_value(sd_device *device, const char *sysattr, const char *match_value) {
349 const char *value;
350 int r;
351
352 assert(device);
353 assert(sysattr);
354
355 r = sd_device_get_sysattr_value(device, sysattr, &value);
356 if (r < 0)
357 return false;
358
359 if (!match_value)
360 return true;
361
362 if (fnmatch(match_value, value, 0) == 0)
363 return true;
364
365 return false;
366 }
367
368 static bool match_sysattr(sd_device_enumerator *enumerator, sd_device *device) {
369 const char *sysattr;
370 const char *value;
371 Iterator i;
372
373 assert(enumerator);
374 assert(device);
375
376 HASHMAP_FOREACH_KEY(value, sysattr, enumerator->nomatch_sysattr, i)
377 if (match_sysattr_value(device, sysattr, value))
378 return false;
379
380 HASHMAP_FOREACH_KEY(value, sysattr, enumerator->match_sysattr, i)
381 if (!match_sysattr_value(device, sysattr, value))
382 return false;
383
384 return true;
385 }
386
387 static bool match_property(sd_device_enumerator *enumerator, sd_device *device) {
388 const char *property;
389 const char *value;
390 Iterator i;
391
392 assert(enumerator);
393 assert(device);
394
395 if (hashmap_isempty(enumerator->match_property))
396 return true;
397
398 HASHMAP_FOREACH_KEY(value, property, enumerator->match_property, i) {
399 const char *property_dev, *value_dev;
400
401 FOREACH_DEVICE_PROPERTY(device, property_dev, value_dev) {
402 if (fnmatch(property, property_dev, 0) != 0)
403 continue;
404
405 if (!value && !value_dev)
406 return true;
407
408 if (!value || !value_dev)
409 continue;
410
411 if (fnmatch(value, value_dev, 0) == 0)
412 return true;
413 }
414 }
415
416 return false;
417 }
418
419 static bool match_tag(sd_device_enumerator *enumerator, sd_device *device) {
420 const char *tag;
421 Iterator i;
422
423 assert(enumerator);
424 assert(device);
425
426 SET_FOREACH(tag, enumerator->match_tag, i)
427 if (!sd_device_has_tag(device, tag))
428 return false;
429
430 return true;
431 }
432
433 static bool match_parent(sd_device_enumerator *enumerator, sd_device *device) {
434 const char *devpath, *devpath_dev;
435 int r;
436
437 assert(enumerator);
438 assert(device);
439
440 if (!enumerator->match_parent)
441 return true;
442
443 r = sd_device_get_devpath(enumerator->match_parent, &devpath);
444 assert(r >= 0);
445
446 r = sd_device_get_devpath(device, &devpath_dev);
447 assert(r >= 0);
448
449 return startswith(devpath_dev, devpath);
450 }
451
452 static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname) {
453 const char *sysname_match;
454 Iterator i;
455
456 assert(enumerator);
457 assert(sysname);
458
459 if (set_isempty(enumerator->match_sysname))
460 return true;
461
462 SET_FOREACH(sysname_match, enumerator->match_sysname, i)
463 if (fnmatch(sysname_match, sysname, 0) == 0)
464 return true;
465
466 return false;
467 }
468
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;
471 char *path;
472 struct dirent *dent;
473 int r = 0;
474
475 assert(enumerator);
476 assert(basedir);
477
478 path = strjoina("/sys/", basedir, "/");
479
480 if (subdir1)
481 path = strjoina(path, subdir1, "/");
482
483 if (subdir2)
484 path = strjoina(path, subdir2, "/");
485
486 dir = opendir(path);
487 if (!dir)
488 return -errno;
489
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];
493 dev_t devnum;
494 int ifindex, initialized, k;
495
496 if (dent->d_name[0] == '.')
497 continue;
498
499 if (!match_sysname(enumerator, dent->d_name))
500 continue;
501
502 (void)sprintf(syspath, "%s%s", path, dent->d_name);
503
504 k = sd_device_new_from_syspath(&device, syspath);
505 if (k < 0) {
506 if (k != -ENODEV)
507 /* this is necessarily racey, so ignore missing devices */
508 r = k;
509
510 continue;
511 }
512
513 k = sd_device_get_devnum(device, &devnum);
514 if (k < 0) {
515 r = k;
516 continue;
517 }
518
519 k = sd_device_get_ifindex(device, &ifindex);
520 if (k < 0) {
521 r = k;
522 continue;
523 }
524
525 k = sd_device_get_is_initialized(device, &initialized);
526 if (k < 0) {
527 r = k;
528 continue;
529 }
530
531 /*
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.
536 *
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.
540 */
541 if (!enumerator->match_allow_uninitialized &&
542 !initialized &&
543 (major(devnum) > 0 || ifindex > 0))
544 continue;
545
546 if (!match_parent(enumerator, device))
547 continue;
548
549 if (!match_tag(enumerator, device))
550 continue;
551
552 if (!match_property(enumerator, device))
553 continue;
554
555 if (!match_sysattr(enumerator, device))
556 continue;
557
558 k = device_enumerator_add_device(enumerator, device);
559 if (k < 0)
560 r = k;
561 }
562
563 return r;
564 }
565
566 static bool match_subsystem(sd_device_enumerator *enumerator, const char *subsystem) {
567 const char *subsystem_match;
568 Iterator i;
569
570 assert(enumerator);
571
572 if (!subsystem)
573 return false;
574
575 SET_FOREACH(subsystem_match, enumerator->nomatch_subsystem, i)
576 if (fnmatch(subsystem_match, subsystem, 0) == 0)
577 return false;
578
579 if (set_isempty(enumerator->match_subsystem))
580 return true;
581
582 SET_FOREACH(subsystem_match, enumerator->match_subsystem, i)
583 if (fnmatch(subsystem_match, subsystem, 0) == 0)
584 return true;
585
586 return false;
587 }
588
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;
591 char *path;
592 struct dirent *dent;
593 int r = 0;
594
595 path = strjoina("/sys/", basedir);
596
597 dir = opendir(path);
598 if (!dir)
599 return -errno;
600
601 log_debug(" device-enumerator: scanning %s", path);
602
603 FOREACH_DIRENT_ALL(dent, dir, return -errno) {
604 int k;
605
606 if (dent->d_name[0] == '.')
607 continue;
608
609 if (!match_subsystem(enumerator, subsystem ? : dent->d_name))
610 continue;
611
612 k = enumerator_scan_dir_and_add_devices(enumerator, basedir, dent->d_name, subdir);
613 if (k < 0)
614 r = k;
615 }
616
617 return r;
618 }
619
620 static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const char *tag) {
621 _cleanup_closedir_ DIR *dir = NULL;
622 char *path;
623 struct dirent *dent;
624 int r = 0;
625
626 assert(enumerator);
627 assert(tag);
628
629 path = strjoina("/run/udev/tags/", tag);
630
631 dir = opendir(path);
632 if (!dir) {
633 if (errno == ENOENT)
634 return 0;
635 else
636 return log_error_errno(errno, "sd-device-enumerator: could not open tags directory %s: %m", path);
637 }
638
639 /* TODO: filter away subsystems? */
640
641 FOREACH_DIRENT_ALL(dent, dir, return -errno) {
642 _cleanup_(sd_device_unrefp) sd_device *device = NULL;
643 const char *subsystem, *sysname;
644 int k;
645
646 if (dent->d_name[0] == '.')
647 continue;
648
649 k = sd_device_new_from_device_id(&device, dent->d_name);
650 if (k < 0) {
651 if (k != -ENODEV)
652 /* this is necessarily racy, so ignore missing devices */
653 r = k;
654
655 continue;
656 }
657
658 k = sd_device_get_subsystem(device, &subsystem);
659 if (k < 0) {
660 r = k;
661 continue;
662 }
663
664 if (!match_subsystem(enumerator, subsystem))
665 continue;
666
667 k = sd_device_get_sysname(device, &sysname);
668 if (k < 0) {
669 r = k;
670 continue;
671 }
672
673 if (!match_sysname(enumerator, sysname))
674 continue;
675
676 if (!match_parent(enumerator, device))
677 continue;
678
679 if (!match_property(enumerator, device))
680 continue;
681
682 if (!match_sysattr(enumerator, device))
683 continue;
684
685 k = device_enumerator_add_device(enumerator, device);
686 if (k < 0) {
687 r = k;
688 continue;
689 }
690 }
691
692 return r;
693 }
694
695 static int enumerator_scan_devices_tags(sd_device_enumerator *enumerator) {
696 const char *tag;
697 Iterator i;
698 int r = 0;
699
700 assert(enumerator);
701
702 SET_FOREACH(tag, enumerator->match_tag, i) {
703 int k;
704
705 k = enumerator_scan_devices_tag(enumerator, tag);
706 if (k < 0)
707 r = k;
708 }
709
710 return r;
711 }
712
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;
716 int r;
717
718 r = sd_device_new_from_syspath(&device, path);
719 if (r == -ENODEV)
720 /* this is necessarily racy, so ignore missing devices */
721 return 0;
722 else if (r < 0)
723 return r;
724
725 r = sd_device_get_subsystem(device, &subsystem);
726 if (r == -ENOENT)
727 return 0;
728 if (r < 0)
729 return r;
730
731 if (!match_subsystem(enumerator, subsystem))
732 return 0;
733
734 r = sd_device_get_sysname(device, &sysname);
735 if (r < 0)
736 return r;
737
738 if (!match_sysname(enumerator, sysname))
739 return 0;
740
741 if (!match_property(enumerator, device))
742 return 0;
743
744 if (!match_sysattr(enumerator, device))
745 return 0;
746
747 r = device_enumerator_add_device(enumerator, device);
748 if (r < 0)
749 return r;
750
751 return 1;
752 }
753
754 static int parent_crawl_children(sd_device_enumerator *enumerator, const char *path, unsigned maxdepth) {
755 _cleanup_closedir_ DIR *dir = NULL;
756 struct dirent *dent;
757 int r = 0;
758
759 dir = opendir(path);
760 if (!dir)
761 return log_debug_errno(errno, "sd-device-enumerate: could not open parent directory %s: %m", path);
762
763 FOREACH_DIRENT_ALL(dent, dir, return -errno) {
764 _cleanup_free_ char *child = NULL;
765 int k;
766
767 if (dent->d_name[0] == '.')
768 continue;
769
770 if (dent->d_type != DT_DIR)
771 continue;
772
773 child = strjoin(path, "/", dent->d_name);
774 if (!child)
775 return -ENOMEM;
776
777 k = parent_add_child(enumerator, child);
778 if (k < 0)
779 r = k;
780
781 if (maxdepth > 0)
782 parent_crawl_children(enumerator, child, maxdepth - 1);
783 else
784 log_debug("device-enumerate: max depth reached, %s: ignoring devices", child);
785 }
786
787 return r;
788 }
789
790 static int enumerator_scan_devices_children(sd_device_enumerator *enumerator) {
791 const char *path;
792 int r = 0, k;
793
794 r = sd_device_get_syspath(enumerator->match_parent, &path);
795 if (r < 0)
796 return r;
797
798 k = parent_add_child(enumerator, path);
799 if (k < 0)
800 r = k;
801
802 k = parent_crawl_children(enumerator, path, DEVICE_ENUMERATE_MAX_DEPTH);
803 if (k < 0)
804 r = k;
805
806 return r;
807 }
808
809 static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) {
810 int r = 0;
811
812 log_debug("device-enumerator: scan all dirs");
813
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);
817 if (r < 0)
818 return log_debug_errno(r, "device-enumerator: failed to scan /sys/subsystem: %m");
819 } else {
820 int k;
821
822 k = enumerator_scan_dir(enumerator, "bus", "devices", NULL);
823 if (k < 0) {
824 log_debug_errno(k, "device-enumerator: failed to scan /sys/bus: %m");
825 r = k;
826 }
827
828 k = enumerator_scan_dir(enumerator, "class", NULL, NULL);
829 if (k < 0) {
830 log_debug_errno(k, "device-enumerator: failed to scan /sys/class: %m");
831 r = k;
832 }
833 }
834
835 return r;
836 }
837
838 int device_enumerator_scan_devices(sd_device_enumerator *enumerator) {
839 sd_device *device;
840 int r = 0, k;
841
842 assert(enumerator);
843
844 if (enumerator->scan_uptodate &&
845 enumerator->type == DEVICE_ENUMERATION_TYPE_DEVICES)
846 return 0;
847
848 while ((device = prioq_pop(enumerator->devices)))
849 sd_device_unref(device);
850
851 if (!set_isempty(enumerator->match_tag)) {
852 k = enumerator_scan_devices_tags(enumerator);
853 if (k < 0)
854 r = k;
855 } else if (enumerator->match_parent) {
856 k = enumerator_scan_devices_children(enumerator);
857 if (k < 0)
858 r = k;
859 } else {
860 k = enumerator_scan_devices_all(enumerator);
861 if (k < 0)
862 r = k;
863 }
864
865 enumerator->scan_uptodate = true;
866
867 return r;
868 }
869
870 _public_ sd_device *sd_device_enumerator_get_device_first(sd_device_enumerator *enumerator) {
871 int r;
872
873 assert_return(enumerator, NULL);
874
875 r = device_enumerator_scan_devices(enumerator);
876 if (r < 0)
877 return NULL;
878
879 enumerator->type = DEVICE_ENUMERATION_TYPE_DEVICES;
880
881 return prioq_peek(enumerator->devices);
882 }
883
884 _public_ sd_device *sd_device_enumerator_get_device_next(sd_device_enumerator *enumerator) {
885 assert_return(enumerator, NULL);
886
887 if (!enumerator->scan_uptodate ||
888 enumerator->type != DEVICE_ENUMERATION_TYPE_DEVICES)
889 return NULL;
890
891 sd_device_unref(prioq_pop(enumerator->devices));
892
893 return prioq_peek(enumerator->devices);
894 }
895
896 int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
897 sd_device *device;
898 const char *subsysdir;
899 int r = 0, k;
900
901 assert(enumerator);
902
903 if (enumerator->scan_uptodate &&
904 enumerator->type == DEVICE_ENUMERATION_TYPE_SUBSYSTEMS)
905 return 0;
906
907 while ((device = prioq_pop(enumerator->devices)))
908 sd_device_unref(device);
909
910 /* modules */
911 if (match_subsystem(enumerator, "module")) {
912 k = enumerator_scan_dir_and_add_devices(enumerator, "module", NULL, NULL);
913 if (k < 0) {
914 log_debug_errno(k, "device-enumerator: failed to scan modules: %m");
915 r = k;
916 }
917 }
918
919 if (access("/sys/subsystem", F_OK) >= 0)
920 subsysdir = "subsystem";
921 else
922 subsysdir = "bus";
923
924 /* subsystems (only buses support coldplug) */
925 if (match_subsystem(enumerator, "subsystem")) {
926 k = enumerator_scan_dir_and_add_devices(enumerator, subsysdir, NULL, NULL);
927 if (k < 0) {
928 log_debug_errno(k, "device-enumerator: failed to scan subsystems: %m");
929 r = k;
930 }
931 }
932
933 /* subsystem drivers */
934 if (match_subsystem(enumerator, "drivers")) {
935 k = enumerator_scan_dir(enumerator, subsysdir, "drivers", "drivers");
936 if (k < 0) {
937 log_debug_errno(k, "device-enumerator: failed to scan drivers: %m");
938 r = k;
939 }
940 }
941
942 enumerator->scan_uptodate = true;
943
944 return r;
945 }
946
947 _public_ sd_device *sd_device_enumerator_get_subsystem_first(sd_device_enumerator *enumerator) {
948 int r;
949
950 assert_return(enumerator, NULL);
951
952 r = device_enumerator_scan_subsystems(enumerator);
953 if (r < 0)
954 return NULL;
955
956 enumerator->type = DEVICE_ENUMERATION_TYPE_SUBSYSTEMS;
957
958 return prioq_peek(enumerator->devices);
959 }
960
961 _public_ sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator *enumerator) {
962 assert_return(enumerator, NULL);
963
964 if (enumerator->scan_uptodate ||
965 enumerator->type != DEVICE_ENUMERATION_TYPE_SUBSYSTEMS)
966 return NULL;
967
968 sd_device_unref(prioq_pop(enumerator->devices));
969
970 return prioq_peek(enumerator->devices);
971 }
972
973 sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator) {
974 assert_return(enumerator, NULL);
975
976 return prioq_peek(enumerator->devices);
977 }
978
979 sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator) {
980 assert_return(enumerator, NULL);
981
982 sd_device_unref(prioq_pop(enumerator->devices));
983
984 return prioq_peek(enumerator->devices);
985 }