]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-device/device-enumerator.c
util-lib: introduce dirent-util.[ch] for directory entry calls
[thirdparty/systemd.git] / src / libsystemd / sd-device / device-enumerator.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
5 Copyright 2014-2015 Tom Gundersen <teg@jklm.no>
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include "sd-device.h"
22
23 #include "device-enumerator-private.h"
24 #include "device-util.h"
25 #include "dirent-util.h"
26 #include "fd-util.h"
27 #include "prioq.h"
28 #include "set.h"
29 #include "string-util.h"
30 #include "strv.h"
31 #include "util.h"
32
33 #define DEVICE_ENUMERATE_MAX_DEPTH 256
34
35 typedef enum DeviceEnumerationType {
36 DEVICE_ENUMERATION_TYPE_DEVICES,
37 DEVICE_ENUMERATION_TYPE_SUBSYSTEMS,
38 _DEVICE_ENUMERATION_TYPE_MAX,
39 _DEVICE_ENUMERATION_TYPE_INVALID = -1,
40 } DeviceEnumerationType;
41
42 struct sd_device_enumerator {
43 unsigned n_ref;
44
45 DeviceEnumerationType type;
46 Prioq *devices;
47 bool scan_uptodate;
48
49 Set *match_subsystem;
50 Set *nomatch_subsystem;
51 Hashmap *match_sysattr;
52 Hashmap *nomatch_sysattr;
53 Hashmap *match_property;
54 Set *match_sysname;
55 Set *match_tag;
56 sd_device *match_parent;
57 bool match_allow_uninitialized;
58 };
59
60 _public_ int sd_device_enumerator_new(sd_device_enumerator **ret) {
61 _cleanup_device_enumerator_unref_ sd_device_enumerator *enumerator = NULL;
62
63 assert(ret);
64
65 enumerator = new0(sd_device_enumerator, 1);
66 if (!enumerator)
67 return -ENOMEM;
68
69 enumerator->n_ref = 1;
70 enumerator->type = _DEVICE_ENUMERATION_TYPE_INVALID;
71
72 *ret = enumerator;
73 enumerator = NULL;
74
75 return 0;
76 }
77
78 _public_ sd_device_enumerator *sd_device_enumerator_ref(sd_device_enumerator *enumerator) {
79 assert_return(enumerator, NULL);
80
81 assert_se((++ enumerator->n_ref) >= 2);
82
83 return enumerator;
84 }
85
86 _public_ sd_device_enumerator *sd_device_enumerator_unref(sd_device_enumerator *enumerator) {
87 if (enumerator && (-- enumerator->n_ref) == 0) {
88 sd_device *device;
89
90 while ((device = prioq_pop(enumerator->devices)))
91 sd_device_unref(device);
92
93 prioq_free(enumerator->devices);
94
95 set_free_free(enumerator->match_subsystem);
96 set_free_free(enumerator->nomatch_subsystem);
97 hashmap_free_free_free(enumerator->match_sysattr);
98 hashmap_free_free_free(enumerator->nomatch_sysattr);
99 hashmap_free_free_free(enumerator->match_property);
100 set_free_free(enumerator->match_sysname);
101 set_free_free(enumerator->match_tag);
102 sd_device_unref(enumerator->match_parent);
103
104 free(enumerator);
105 }
106
107 return NULL;
108 }
109
110 _public_ int sd_device_enumerator_add_match_subsystem(sd_device_enumerator *enumerator, const char *subsystem, int match) {
111 Set **set;
112 int r;
113
114 assert_return(enumerator, -EINVAL);
115 assert_return(subsystem, -EINVAL);
116
117 if (match)
118 set = &enumerator->match_subsystem;
119 else
120 set = &enumerator->nomatch_subsystem;
121
122 r = set_ensure_allocated(set, NULL);
123 if (r < 0)
124 return r;
125
126 r = set_put_strdup(*set, subsystem);
127 if (r < 0)
128 return r;
129
130 enumerator->scan_uptodate = false;
131
132 return 0;
133 }
134
135 _public_ int sd_device_enumerator_add_match_sysattr(sd_device_enumerator *enumerator, const char *_sysattr, const char *_value, int match) {
136 _cleanup_free_ char *sysattr = NULL, *value = NULL;
137 Hashmap **hashmap;
138 int r;
139
140 assert_return(enumerator, -EINVAL);
141 assert_return(_sysattr, -EINVAL);
142
143 if (match)
144 hashmap = &enumerator->match_sysattr;
145 else
146 hashmap = &enumerator->nomatch_sysattr;
147
148 r = hashmap_ensure_allocated(hashmap, NULL);
149 if (r < 0)
150 return r;
151
152 sysattr = strdup(_sysattr);
153 if (!sysattr)
154 return -ENOMEM;
155
156 if (_value) {
157 value = strdup(_value);
158 if (!value)
159 return -ENOMEM;
160 }
161
162 r = hashmap_put(*hashmap, sysattr, value);
163 if (r < 0)
164 return r;
165
166 sysattr = NULL;
167 value = NULL;
168
169 enumerator->scan_uptodate = false;
170
171 return 0;
172 }
173
174 _public_ int sd_device_enumerator_add_match_property(sd_device_enumerator *enumerator, const char *_property, const char *_value) {
175 _cleanup_free_ char *property = NULL, *value = NULL;
176 int r;
177
178 assert_return(enumerator, -EINVAL);
179 assert_return(_property, -EINVAL);
180
181 r = hashmap_ensure_allocated(&enumerator->match_property, NULL);
182 if (r < 0)
183 return r;
184
185 property = strdup(_property);
186 if (!property)
187 return -ENOMEM;
188
189 if (_value) {
190 value = strdup(_value);
191 if (!value)
192 return -ENOMEM;
193 }
194
195 r = hashmap_put(enumerator->match_property, property, value);
196 if (r < 0)
197 return r;
198
199 property = NULL;
200 value = NULL;
201
202 enumerator->scan_uptodate = false;
203
204 return 0;
205 }
206
207 _public_ int sd_device_enumerator_add_match_sysname(sd_device_enumerator *enumerator, const char *sysname) {
208 int r;
209
210 assert_return(enumerator, -EINVAL);
211 assert_return(sysname, -EINVAL);
212
213 r = set_ensure_allocated(&enumerator->match_sysname, NULL);
214 if (r < 0)
215 return r;
216
217 r = set_put_strdup(enumerator->match_sysname, sysname);
218 if (r < 0)
219 return r;
220
221 enumerator->scan_uptodate = false;
222
223 return 0;
224 }
225
226 _public_ int sd_device_enumerator_add_match_tag(sd_device_enumerator *enumerator, const char *tag) {
227 int r;
228
229 assert_return(enumerator, -EINVAL);
230 assert_return(tag, -EINVAL);
231
232 r = set_ensure_allocated(&enumerator->match_tag, NULL);
233 if (r < 0)
234 return r;
235
236 r = set_put_strdup(enumerator->match_tag, tag);
237 if (r < 0)
238 return r;
239
240 enumerator->scan_uptodate = false;
241
242 return 0;
243 }
244
245 _public_ int sd_device_enumerator_add_match_parent(sd_device_enumerator *enumerator, sd_device *parent) {
246 assert_return(enumerator, -EINVAL);
247 assert_return(parent, -EINVAL);
248
249 sd_device_unref(enumerator->match_parent);
250 enumerator->match_parent = sd_device_ref(parent);
251
252 enumerator->scan_uptodate = false;
253
254 return 0;
255 }
256
257 _public_ int sd_device_enumerator_allow_uninitialized(sd_device_enumerator *enumerator) {
258 assert_return(enumerator, -EINVAL);
259
260 enumerator->match_allow_uninitialized = true;
261
262 enumerator->scan_uptodate = false;
263
264 return 0;
265 }
266
267 int device_enumerator_add_match_is_initialized(sd_device_enumerator *enumerator) {
268 assert_return(enumerator, -EINVAL);
269
270 enumerator->match_allow_uninitialized = false;
271
272 enumerator->scan_uptodate = false;
273
274 return 0;
275 }
276
277 static int device_compare(const void *_a, const void *_b) {
278 sd_device *a = (sd_device *)_a, *b = (sd_device *)_b;
279 const char *devpath_a, *devpath_b, *sound_a;
280 bool delay_a, delay_b;
281
282 assert_se(sd_device_get_devpath(a, &devpath_a) >= 0);
283 assert_se(sd_device_get_devpath(b, &devpath_b) >= 0);
284
285 sound_a = strstr(devpath_a, "/sound/card");
286 if (sound_a) {
287 /* For sound cards the control device must be enumerated last to
288 * make sure it's the final device node that gets ACLs applied.
289 * Applications rely on this fact and use ACL changes on the
290 * control node as an indicator that the ACL change of the
291 * entire sound card completed. The kernel makes this guarantee
292 * when creating those devices, and hence we should too when
293 * enumerating them. */
294 sound_a += strlen("/sound/card");
295 sound_a = strchr(sound_a, '/');
296
297 if (sound_a) {
298 unsigned prefix_len;
299
300 prefix_len = sound_a - devpath_a;
301
302 if (strncmp(devpath_a, devpath_b, prefix_len) == 0) {
303 const char *sound_b;
304
305 sound_b = devpath_b + prefix_len;
306
307 if (startswith(sound_a, "/controlC") &&
308 !startswith(sound_b, "/contolC"))
309 return 1;
310
311 if (!startswith(sound_a, "/controlC") &&
312 startswith(sound_b, "/controlC"))
313 return -1;
314 }
315 }
316 }
317
318 /* md and dm devices are enumerated after all other devices */
319 delay_a = strstr(devpath_a, "/block/md") || strstr(devpath_a, "/block/dm-");
320 delay_b = strstr(devpath_b, "/block/md") || strstr(devpath_b, "/block/dm-");
321 if (delay_a != delay_b)
322 return delay_a - delay_b;
323
324 return strcmp(devpath_a, devpath_b);
325 }
326
327 int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device) {
328 int r;
329
330 assert_return(enumerator, -EINVAL);
331 assert_return(device, -EINVAL);
332
333 r = prioq_ensure_allocated(&enumerator->devices, device_compare);
334 if (r < 0)
335 return r;
336
337 r = prioq_put(enumerator->devices, device, NULL);
338 if (r < 0)
339 return r;
340
341 sd_device_ref(device);
342
343 return 0;
344 }
345
346 static bool match_sysattr_value(sd_device *device, const char *sysattr, const char *match_value) {
347 const char *value;
348 int r;
349
350 assert(device);
351 assert(sysattr);
352
353 r = sd_device_get_sysattr_value(device, sysattr, &value);
354 if (r < 0)
355 return false;
356
357 if (!match_value)
358 return true;
359
360 if (fnmatch(match_value, value, 0) == 0)
361 return true;
362
363 return false;
364 }
365
366 static bool match_sysattr(sd_device_enumerator *enumerator, sd_device *device) {
367 const char *sysattr;
368 const char *value;
369 Iterator i;
370
371 assert(enumerator);
372 assert(device);
373
374 HASHMAP_FOREACH_KEY(value, sysattr, enumerator->nomatch_sysattr, i)
375 if (match_sysattr_value(device, sysattr, value))
376 return false;
377
378 HASHMAP_FOREACH_KEY(value, sysattr, enumerator->match_sysattr, i)
379 if (!match_sysattr_value(device, sysattr, value))
380 return false;
381
382 return true;
383 }
384
385 static bool match_property(sd_device_enumerator *enumerator, sd_device *device) {
386 const char *property;
387 const char *value;
388 Iterator i;
389
390 assert(enumerator);
391 assert(device);
392
393 if (hashmap_isempty(enumerator->match_property))
394 return true;
395
396 HASHMAP_FOREACH_KEY(value, property, enumerator->match_property, i) {
397 const char *property_dev, *value_dev;
398
399 FOREACH_DEVICE_PROPERTY(device, property_dev, value_dev) {
400 if (fnmatch(property, property_dev, 0) != 0)
401 continue;
402
403 if (!value && !value_dev)
404 return true;
405
406 if (!value || !value_dev)
407 continue;
408
409 if (fnmatch(value, value_dev, 0) == 0)
410 return true;
411 }
412 }
413
414 return false;
415 }
416
417 static bool match_tag(sd_device_enumerator *enumerator, sd_device *device) {
418 const char *tag;
419 Iterator i;
420
421 assert(enumerator);
422 assert(device);
423
424 SET_FOREACH(tag, enumerator->match_tag, i)
425 if (!sd_device_has_tag(device, tag))
426 return false;
427
428 return true;
429 }
430
431 static bool match_parent(sd_device_enumerator *enumerator, sd_device *device) {
432 const char *devpath, *devpath_dev;
433 int r;
434
435 assert(enumerator);
436 assert(device);
437
438 if (!enumerator->match_parent)
439 return true;
440
441 r = sd_device_get_devpath(enumerator->match_parent, &devpath);
442 assert(r >= 0);
443
444 r = sd_device_get_devpath(device, &devpath_dev);
445 assert(r >= 0);
446
447 return startswith(devpath_dev, devpath);
448 }
449
450 static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname) {
451 const char *sysname_match;
452 Iterator i;
453
454 assert(enumerator);
455 assert(sysname);
456
457 if (set_isempty(enumerator->match_sysname))
458 return true;
459
460 SET_FOREACH(sysname_match, enumerator->match_sysname, i)
461 if (fnmatch(sysname_match, sysname, 0) == 0)
462 return true;
463
464 return false;
465 }
466
467 static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator, const char *basedir, const char *subdir1, const char *subdir2) {
468 _cleanup_closedir_ DIR *dir = NULL;
469 char *path;
470 struct dirent *dent;
471 int r = 0;
472
473 assert(enumerator);
474 assert(basedir);
475
476 path = strjoina("/sys/", basedir, "/");
477
478 if (subdir1)
479 path = strjoina(path, subdir1, "/");
480
481 if (subdir2)
482 path = strjoina(path, subdir2, "/");
483
484 dir = opendir(path);
485 if (!dir)
486 return -errno;
487
488 FOREACH_DIRENT_ALL(dent, dir, return -errno) {
489 _cleanup_device_unref_ sd_device *device = NULL;
490 char syspath[strlen(path) + 1 + strlen(dent->d_name) + 1];
491 dev_t devnum;
492 int ifindex, initialized, k;
493
494 if (dent->d_name[0] == '.')
495 continue;
496
497 if (!match_sysname(enumerator, dent->d_name))
498 continue;
499
500 (void)sprintf(syspath, "%s%s", path, dent->d_name);
501
502 k = sd_device_new_from_syspath(&device, syspath);
503 if (k < 0) {
504 if (k != -ENODEV)
505 /* this is necessarily racey, so ignore missing devices */
506 r = k;
507
508 continue;
509 }
510
511 k = sd_device_get_devnum(device, &devnum);
512 if (k < 0) {
513 r = k;
514 continue;
515 }
516
517 k = sd_device_get_ifindex(device, &ifindex);
518 if (k < 0) {
519 r = k;
520 continue;
521 }
522
523 k = sd_device_get_is_initialized(device, &initialized);
524 if (k < 0) {
525 r = k;
526 continue;
527 }
528
529 /*
530 * All devices with a device node or network interfaces
531 * possibly need udev to adjust the device node permission
532 * or context, or rename the interface before it can be
533 * reliably used from other processes.
534 *
535 * For now, we can only check these types of devices, we
536 * might not store a database, and have no way to find out
537 * for all other types of devices.
538 */
539 if (!enumerator->match_allow_uninitialized &&
540 !initialized &&
541 (major(devnum) > 0 || ifindex > 0))
542 continue;
543
544 if (!match_parent(enumerator, device))
545 continue;
546
547 if (!match_tag(enumerator, device))
548 continue;
549
550 if (!match_property(enumerator, device))
551 continue;
552
553 if (!match_sysattr(enumerator, device))
554 continue;
555
556 k = device_enumerator_add_device(enumerator, device);
557 if (k < 0)
558 r = k;
559 }
560
561 return r;
562 }
563
564 static bool match_subsystem(sd_device_enumerator *enumerator, const char *subsystem) {
565 const char *subsystem_match;
566 Iterator i;
567
568 assert(enumerator);
569
570 if (!subsystem)
571 return false;
572
573 SET_FOREACH(subsystem_match, enumerator->nomatch_subsystem, i)
574 if (fnmatch(subsystem_match, subsystem, 0) == 0)
575 return false;
576
577 if (set_isempty(enumerator->match_subsystem))
578 return true;
579
580 SET_FOREACH(subsystem_match, enumerator->match_subsystem, i)
581 if (fnmatch(subsystem_match, subsystem, 0) == 0)
582 return true;
583
584 return false;
585 }
586
587 static int enumerator_scan_dir(sd_device_enumerator *enumerator, const char *basedir, const char *subdir, const char *subsystem) {
588 _cleanup_closedir_ DIR *dir = NULL;
589 char *path;
590 struct dirent *dent;
591 int r = 0;
592
593 path = strjoina("/sys/", basedir);
594
595 dir = opendir(path);
596 if (!dir)
597 return -errno;
598
599 log_debug(" device-enumerator: scanning %s", path);
600
601 FOREACH_DIRENT_ALL(dent, dir, return -errno) {
602 int k;
603
604 if (dent->d_name[0] == '.')
605 continue;
606
607 if (!match_subsystem(enumerator, subsystem ? : dent->d_name))
608 continue;
609
610 k = enumerator_scan_dir_and_add_devices(enumerator, basedir, dent->d_name, subdir);
611 if (k < 0)
612 r = k;
613 }
614
615 return r;
616 }
617
618 static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const char *tag) {
619 _cleanup_closedir_ DIR *dir = NULL;
620 char *path;
621 struct dirent *dent;
622 int r = 0;
623
624 assert(enumerator);
625 assert(tag);
626
627 path = strjoina("/run/udev/tags/", tag);
628
629 dir = opendir(path);
630 if (!dir) {
631 if (errno == ENOENT)
632 return 0;
633 else {
634 log_error("sd-device-enumerator: could not open tags directory %s: %m", path);
635 return -errno;
636 }
637 }
638
639 /* TODO: filter away subsystems? */
640
641 FOREACH_DIRENT_ALL(dent, dir, return -errno) {
642 _cleanup_device_unref_ 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;
699
700 assert(enumerator);
701
702 SET_FOREACH(tag, enumerator->match_tag, i) {
703 r = enumerator_scan_devices_tag(enumerator, tag);
704 if (r < 0)
705 return r;
706 }
707
708 return 0;
709 }
710
711 static int parent_add_child(sd_device_enumerator *enumerator, const char *path) {
712 _cleanup_device_unref_ sd_device *device = NULL;
713 const char *subsystem, *sysname;
714 int r;
715
716 r = sd_device_new_from_syspath(&device, path);
717 if (r == -ENODEV)
718 /* this is necessarily racy, so ignore missing devices */
719 return 0;
720 else if (r < 0)
721 return r;
722
723 r = sd_device_get_subsystem(device, &subsystem);
724 if (r == -ENOENT)
725 return 0;
726 if (r < 0)
727 return r;
728
729 if (!match_subsystem(enumerator, subsystem))
730 return 0;
731
732 r = sd_device_get_sysname(device, &sysname);
733 if (r < 0)
734 return r;
735
736 if (!match_sysname(enumerator, sysname))
737 return 0;
738
739 if (!match_property(enumerator, device))
740 return 0;
741
742 if (!match_sysattr(enumerator, device))
743 return 0;
744
745 r = device_enumerator_add_device(enumerator, device);
746 if (r < 0)
747 return r;
748
749 return 1;
750 }
751
752 static int parent_crawl_children(sd_device_enumerator *enumerator, const char *path, unsigned maxdepth) {
753 _cleanup_closedir_ DIR *dir = NULL;
754 struct dirent *dent;
755 int r = 0;
756
757 dir = opendir(path);
758 if (!dir) {
759 log_debug("sd-device-enumerate: could not open parent directory %s: %m", path);
760 return -errno;
761 }
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, NULL);
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;
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 r = enumerator_scan_devices_tags(enumerator);
853 if (r < 0)
854 return r;
855 } else if (enumerator->match_parent) {
856 r = enumerator_scan_devices_children(enumerator);
857 if (r < 0)
858 return r;
859 } else {
860 r = enumerator_scan_devices_all(enumerator);
861 if (r < 0)
862 return r;
863 }
864
865 enumerator->scan_uptodate = true;
866
867 return 0;
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 }