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