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