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