chiark / gitweb /
dbus-common: Add helper method to handle no-reply messages
[elogind.git] / src / libudev / libudev-enumerate.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stddef.h>
23 #include <unistd.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <dirent.h>
27 #include <fnmatch.h>
28 #include <stdbool.h>
29 #include <sys/stat.h>
30 #include <sys/param.h>
31
32 #include "libudev.h"
33 #include "libudev-private.h"
34
35 /**
36  * SECTION:libudev-enumerate
37  * @short_description: lookup and sort sys devices
38  *
39  * Lookup devices in the sys filesystem, filter devices by properties,
40  * and return a sorted list of devices.
41  */
42
43 struct syspath {
44         char *syspath;
45         size_t len;
46 };
47
48 /**
49  * udev_enumerate:
50  *
51  * Opaque object representing one device lookup/sort context.
52  */
53 struct udev_enumerate {
54         struct udev *udev;
55         int refcount;
56         struct udev_list sysattr_match_list;
57         struct udev_list sysattr_nomatch_list;
58         struct udev_list subsystem_match_list;
59         struct udev_list subsystem_nomatch_list;
60         struct udev_list sysname_match_list;
61         struct udev_list properties_match_list;
62         struct udev_list tags_match_list;
63         struct udev_device *parent_match;
64         struct udev_list devices_list;
65         struct syspath *devices;
66         unsigned int devices_cur;
67         unsigned int devices_max;
68         bool devices_uptodate:1;
69         bool match_is_initialized;
70 };
71
72 /**
73  * udev_enumerate_new:
74  * @udev: udev library context
75  *
76  * Create an enumeration context to scan /sys.
77  *
78  * Returns: an enumeration context.
79  **/
80 _public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev)
81 {
82         struct udev_enumerate *udev_enumerate;
83
84         udev_enumerate = calloc(1, sizeof(struct udev_enumerate));
85         if (udev_enumerate == NULL)
86                 return NULL;
87         udev_enumerate->refcount = 1;
88         udev_enumerate->udev = udev;
89         udev_list_init(udev, &udev_enumerate->sysattr_match_list, false);
90         udev_list_init(udev, &udev_enumerate->sysattr_nomatch_list, false);
91         udev_list_init(udev, &udev_enumerate->subsystem_match_list, true);
92         udev_list_init(udev, &udev_enumerate->subsystem_nomatch_list, true);
93         udev_list_init(udev, &udev_enumerate->sysname_match_list, true);
94         udev_list_init(udev, &udev_enumerate->properties_match_list, false);
95         udev_list_init(udev, &udev_enumerate->tags_match_list, true);
96         udev_list_init(udev, &udev_enumerate->devices_list, false);
97         return udev_enumerate;
98 }
99
100 /**
101  * udev_enumerate_ref:
102  * @udev_enumerate: context
103  *
104  * Take a reference of a enumeration context.
105  *
106  * Returns: the passed enumeration context
107  **/
108 _public_ struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate)
109 {
110         if (udev_enumerate == NULL)
111                 return NULL;
112         udev_enumerate->refcount++;
113         return udev_enumerate;
114 }
115
116 /**
117  * udev_enumerate_unref:
118  * @udev_enumerate: context
119  *
120  * Drop a reference of an enumeration context. If the refcount reaches zero,
121  * all resources of the enumeration context will be released.
122  *
123  * Returns: the passed enumeration context if it has still an active reference, or #NULL otherwise.
124  **/
125 _public_ struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate)
126 {
127         unsigned int i;
128
129         if (udev_enumerate == NULL)
130                 return NULL;
131         udev_enumerate->refcount--;
132         if (udev_enumerate->refcount > 0)
133                 return udev_enumerate;
134         udev_list_cleanup(&udev_enumerate->sysattr_match_list);
135         udev_list_cleanup(&udev_enumerate->sysattr_nomatch_list);
136         udev_list_cleanup(&udev_enumerate->subsystem_match_list);
137         udev_list_cleanup(&udev_enumerate->subsystem_nomatch_list);
138         udev_list_cleanup(&udev_enumerate->sysname_match_list);
139         udev_list_cleanup(&udev_enumerate->properties_match_list);
140         udev_list_cleanup(&udev_enumerate->tags_match_list);
141         udev_device_unref(udev_enumerate->parent_match);
142         udev_list_cleanup(&udev_enumerate->devices_list);
143         for (i = 0; i < udev_enumerate->devices_cur; i++)
144                 free(udev_enumerate->devices[i].syspath);
145         free(udev_enumerate->devices);
146         free(udev_enumerate);
147         return NULL;
148 }
149
150 /**
151  * udev_enumerate_get_udev:
152  * @udev_enumerate: context
153  *
154  * Get the udev library context.
155  *
156  * Returns: a pointer to the context.
157  */
158 _public_ struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate)
159 {
160         if (udev_enumerate == NULL)
161                 return NULL;
162         return udev_enumerate->udev;
163 }
164
165 static int syspath_add(struct udev_enumerate *udev_enumerate, const char *syspath)
166 {
167         char *path;
168         struct syspath *entry;
169
170         /* double array size if needed */
171         if (udev_enumerate->devices_cur >= udev_enumerate->devices_max) {
172                 struct syspath *buf;
173                 unsigned int add;
174
175                 add = udev_enumerate->devices_max;
176                 if (add < 1024)
177                         add = 1024;
178                 buf = realloc(udev_enumerate->devices, (udev_enumerate->devices_max + add) * sizeof(struct syspath));
179                 if (buf == NULL)
180                         return -ENOMEM;
181                 udev_enumerate->devices = buf;
182                 udev_enumerate->devices_max += add;
183         }
184
185         path = strdup(syspath);
186         if (path == NULL)
187                 return -ENOMEM;
188         entry = &udev_enumerate->devices[udev_enumerate->devices_cur];
189         entry->syspath = path;
190         entry->len = strlen(path);
191         udev_enumerate->devices_cur++;
192         udev_enumerate->devices_uptodate = false;
193         return 0;
194 }
195
196 static int syspath_cmp(const void *p1, const void *p2)
197 {
198         const struct syspath *path1 = p1;
199         const struct syspath *path2 = p2;
200         size_t len;
201         int ret;
202
203         len = MIN(path1->len, path2->len);
204         ret = memcmp(path1->syspath, path2->syspath, len);
205         if (ret == 0) {
206                 if (path1->len < path2->len)
207                         ret = -1;
208                 else if (path1->len > path2->len)
209                         ret = 1;
210         }
211         return ret;
212 }
213
214 /* For devices that should be moved to the absolute end of the list */
215 static bool devices_delay_end(struct udev *udev, const char *syspath)
216 {
217         static const char *delay_device_list[] = {
218                 "/block/md",
219                 "/block/dm-",
220                 NULL
221         };
222         int i;
223
224         for (i = 0; delay_device_list[i] != NULL; i++) {
225                 if (strstr(syspath + strlen("/sys"), delay_device_list[i]) != NULL)
226                         return true;
227         }
228         return false;
229 }
230
231 /* For devices that should just be moved a little bit later, just
232  * before the point where some common path prefix changes. Returns the
233  * number of characters that make up that common prefix */
234 static size_t devices_delay_later(struct udev *udev, const char *syspath)
235 {
236         const char *c;
237
238         /* For sound cards the control device must be enumerated last
239          * to make sure it's the final device node that gets ACLs
240          * applied. Applications rely on this fact and use ACL changes
241          * on the control node as an indicator that the ACL change of
242          * the entire sound card completed. The kernel makes this
243          * guarantee when creating those devices, and hence we should
244          * too when enumerating them. */
245
246         if ((c = strstr(syspath, "/sound/card"))) {
247                 c += 11;
248                 c += strcspn(c, "/");
249
250                 if (startswith(c, "/controlC"))
251                         return c - syspath + 1;
252         }
253
254         return 0;
255 }
256
257 /**
258  * udev_enumerate_get_list_entry:
259  * @udev_enumerate: context
260  *
261  * Get the first entry of the sorted list of device paths.
262  *
263  * Returns: a udev_list_entry.
264  */
265 _public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate)
266 {
267         if (udev_enumerate == NULL)
268                 return NULL;
269         if (!udev_enumerate->devices_uptodate) {
270                 unsigned int i;
271                 unsigned int max;
272                 struct syspath *prev = NULL, *move_later = NULL;
273                 size_t move_later_prefix = 0;
274
275                 udev_list_cleanup(&udev_enumerate->devices_list);
276                 qsort(udev_enumerate->devices, udev_enumerate->devices_cur, sizeof(struct syspath), syspath_cmp);
277
278                 max = udev_enumerate->devices_cur;
279                 for (i = 0; i < max; i++) {
280                         struct syspath *entry = &udev_enumerate->devices[i];
281
282                         /* skip duplicated entries */
283                         if (prev != NULL &&
284                             entry->len == prev->len &&
285                             memcmp(entry->syspath, prev->syspath, entry->len) == 0)
286                                 continue;
287                         prev = entry;
288
289                         /* skip to be delayed devices, and add them to the end of the list */
290                         if (devices_delay_end(udev_enumerate->udev, entry->syspath)) {
291                                 syspath_add(udev_enumerate, entry->syspath);
292                                 /* need to update prev here for the case realloc() gives a different address */
293                                 prev = &udev_enumerate->devices[i];
294                                 continue;
295                         }
296
297                         /* skip to be delayed devices, and move the to
298                          * the point where the prefix changes. We can
299                          * only move one item at a time. */
300                         if (!move_later) {
301                                 move_later_prefix = devices_delay_later(udev_enumerate->udev, entry->syspath);
302
303                                 if (move_later_prefix > 0) {
304                                         move_later = entry;
305                                         continue;
306                                 }
307                         }
308
309                         if (move_later &&
310                             strncmp(entry->syspath, move_later->syspath, move_later_prefix) != 0) {
311
312                                 udev_list_entry_add(&udev_enumerate->devices_list, move_later->syspath, NULL);
313                                 move_later = NULL;
314                         }
315
316                         udev_list_entry_add(&udev_enumerate->devices_list, entry->syspath, NULL);
317                 }
318
319                 if (move_later)
320                         udev_list_entry_add(&udev_enumerate->devices_list, move_later->syspath, NULL);
321
322                 /* add and cleanup delayed devices from end of list */
323                 for (i = max; i < udev_enumerate->devices_cur; i++) {
324                         struct syspath *entry = &udev_enumerate->devices[i];
325
326                         udev_list_entry_add(&udev_enumerate->devices_list, entry->syspath, NULL);
327                         free(entry->syspath);
328                 }
329                 udev_enumerate->devices_cur = max;
330
331                 udev_enumerate->devices_uptodate = true;
332         }
333         return udev_list_get_entry(&udev_enumerate->devices_list);
334 }
335
336 /**
337  * udev_enumerate_add_match_subsystem:
338  * @udev_enumerate: context
339  * @subsystem: filter for a subsystem of the device to include in the list
340  *
341  * Match only devices belonging to a certain kernel subsystem.
342  *
343  * Returns: 0 on success, otherwise a negative error value.
344  */
345 _public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem)
346 {
347         if (udev_enumerate == NULL)
348                 return -EINVAL;
349         if (subsystem == NULL)
350                 return 0;
351         if (udev_list_entry_add(&udev_enumerate->subsystem_match_list, subsystem, NULL) == NULL)
352                 return -ENOMEM;
353         return 0;
354 }
355
356 /**
357  * udev_enumerate_add_nomatch_subsystem:
358  * @udev_enumerate: context
359  * @subsystem: filter for a subsystem of the device to exclude from the list
360  *
361  * Match only devices not belonging to a certain kernel subsystem.
362  *
363  * Returns: 0 on success, otherwise a negative error value.
364  */
365 _public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem)
366 {
367         if (udev_enumerate == NULL)
368                 return -EINVAL;
369         if (subsystem == NULL)
370                 return 0;
371         if (udev_list_entry_add(&udev_enumerate->subsystem_nomatch_list, subsystem, NULL) == NULL)
372                 return -ENOMEM;
373         return 0;
374 }
375
376 /**
377  * udev_enumerate_add_match_sysattr:
378  * @udev_enumerate: context
379  * @sysattr: filter for a sys attribute at the device to include in the list
380  * @value: optional value of the sys attribute
381  *
382  * Match only devices with a certain /sys device attribute.
383  *
384  * Returns: 0 on success, otherwise a negative error value.
385  */
386 _public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value)
387 {
388         if (udev_enumerate == NULL)
389                 return -EINVAL;
390         if (sysattr == NULL)
391                 return 0;
392         if (udev_list_entry_add(&udev_enumerate->sysattr_match_list, sysattr, value) == NULL)
393                 return -ENOMEM;
394         return 0;
395 }
396
397 /**
398  * udev_enumerate_add_nomatch_sysattr:
399  * @udev_enumerate: context
400  * @sysattr: filter for a sys attribute at the device to exclude from the list
401  * @value: optional value of the sys attribute
402  *
403  * Match only devices not having a certain /sys device attribute.
404  *
405  * Returns: 0 on success, otherwise a negative error value.
406  */
407 _public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value)
408 {
409         if (udev_enumerate == NULL)
410                 return -EINVAL;
411         if (sysattr == NULL)
412                 return 0;
413         if (udev_list_entry_add(&udev_enumerate->sysattr_nomatch_list, sysattr, value) == NULL)
414                 return -ENOMEM;
415         return 0;
416 }
417
418 static int match_sysattr_value(struct udev_device *dev, const char *sysattr, const char *match_val)
419 {
420         const char *val = NULL;
421         bool match = false;
422
423         val = udev_device_get_sysattr_value(dev, sysattr);
424         if (val == NULL)
425                 goto exit;
426         if (match_val == NULL) {
427                 match = true;
428                 goto exit;
429         }
430         if (fnmatch(match_val, val, 0) == 0) {
431                 match = true;
432                 goto exit;
433         }
434 exit:
435         return match;
436 }
437
438 /**
439  * udev_enumerate_add_match_property:
440  * @udev_enumerate: context
441  * @property: filter for a property of the device to include in the list
442  * @value: value of the property
443  *
444  * Match only devices with a certain property.
445  *
446  * Returns: 0 on success, otherwise a negative error value.
447  */
448 _public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value)
449 {
450         if (udev_enumerate == NULL)
451                 return -EINVAL;
452         if (property == NULL)
453                 return 0;
454         if (udev_list_entry_add(&udev_enumerate->properties_match_list, property, value) == NULL)
455                 return -ENOMEM;
456         return 0;
457 }
458
459 /**
460  * udev_enumerate_add_match_tag:
461  * @udev_enumerate: context
462  * @tag: filter for a tag of the device to include in the list
463  *
464  * Match only devices with a certain tag.
465  *
466  * Returns: 0 on success, otherwise a negative error value.
467  */
468 _public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag)
469 {
470         if (udev_enumerate == NULL)
471                 return -EINVAL;
472         if (tag == NULL)
473                 return 0;
474         if (udev_list_entry_add(&udev_enumerate->tags_match_list, tag, NULL) == NULL)
475                 return -ENOMEM;
476         return 0;
477 }
478
479 /**
480  * udev_enumerate_add_match_parent:
481  * @udev_enumerate: context
482  * @parent: parent device where to start searching
483  *
484  * Return the devices on the subtree of one given device. The parent
485  * itself is included in the list.
486  *
487  * A reference for the device is held until the udev_enumerate context
488  * is cleaned up.
489  *
490  * Returns: 0 on success, otherwise a negative error value.
491  */
492 _public_ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent)
493 {
494         if (udev_enumerate == NULL)
495                 return -EINVAL;
496         if (parent == NULL)
497                 return 0;
498         if (udev_enumerate->parent_match != NULL)
499                 udev_device_unref(udev_enumerate->parent_match);
500         udev_enumerate->parent_match = udev_device_ref(parent);
501         return 0;
502 }
503
504 /**
505  * udev_enumerate_add_match_is_initialized:
506  * @udev_enumerate: context
507  *
508  * Match only devices which udev has set up already. This makes
509  * sure, that the device node permissions and context are properly set
510  * and that network devices are fully renamed.
511  *
512  * Usually, devices which are found in the kernel but not already
513  * handled by udev, have still pending events. Services should subscribe
514  * to monitor events and wait for these devices to become ready, instead
515  * of using uninitialized devices.
516  *
517  * For now, this will not affect devices which do not have a device node
518  * and are not network interfaces.
519  *
520  * Returns: 0 on success, otherwise a negative error value.
521  */
522 _public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate)
523 {
524         if (udev_enumerate == NULL)
525                 return -EINVAL;
526         udev_enumerate->match_is_initialized = true;
527         return 0;
528 }
529
530 /**
531  * udev_enumerate_add_match_sysname:
532  * @udev_enumerate: context
533  * @sysname: filter for the name of the device to include in the list
534  *
535  * Match only devices with a given /sys device name.
536  *
537  * Returns: 0 on success, otherwise a negative error value.
538  */
539 _public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname)
540 {
541         if (udev_enumerate == NULL)
542                 return -EINVAL;
543         if (sysname == NULL)
544                 return 0;
545         if (udev_list_entry_add(&udev_enumerate->sysname_match_list, sysname, NULL) == NULL)
546                 return -ENOMEM;
547         return 0;
548 }
549
550 static bool match_sysattr(struct udev_enumerate *udev_enumerate, struct udev_device *dev)
551 {
552         struct udev_list_entry *list_entry;
553
554         /* skip list */
555         udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysattr_nomatch_list)) {
556                 if (match_sysattr_value(dev, udev_list_entry_get_name(list_entry),
557                                         udev_list_entry_get_value(list_entry)))
558                         return false;
559         }
560         /* include list */
561         if (udev_list_get_entry(&udev_enumerate->sysattr_match_list) != NULL) {
562                 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysattr_match_list)) {
563                         /* anything that does not match, will make it FALSE */
564                         if (!match_sysattr_value(dev, udev_list_entry_get_name(list_entry),
565                                                  udev_list_entry_get_value(list_entry)))
566                                 return false;
567                 }
568                 return true;
569         }
570         return true;
571 }
572
573 static bool match_property(struct udev_enumerate *udev_enumerate, struct udev_device *dev)
574 {
575         struct udev_list_entry *list_entry;
576         bool match = false;
577
578         /* no match always matches */
579         if (udev_list_get_entry(&udev_enumerate->properties_match_list) == NULL)
580                 return true;
581
582         /* loop over matches */
583         udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->properties_match_list)) {
584                 const char *match_key = udev_list_entry_get_name(list_entry);
585                 const char *match_value = udev_list_entry_get_value(list_entry);
586                 struct udev_list_entry *property_entry;
587
588                 /* loop over device properties */
589                 udev_list_entry_foreach(property_entry, udev_device_get_properties_list_entry(dev)) {
590                         const char *dev_key = udev_list_entry_get_name(property_entry);
591                         const char *dev_value = udev_list_entry_get_value(property_entry);
592
593                         if (fnmatch(match_key, dev_key, 0) != 0)
594                                 continue;
595                         if (match_value == NULL && dev_value == NULL) {
596                                 match = true;
597                                 goto out;
598                         }
599                         if (match_value == NULL || dev_value == NULL)
600                                 continue;
601                         if (fnmatch(match_value, dev_value, 0) == 0) {
602                                 match = true;
603                                 goto out;
604                         }
605                 }
606         }
607 out:
608         return match;
609 }
610
611 static bool match_tag(struct udev_enumerate *udev_enumerate, struct udev_device *dev)
612 {
613         struct udev_list_entry *list_entry;
614
615         /* no match always matches */
616         if (udev_list_get_entry(&udev_enumerate->tags_match_list) == NULL)
617                 return true;
618
619         /* loop over matches */
620         udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->tags_match_list))
621                 if (!udev_device_has_tag(dev, udev_list_entry_get_name(list_entry)))
622                         return false;
623
624         return true;
625 }
626
627 static bool match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *dev)
628 {
629         if (udev_enumerate->parent_match == NULL)
630                 return true;
631
632         return startswith(udev_device_get_devpath(dev), udev_device_get_devpath(udev_enumerate->parent_match));
633 }
634
635 static bool match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname)
636 {
637         struct udev_list_entry *list_entry;
638
639         if (udev_list_get_entry(&udev_enumerate->sysname_match_list) == NULL)
640                 return true;
641
642         udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysname_match_list)) {
643                 if (fnmatch(udev_list_entry_get_name(list_entry), sysname, 0) != 0)
644                         continue;
645                 return true;
646         }
647         return false;
648 }
649
650 static int scan_dir_and_add_devices(struct udev_enumerate *udev_enumerate,
651                                     const char *basedir, const char *subdir1, const char *subdir2)
652 {
653         char path[UTIL_PATH_SIZE];
654         size_t l;
655         char *s;
656         DIR *dir;
657         struct dirent *dent;
658
659         s = path;
660         l = util_strpcpyl(&s, sizeof(path), "/sys/", basedir, NULL);
661         if (subdir1 != NULL)
662                 l = util_strpcpyl(&s, l, "/", subdir1, NULL);
663         if (subdir2 != NULL)
664                 util_strpcpyl(&s, l, "/", subdir2, NULL);
665         dir = opendir(path);
666         if (dir == NULL)
667                 return -ENOENT;
668         for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
669                 char syspath[UTIL_PATH_SIZE];
670                 struct udev_device *dev;
671
672                 if (dent->d_name[0] == '.')
673                         continue;
674
675                 if (!match_sysname(udev_enumerate, dent->d_name))
676                         continue;
677
678                 util_strscpyl(syspath, sizeof(syspath), path, "/", dent->d_name, NULL);
679                 dev = udev_device_new_from_syspath(udev_enumerate->udev, syspath);
680                 if (dev == NULL)
681                         continue;
682
683                 if (udev_enumerate->match_is_initialized) {
684                         /*
685                          * All devices with a device node or network interfaces
686                          * possibly need udev to adjust the device node permission
687                          * or context, or rename the interface before it can be
688                          * reliably used from other processes.
689                          *
690                          * For now, we can only check these types of devices, we
691                          * might not store a database, and have no way to find out
692                          * for all other types of devices.
693                          */
694                         if (!udev_device_get_is_initialized(dev) &&
695                             (major(udev_device_get_devnum(dev)) > 0 || udev_device_get_ifindex(dev) > 0))
696                                 goto nomatch;
697                 }
698                 if (!match_parent(udev_enumerate, dev))
699                         goto nomatch;
700                 if (!match_tag(udev_enumerate, dev))
701                         goto nomatch;
702                 if (!match_property(udev_enumerate, dev))
703                         goto nomatch;
704                 if (!match_sysattr(udev_enumerate, dev))
705                         goto nomatch;
706
707                 syspath_add(udev_enumerate, udev_device_get_syspath(dev));
708 nomatch:
709                 udev_device_unref(dev);
710         }
711         closedir(dir);
712         return 0;
713 }
714
715 static bool match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem)
716 {
717         struct udev_list_entry *list_entry;
718
719         udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->subsystem_nomatch_list)) {
720                 if (fnmatch(udev_list_entry_get_name(list_entry), subsystem, 0) == 0)
721                         return false;
722         }
723         if (udev_list_get_entry(&udev_enumerate->subsystem_match_list) != NULL) {
724                 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->subsystem_match_list)) {
725                         if (fnmatch(udev_list_entry_get_name(list_entry), subsystem, 0) == 0)
726                                 return true;
727                 }
728                 return false;
729         }
730         return true;
731 }
732
733 static int scan_dir(struct udev_enumerate *udev_enumerate, const char *basedir, const char *subdir, const char *subsystem)
734 {
735         char path[UTIL_PATH_SIZE];
736         DIR *dir;
737         struct dirent *dent;
738
739         util_strscpyl(path, sizeof(path), "/sys/", basedir, NULL);
740         dir = opendir(path);
741         if (dir == NULL)
742                 return -1;
743         for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
744                 if (dent->d_name[0] == '.')
745                         continue;
746                 if (!match_subsystem(udev_enumerate, subsystem != NULL ? subsystem : dent->d_name))
747                         continue;
748                 scan_dir_and_add_devices(udev_enumerate, basedir, dent->d_name, subdir);
749         }
750         closedir(dir);
751         return 0;
752 }
753
754 /**
755  * udev_enumerate_add_syspath:
756  * @udev_enumerate: context
757  * @syspath: path of a device
758  *
759  * Add a device to the list of devices, to retrieve it back sorted in dependency order.
760  *
761  * Returns: 0 on success, otherwise a negative error value.
762  */
763 _public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath)
764 {
765         struct udev_device *udev_device;
766
767         if (udev_enumerate == NULL)
768                 return -EINVAL;
769         if (syspath == NULL)
770                 return 0;
771         /* resolve to real syspath */
772         udev_device = udev_device_new_from_syspath(udev_enumerate->udev, syspath);
773         if (udev_device == NULL)
774                 return -EINVAL;
775         syspath_add(udev_enumerate, udev_device_get_syspath(udev_device));
776         udev_device_unref(udev_device);
777         return 0;
778 }
779
780 static int scan_devices_tags(struct udev_enumerate *udev_enumerate)
781 {
782         struct udev_list_entry *list_entry;
783
784         /* scan only tagged devices, use tags reverse-index, instead of searching all devices in /sys */
785         udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->tags_match_list)) {
786                 DIR *dir;
787                 struct dirent *dent;
788                 char path[UTIL_PATH_SIZE];
789
790                 util_strscpyl(path, sizeof(path), "/run/udev/tags/", udev_list_entry_get_name(list_entry), NULL);
791                 dir = opendir(path);
792                 if (dir == NULL)
793                         continue;
794                 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
795                         struct udev_device *dev;
796
797                         if (dent->d_name[0] == '.')
798                                 continue;
799
800                         dev = udev_device_new_from_device_id(udev_enumerate->udev, dent->d_name);
801                         if (dev == NULL)
802                                 continue;
803
804                         if (!match_subsystem(udev_enumerate, udev_device_get_subsystem(dev)))
805                                 goto nomatch;
806                         if (!match_sysname(udev_enumerate, udev_device_get_sysname(dev)))
807                                 goto nomatch;
808                         if (!match_parent(udev_enumerate, dev))
809                                 goto nomatch;
810                         if (!match_property(udev_enumerate, dev))
811                                 goto nomatch;
812                         if (!match_sysattr(udev_enumerate, dev))
813                                 goto nomatch;
814
815                         syspath_add(udev_enumerate, udev_device_get_syspath(dev));
816 nomatch:
817                         udev_device_unref(dev);
818                 }
819                 closedir(dir);
820         }
821         return 0;
822 }
823
824 static int parent_add_child(struct udev_enumerate *enumerate, const char *path)
825 {
826         struct udev_device *dev;
827
828         dev = udev_device_new_from_syspath(enumerate->udev, path);
829         if (dev == NULL)
830                 return -ENODEV;
831
832         if (!match_subsystem(enumerate, udev_device_get_subsystem(dev)))
833                 return 0;
834         if (!match_sysname(enumerate, udev_device_get_sysname(dev)))
835                 return 0;
836         if (!match_property(enumerate, dev))
837                 return 0;
838         if (!match_sysattr(enumerate, dev))
839                 return 0;
840
841         syspath_add(enumerate, udev_device_get_syspath(dev));
842         udev_device_unref(dev);
843         return 1;
844 }
845
846 static int parent_crawl_children(struct udev_enumerate *enumerate, const char *path, int maxdepth)
847 {
848         DIR *d;
849         struct dirent *dent;
850
851         d = opendir(path);
852         if (d == NULL)
853                 return -errno;
854
855         for (dent = readdir(d); dent != NULL; dent = readdir(d)) {
856                 char *child;
857
858                 if (dent->d_name[0] == '.')
859                         continue;
860                 if (dent->d_type != DT_DIR)
861                         continue;
862                 if (asprintf(&child, "%s/%s", path, dent->d_name) < 0)
863                         continue;
864                 parent_add_child(enumerate, child);
865                 if (maxdepth > 0)
866                         parent_crawl_children(enumerate, child, maxdepth-1);
867                 free(child);
868         }
869
870         closedir(d);
871         return 0;
872 }
873
874 static int scan_devices_children(struct udev_enumerate *enumerate)
875 {
876         const char *path;
877
878         path = udev_device_get_syspath(enumerate->parent_match);
879         parent_add_child(enumerate, path);
880         return parent_crawl_children(enumerate, path, 256);
881 }
882
883 static int scan_devices_all(struct udev_enumerate *udev_enumerate)
884 {
885         struct stat statbuf;
886
887         if (stat("/sys/subsystem", &statbuf) == 0) {
888                 /* we have /subsystem/, forget all the old stuff */
889                 scan_dir(udev_enumerate, "subsystem", "devices", NULL);
890         } else {
891                 scan_dir(udev_enumerate, "bus", "devices", NULL);
892                 scan_dir(udev_enumerate, "class", NULL, NULL);
893         }
894         return 0;
895 }
896
897 /**
898  * udev_enumerate_scan_devices:
899  * @udev_enumerate: udev enumeration context
900  *
901  * Scan /sys for all devices which match the given filters. No matches
902  * will return all currently available devices.
903  *
904  * Returns: 0 on success, otherwise a negative error value.
905  **/
906 _public_ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate)
907 {
908         if (udev_enumerate == NULL)
909                 return -EINVAL;
910
911         /* efficiently lookup tags only, we maintain a reverse-index */
912         if (udev_list_get_entry(&udev_enumerate->tags_match_list) != NULL)
913                 return scan_devices_tags(udev_enumerate);
914
915         /* walk the subtree of one parent device only */
916         if (udev_enumerate->parent_match != NULL)
917                 return scan_devices_children(udev_enumerate);
918
919         /* scan devices of all subsystems */
920         return scan_devices_all(udev_enumerate);
921 }
922
923 /**
924  * udev_enumerate_scan_subsystems:
925  * @udev_enumerate: udev enumeration context
926  *
927  * Scan /sys for all kernel subsystems, including buses, classes, drivers.
928  *
929  * Returns: 0 on success, otherwise a negative error value.
930  **/
931 _public_ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate)
932 {
933         struct stat statbuf;
934         const char *subsysdir;
935
936         if (udev_enumerate == NULL)
937                 return -EINVAL;
938
939         /* all kernel modules */
940         if (match_subsystem(udev_enumerate, "module"))
941                 scan_dir_and_add_devices(udev_enumerate, "module", NULL, NULL);
942
943         if (stat("/sys/subsystem", &statbuf) == 0)
944                 subsysdir = "subsystem";
945         else
946                 subsysdir = "bus";
947
948         /* all subsystems (only buses support coldplug) */
949         if (match_subsystem(udev_enumerate, "subsystem"))
950                 scan_dir_and_add_devices(udev_enumerate, subsysdir, NULL, NULL);
951
952         /* all subsystem drivers */
953         if (match_subsystem(udev_enumerate, "drivers"))
954                 scan_dir(udev_enumerate, subsysdir, "drivers", "drivers");
955         return 0;
956 }