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