chiark / gitweb /
sd-device: enumerator - match only on initialized devices by default
[elogind.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 = false, delay_b = false;
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         if (strstr(devpath_a, "/block/md") || strstr(devpath_a, "/block/dm-"))
316                 delay_a = true;
317
318         if (strstr(devpath_b, "/block/md") || strstr(devpath_b, "/block/dm-"))
319                 delay_b = true;
320
321         if (delay_a && !delay_b)
322                 return 1;
323
324         if (!delay_a && delay_b)
325                 return -1;
326
327         return strcmp(devpath_a, devpath_b);
328 }
329
330 int device_enumerator_add_device(sd_device_enumerator *enumerator, sd_device *device) {
331         int r;
332
333         assert_return(enumerator, -EINVAL);
334         assert_return(device, -EINVAL);
335
336         r = prioq_ensure_allocated(&enumerator->devices, device_compare);
337         if (r < 0)
338                 return r;
339
340         r = prioq_put(enumerator->devices, device, NULL);
341         if (r < 0)
342                 return r;
343
344         sd_device_ref(device);
345
346         return 0;
347 }
348
349 static bool match_sysattr_value(sd_device *device, const char *sysattr, const char *match_value) {
350         const char *value;
351         int r;
352
353         assert(device);
354         assert(sysattr);
355
356         r = sd_device_get_sysattr_value(device, sysattr, &value);
357         if (r < 0)
358                 return false;
359
360         if (!match_value)
361                 return true;
362
363         if (fnmatch(match_value, value, 0) == 0)
364                 return true;
365
366         return false;
367 }
368
369 static bool match_sysattr(sd_device_enumerator *enumerator, sd_device *device) {
370         const char *sysattr;
371         const char *value;
372         Iterator i;
373
374         assert(enumerator);
375         assert(device);
376
377         HASHMAP_FOREACH_KEY(sysattr, value, enumerator->nomatch_sysattr, i)
378                 if (match_sysattr_value(device, sysattr, value))
379                         return false;
380
381         HASHMAP_FOREACH_KEY(sysattr, value, enumerator->match_sysattr, i)
382                 if (!match_sysattr_value(device, sysattr, value))
383                         return false;
384
385         return true;
386 }
387
388 static bool match_property(sd_device_enumerator *enumerator, sd_device *device) {
389         const char *property;
390         const char *value;
391         Iterator i;
392
393         assert(enumerator);
394         assert(device);
395
396         if (hashmap_isempty(enumerator->match_property))
397                 return true;
398
399         HASHMAP_FOREACH_KEY(property, value, enumerator->match_property, i) {
400                 const char *property_dev, *value_dev;
401
402                 FOREACH_DEVICE_PROPERTY(device, property_dev, value_dev) {
403                         if (fnmatch(property, property_dev, 0) != 0)
404                                 continue;
405
406                         if (!value && !value_dev)
407                                 return true;
408
409                         if (!value || !value_dev)
410                                 continue;
411
412                         if (fnmatch(value, value_dev, 0) == 0)
413                                 return true;
414                 }
415         }
416
417         return false;
418 }
419
420 static bool match_tag(sd_device_enumerator *enumerator, sd_device *device) {
421         const char *tag;
422         Iterator i;
423
424         assert(enumerator);
425         assert(device);
426
427         SET_FOREACH(tag, enumerator->match_tag, i)
428                 if (!sd_device_has_tag(device, tag))
429                         return false;
430
431         return true;
432 }
433
434 static bool match_parent(sd_device_enumerator *enumerator, sd_device *device) {
435         const char *devpath, *devpath_dev;
436         int r;
437
438         assert(enumerator);
439         assert(device);
440
441         if (!enumerator->match_parent)
442                 return true;
443
444         r = sd_device_get_devpath(enumerator->match_parent, &devpath);
445         assert(r >= 0);
446
447         r = sd_device_get_devpath(device, &devpath_dev);
448         assert(r >= 0);
449
450         return startswith(devpath_dev, devpath);
451 }
452
453 static bool match_sysname(sd_device_enumerator *enumerator, const char *sysname) {
454         const char *sysname_match;
455         Iterator i;
456
457         assert(enumerator);
458         assert(sysname);
459
460         if (set_isempty(enumerator->match_sysname))
461                 return true;
462
463         SET_FOREACH(sysname_match, enumerator->match_sysname, i)
464                 if (fnmatch(sysname_match, sysname, 0) == 0)
465                         return true;
466
467         return false;
468 }
469
470 static int enumerator_scan_dir_and_add_devices(sd_device_enumerator *enumerator, const char *basedir, const char *subdir1, const char *subdir2) {
471         _cleanup_closedir_ DIR *dir = NULL;
472         char *path;
473         struct dirent *dent;
474         int r = 0;
475
476         assert(enumerator);
477         assert(basedir);
478
479         path = strjoina("/sys/", basedir, "/");
480
481         if (subdir1)
482                 path = strjoina(path, subdir1, "/");
483
484         if (subdir2)
485                 path = strjoina(path, subdir2, "/");
486
487         dir = opendir(path);
488         if (!dir)
489                 return -errno;
490
491         FOREACH_DIRENT_ALL(dent, dir, return -errno) {
492                 _cleanup_device_unref_ sd_device *device = NULL;
493                 char syspath[strlen(path) + 1 + strlen(dent->d_name) + 1];
494                 dev_t devnum;
495                 int ifindex, initialized, k;
496
497                 if (dent->d_name[0] == '.')
498                         continue;
499
500                 if (!match_sysname(enumerator, dent->d_name))
501                         continue;
502
503                 (void)sprintf(syspath, "%s%s", path, dent->d_name);
504
505                 k = sd_device_new_from_syspath(&device, syspath);
506                 if (k < 0) {
507                         log_debug_errno(k, "device-enumerator: failed to create device from syspath %s: %m", syspath);
508                         r = k;
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                         log_error("sd-device-enumerator: could not open tags directory %s: %m", path);
636                         return -errno;
637                 }
638         }
639
640         /* TODO: filter away subsystems? */
641
642         FOREACH_DIRENT_ALL(dent, dir, return -errno) {
643                 _cleanup_device_unref_ sd_device *device = NULL;
644                 const char *subsystem, *sysname;
645                 int k;
646
647                 if (dent->d_name[0] == '.')
648                         continue;
649
650                 k = sd_device_new_from_device_id(&device, dent->d_name);
651                 if (k < 0) {
652                         r = k;
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 == -ENOENT)
716                 return 0;
717         else if (r < 0)
718                 return r;
719
720         r = sd_device_get_subsystem(device, &subsystem);
721         if (r < 0)
722                 return r;
723
724         if (!match_subsystem(enumerator, subsystem))
725                 return 0;
726
727         r = sd_device_get_sysname(device, &sysname);
728         if (r < 0)
729                 return r;
730
731         if (!match_sysname(enumerator, sysname))
732                 return 0;
733
734         if (!match_property(enumerator, device))
735                 return 0;
736
737         if (!match_sysattr(enumerator, device))
738                 return 0;
739
740         r = device_enumerator_add_device(enumerator, device);
741         if (r < 0)
742                 return r;
743
744         return 1;
745 }
746
747 static int parent_crawl_children(sd_device_enumerator *enumerator, const char *path, unsigned maxdepth) {
748         _cleanup_closedir_ DIR *dir = NULL;
749         struct dirent *dent;
750         int r = 0;
751
752         dir = opendir(path);
753         if (!dir) {
754                 log_debug("sd-device-enumerate: could not open parent directory %s: %m", path);
755                 return -errno;
756         }
757
758         FOREACH_DIRENT_ALL(dent, dir, return -errno) {
759                 _cleanup_free_ char *child = NULL;
760                 int k;
761
762                 if (dent->d_name[0] == '.')
763                         continue;
764
765                 if (dent->d_type != DT_DIR)
766                         continue;
767
768                 k = asprintf(&child, "%s/%s", path, dent->d_name);
769                 if (k < 0)
770                         return -errno;
771
772                 k = parent_add_child(enumerator, child);
773                 if (k < 0)
774                         r = k;
775
776                 if (maxdepth > 0)
777                         parent_crawl_children(enumerator, child, maxdepth - 1);
778                 else
779                         log_debug("device-enumerate: max depth reached, %s: ignoring devices", child);
780         }
781
782         return r;
783 }
784
785 static int enumerator_scan_devices_children(sd_device_enumerator *enumerator) {
786         const char *path;
787         int r = 0, k;
788
789         r = sd_device_get_syspath(enumerator->match_parent, &path);
790         if (r < 0)
791                 return r;
792
793         k = parent_add_child(enumerator, path);
794         if (k < 0)
795                 r = k;
796
797         k = parent_crawl_children(enumerator, path, DEVICE_ENUMERATE_MAX_DEPTH);
798         if (k < 0)
799                 r = k;
800
801         return r;
802 }
803
804 static int enumerator_scan_devices_all(sd_device_enumerator *enumerator) {
805         int r = 0;
806
807         log_debug("device-enumerator: scan all dirs");
808
809         if (access("/sys/subsystem", F_OK) >= 0) {
810                 /* we have /subsystem/, forget all the old stuff */
811                 r = enumerator_scan_dir(enumerator, "subsystem", "devices", NULL);
812                 if (r < 0) {
813                         log_debug("device-enumerator: failed to scan /sys/subsystem: %s", strerror(-r));
814                         return r;
815                 }
816         } else {
817                 int k;
818
819                 k = enumerator_scan_dir(enumerator, "bus", "devices", NULL);
820                 if (k < 0) {
821                         log_debug_errno(k, "device-enumerator: failed to scan /sys/bus: %m");
822                         r = k;
823                 }
824
825                 k = enumerator_scan_dir(enumerator, "class", NULL, NULL);
826                 if (k < 0) {
827                         log_debug_errno(k, "device-enumerator: failed to scan /sys/class: %m");
828                         r = k;
829                 }
830         }
831
832         return r;
833 }
834
835 int device_enumerator_scan_devices(sd_device_enumerator *enumerator) {
836         sd_device *device;
837         int r;
838
839         assert(enumerator);
840
841         if (enumerator->scan_uptodate &&
842             enumerator->type == DEVICE_ENUMERATION_TYPE_DEVICES)
843                 return 0;
844
845         while ((device = prioq_pop(enumerator->devices)))
846                 sd_device_unref(device);
847
848         if (!set_isempty(enumerator->match_tag)) {
849                 r = enumerator_scan_devices_tags(enumerator);
850                 if (r < 0)
851                         return r;
852         } else if (enumerator->match_parent) {
853                 r = enumerator_scan_devices_children(enumerator);
854                 if (r < 0)
855                         return r;
856         } else {
857                 r = enumerator_scan_devices_all(enumerator);
858                 if (r < 0)
859                         return r;
860         }
861
862         enumerator->scan_uptodate = true;
863
864         return 0;
865 }
866
867 _public_ sd_device *sd_device_enumerator_get_device_first(sd_device_enumerator *enumerator) {
868         int r;
869
870         assert_return(enumerator, NULL);
871
872         r = device_enumerator_scan_devices(enumerator);
873         if (r < 0)
874                 return NULL;
875
876         enumerator->type = DEVICE_ENUMERATION_TYPE_DEVICES;
877
878         return prioq_peek(enumerator->devices);
879 }
880
881 _public_ sd_device *sd_device_enumerator_get_device_next(sd_device_enumerator *enumerator) {
882         assert_return(enumerator, NULL);
883
884         if (!enumerator->scan_uptodate ||
885             enumerator->type != DEVICE_ENUMERATION_TYPE_DEVICES)
886                 return NULL;
887
888         sd_device_unref(prioq_pop(enumerator->devices));
889
890         return prioq_peek(enumerator->devices);
891 }
892
893 int device_enumerator_scan_subsystems(sd_device_enumerator *enumerator) {
894         sd_device *device;
895         const char *subsysdir;
896         int r = 0, k;
897
898         assert(enumerator);
899
900         if (enumerator->scan_uptodate &&
901             enumerator->type == DEVICE_ENUMERATION_TYPE_SUBSYSTEMS)
902                 return 0;
903
904         while ((device = prioq_pop(enumerator->devices)))
905                 sd_device_unref(device);
906
907         /* modules */
908         if (match_subsystem(enumerator, "module")) {
909                 k = enumerator_scan_dir_and_add_devices(enumerator, "module", NULL, NULL);
910                 if (k < 0) {
911                         log_debug_errno(k, "device-enumerator: failed to scan modules: %m");
912                         r = k;
913                 }
914         }
915
916         if (access("/sys/subsystem", F_OK) >= 0)
917                 subsysdir = "subsystem";
918         else
919                 subsysdir = "bus";
920
921         /* subsystems (only buses support coldplug) */
922         if (match_subsystem(enumerator, "subsystem")) {
923                 k = enumerator_scan_dir_and_add_devices(enumerator, subsysdir, NULL, NULL);
924                 if (k < 0) {
925                         log_debug_errno(k, "device-enumerator: failed to scan subsystems: %m");
926                         r = k;
927                 }
928         }
929
930         /* subsystem drivers */
931         if (match_subsystem(enumerator, "drivers")) {
932                 k = enumerator_scan_dir(enumerator, subsysdir, "drivers", "drivers");
933                 if (k < 0) {
934                         log_debug_errno(k, "device-enumerator: failed to scan drivers: %m");
935                         r = k;
936                 }
937         }
938
939         enumerator->scan_uptodate = true;
940
941         return r;
942 }
943
944 _public_ sd_device *sd_device_enumerator_get_subsystem_first(sd_device_enumerator *enumerator) {
945         int r;
946
947         assert_return(enumerator, NULL);
948
949         r = device_enumerator_scan_subsystems(enumerator);
950         if (r < 0)
951                 return NULL;
952
953         enumerator->type = DEVICE_ENUMERATION_TYPE_SUBSYSTEMS;
954
955         return prioq_peek(enumerator->devices);
956 }
957
958 _public_ sd_device *sd_device_enumerator_get_subsystem_next(sd_device_enumerator *enumerator) {
959         assert_return(enumerator, NULL);
960
961         if (enumerator->scan_uptodate ||
962             enumerator->type != DEVICE_ENUMERATION_TYPE_SUBSYSTEMS)
963                 return NULL;
964
965         sd_device_unref(prioq_pop(enumerator->devices));
966
967         return prioq_peek(enumerator->devices);
968 }
969
970 sd_device *device_enumerator_get_first(sd_device_enumerator *enumerator) {
971         assert_return(enumerator, NULL);
972
973         return prioq_peek(enumerator->devices);
974 }
975
976 sd_device *device_enumerator_get_next(sd_device_enumerator *enumerator) {
977         assert_return(enumerator, NULL);
978
979         sd_device_unref(prioq_pop(enumerator->devices));
980
981         return prioq_peek(enumerator->devices);
982 }