2 * libudev - interface to udev device information
4 * Copyright (C) 2008-2010 Kay Sievers <kay.sievers@vrfy.org>
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.
22 #include <sys/param.h>
25 #include "libudev-private.h"
28 * SECTION:libudev-enumerate
29 * @short_description: lookup and sort sys devices
31 * Lookup devices in the sys filesystem, filter devices by properties,
32 * and return a sorted list of devices.
43 * Opaque object representing one device lookup/sort context.
45 struct udev_enumerate {
48 struct udev_list_node sysattr_match_list;
49 struct udev_list_node sysattr_nomatch_list;
50 struct udev_list_node subsystem_match_list;
51 struct udev_list_node subsystem_nomatch_list;
52 struct udev_list_node sysname_match_list;
53 struct udev_list_node properties_match_list;
54 struct udev_list_node tags_match_list;
55 struct udev_list_node devices_list;
56 struct syspath *devices;
57 unsigned int devices_cur;
58 unsigned int devices_max;
59 bool devices_uptodate:1;
64 * @udev: udev library context
66 * Returns: an enumeration context
68 struct udev_enumerate *udev_enumerate_new(struct udev *udev)
70 struct udev_enumerate *udev_enumerate;
72 udev_enumerate = calloc(1, sizeof(struct udev_enumerate));
73 if (udev_enumerate == NULL)
75 udev_enumerate->refcount = 1;
76 udev_enumerate->udev = udev;
77 udev_list_init(&udev_enumerate->sysattr_match_list);
78 udev_list_init(&udev_enumerate->sysattr_nomatch_list);
79 udev_list_init(&udev_enumerate->subsystem_match_list);
80 udev_list_init(&udev_enumerate->subsystem_nomatch_list);
81 udev_list_init(&udev_enumerate->sysname_match_list);
82 udev_list_init(&udev_enumerate->properties_match_list);
83 udev_list_init(&udev_enumerate->tags_match_list);
84 udev_list_init(&udev_enumerate->devices_list);
85 return udev_enumerate;
90 * @udev_enumerate: context
92 * Take a reference of a enumeration context.
94 * Returns: the passed enumeration context
96 struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate)
98 if (udev_enumerate == NULL)
100 udev_enumerate->refcount++;
101 return udev_enumerate;
105 * udev_enumerate_unref:
106 * @udev_enumerate: context
108 * Drop a reference of an enumeration context. If the refcount reaches zero,
109 * all resources of the enumeration context will be released.
111 void udev_enumerate_unref(struct udev_enumerate *udev_enumerate)
115 if (udev_enumerate == NULL)
117 udev_enumerate->refcount--;
118 if (udev_enumerate->refcount > 0)
120 udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->sysattr_match_list);
121 udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->sysattr_nomatch_list);
122 udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->subsystem_match_list);
123 udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->subsystem_nomatch_list);
124 udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->sysname_match_list);
125 udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->properties_match_list);
126 udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->tags_match_list);
127 udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->devices_list);
128 for (i = 0; i < udev_enumerate->devices_cur; i++)
129 free(udev_enumerate->devices[i].syspath);
130 free(udev_enumerate->devices);
131 free(udev_enumerate);
135 * udev_enumerate_get_udev:
136 * @udev_enumerate: context
138 * Returns: the udev library context.
140 struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate)
142 if (udev_enumerate == NULL)
144 return udev_enumerate->udev;
147 static int syspath_add(struct udev_enumerate *udev_enumerate, const char *syspath)
150 struct syspath *entry;
152 /* double array size if needed */
153 if (udev_enumerate->devices_cur >= udev_enumerate->devices_max) {
157 add = udev_enumerate->devices_max;
160 buf = realloc(udev_enumerate->devices, (udev_enumerate->devices_max + add) * sizeof(struct syspath));
163 udev_enumerate->devices = buf;
164 udev_enumerate->devices_max += add;
167 path = strdup(syspath);
170 entry = &udev_enumerate->devices[udev_enumerate->devices_cur];
171 entry->syspath = path;
172 entry->len = strlen(path);
173 udev_enumerate->devices_cur++;
174 udev_enumerate->devices_uptodate = false;
178 static int syspath_cmp(const void *p1, const void *p2)
180 const struct syspath *path1 = p1;
181 const struct syspath *path2 = p2;
185 len = MIN(path1->len, path2->len);
186 ret = memcmp(path1->syspath, path2->syspath, len);
188 if (path1->len < path2->len)
190 else if (path1->len > path2->len)
196 /* For devices that should be moved to the absolute end of the list */
197 static bool devices_delay_end(struct udev *udev, const char *syspath)
199 static const char *delay_device_list[] = {
207 len = strlen(udev_get_sys_path(udev));
208 for (i = 0; delay_device_list[i] != NULL; i++) {
209 if (strstr(&syspath[len], delay_device_list[i]) != NULL) {
210 dbg(udev, "delaying: %s\n", syspath);
217 /* For devices that should just be moved a little bit later, just
218 * before the point where some common path prefix changes. Returns the
219 * number of characters that make up that common prefix */
220 static size_t devices_delay_later(struct udev *udev, const char *syspath)
224 /* For sound cards the control device must be enumerated last
225 * to make sure it's the final device node that gets ACLs
226 * applied. Applications rely on this fact and use ACL changes
227 * on the control node as an indicator that the ACL change of
228 * the entire sound card completed. The kernel makes this
229 * guarantee when creating those devices, and hence we should
230 * too when enumerating them. */
232 if ((c = strstr(syspath, "/sound/card"))) {
234 c += strcspn(c, "/");
236 if (strncmp(c, "/controlC", 9) == 0)
237 return c - syspath + 1;
244 * udev_enumerate_get_list_entry:
245 * @udev_enumerate: context
247 * Returns: the first entry of the sorted list of device paths.
249 struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate)
251 if (udev_enumerate == NULL)
253 if (!udev_enumerate->devices_uptodate) {
256 struct syspath *prev = NULL, *move_later = NULL;
257 size_t move_later_prefix = 0;
259 udev_list_cleanup_entries(udev_enumerate->udev, &udev_enumerate->devices_list);
260 qsort(udev_enumerate->devices, udev_enumerate->devices_cur, sizeof(struct syspath), syspath_cmp);
262 max = udev_enumerate->devices_cur;
263 for (i = 0; i < max; i++) {
264 struct syspath *entry = &udev_enumerate->devices[i];
266 /* skip duplicated entries */
268 entry->len == prev->len &&
269 memcmp(entry->syspath, prev->syspath, entry->len) == 0)
273 /* skip to be delayed devices, and add them to the end of the list */
274 if (devices_delay_end(udev_enumerate->udev, entry->syspath)) {
275 syspath_add(udev_enumerate, entry->syspath);
279 /* skip to be delayed devices, and move the to
280 * the point where the prefix changes. We can
281 * only move one item at a time. */
283 move_later_prefix = devices_delay_later(udev_enumerate->udev, entry->syspath);
285 if (move_later_prefix > 0) {
292 strncmp(entry->syspath, move_later->syspath, move_later_prefix) != 0) {
294 udev_list_entry_add(udev_enumerate->udev, &udev_enumerate->devices_list,
295 move_later->syspath, NULL, 0, 0);
299 udev_list_entry_add(udev_enumerate->udev, &udev_enumerate->devices_list,
300 entry->syspath, NULL, 0, 0);
304 udev_list_entry_add(udev_enumerate->udev, &udev_enumerate->devices_list,
305 move_later->syspath, NULL, 0, 0);
307 /* add and cleanup delayed devices from end of list */
308 for (i = max; i < udev_enumerate->devices_cur; i++) {
309 struct syspath *entry = &udev_enumerate->devices[i];
311 udev_list_entry_add(udev_enumerate->udev, &udev_enumerate->devices_list,
312 entry->syspath, NULL, 0, 0);
313 free(entry->syspath);
315 udev_enumerate->devices_cur = max;
317 udev_enumerate->devices_uptodate = true;
319 return udev_list_get_entry(&udev_enumerate->devices_list);
323 * udev_enumerate_add_match_subsystem:
324 * @udev_enumerate: context
325 * @subsystem: filter for a subsystem of the device to include in the list
327 * Returns: 0 on success, otherwise a negative error value.
329 int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem)
331 if (udev_enumerate == NULL)
333 if (subsystem == NULL)
335 if (udev_list_entry_add(udev_enumerate_get_udev(udev_enumerate),
336 &udev_enumerate->subsystem_match_list, subsystem, NULL, 1, 0) == NULL)
342 * udev_enumerate_add_nomatch_subsystem:
343 * @udev_enumerate: context
344 * @subsystem: filter for a subsystem of the device to exclude from the list
346 * Returns: 0 on success, otherwise a negative error value.
348 int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem)
350 if (udev_enumerate == NULL)
352 if (subsystem == NULL)
354 if (udev_list_entry_add(udev_enumerate_get_udev(udev_enumerate),
355 &udev_enumerate->subsystem_nomatch_list, subsystem, NULL, 1, 0) == NULL)
361 * udev_enumerate_add_match_sysattr:
362 * @udev_enumerate: context
363 * @sysattr: filter for a sys attribute at the device to include in the list
364 * @value: optional value of the sys attribute
366 * Returns: 0 on success, otherwise a negative error value.
368 int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value)
370 if (udev_enumerate == NULL)
374 if (udev_list_entry_add(udev_enumerate_get_udev(udev_enumerate),
375 &udev_enumerate->sysattr_match_list, sysattr, value, 0, 0) == NULL)
381 * udev_enumerate_add_nomatch_sysattr:
382 * @udev_enumerate: context
383 * @sysattr: filter for a sys attribute at the device to exclude from the list
384 * @value: optional value of the sys attribute
386 * Returns: 0 on success, otherwise a negative error value.
388 int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value)
390 if (udev_enumerate == NULL)
394 if (udev_list_entry_add(udev_enumerate_get_udev(udev_enumerate),
395 &udev_enumerate->sysattr_nomatch_list, sysattr, value, 0, 0) == NULL)
400 static int match_sysattr_value(struct udev_device *dev, const char *sysattr, const char *match_val)
402 const char *val = NULL;
405 val = udev_device_get_sysattr_value(dev, sysattr);
408 if (match_val == NULL) {
412 if (fnmatch(match_val, val, 0) == 0) {
421 * udev_enumerate_add_match_property:
422 * @udev_enumerate: context
423 * @property: filter for a property of the device to include in the list
424 * @value: value of the property
426 * Returns: 0 on success, otherwise a negative error value.
428 int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value)
430 if (udev_enumerate == NULL)
432 if (property == NULL)
434 if (udev_list_entry_add(udev_enumerate_get_udev(udev_enumerate),
435 &udev_enumerate->properties_match_list, property, value, 0, 0) == NULL)
441 * udev_enumerate_add_match_tag:
442 * @udev_enumerate: context
443 * @tag: filter for a tag of the device to include in the list
445 * Returns: 0 on success, otherwise a negative error value.
447 int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag)
449 if (udev_enumerate == NULL)
453 if (udev_list_entry_add(udev_enumerate_get_udev(udev_enumerate),
454 &udev_enumerate->tags_match_list, tag, NULL, 1, 0) == NULL)
460 * udev_enumerate_add_match_sysname:
461 * @udev_enumerate: context
462 * @sysname: filter for the name of the device to include in the list
464 * Returns: 0 on success, otherwise a negative error value.
466 int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname)
468 if (udev_enumerate == NULL)
472 if (udev_list_entry_add(udev_enumerate_get_udev(udev_enumerate),
473 &udev_enumerate->sysname_match_list, sysname, NULL, 1, 0) == NULL)
478 static bool match_sysattr(struct udev_enumerate *udev_enumerate, struct udev_device *dev)
480 struct udev_list_entry *list_entry;
483 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysattr_nomatch_list)) {
484 if (match_sysattr_value(dev, udev_list_entry_get_name(list_entry),
485 udev_list_entry_get_value(list_entry)))
489 if (udev_list_get_entry(&udev_enumerate->sysattr_match_list) != NULL) {
490 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysattr_match_list)) {
491 /* anything that does not match, will make it FALSE */
492 if (!match_sysattr_value(dev, udev_list_entry_get_name(list_entry),
493 udev_list_entry_get_value(list_entry)))
501 static bool match_property(struct udev_enumerate *udev_enumerate, struct udev_device *dev)
503 struct udev_list_entry *list_entry;
506 /* no match always matches */
507 if (udev_list_get_entry(&udev_enumerate->properties_match_list) == NULL)
510 /* loop over matches */
511 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->properties_match_list)) {
512 const char *match_key = udev_list_entry_get_name(list_entry);
513 const char *match_value = udev_list_entry_get_value(list_entry);
514 struct udev_list_entry *property_entry;
516 /* loop over device properties */
517 udev_list_entry_foreach(property_entry, udev_device_get_properties_list_entry(dev)) {
518 const char *dev_key = udev_list_entry_get_name(property_entry);
519 const char *dev_value = udev_list_entry_get_value(property_entry);
521 if (fnmatch(match_key, dev_key, 0) != 0)
523 if (match_value == NULL && dev_value == NULL) {
527 if (match_value == NULL || dev_value == NULL)
529 if (fnmatch(match_value, dev_value, 0) == 0) {
539 static bool match_tag(struct udev_enumerate *udev_enumerate, struct udev_device *dev)
541 struct udev_list_entry *list_entry;
543 /* no match always matches */
544 if (udev_list_get_entry(&udev_enumerate->tags_match_list) == NULL)
547 /* loop over matches */
548 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->tags_match_list))
549 if (!udev_device_has_tag(dev, udev_list_entry_get_name(list_entry)))
555 static bool match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname)
557 struct udev_list_entry *list_entry;
559 if (udev_list_get_entry(&udev_enumerate->sysname_match_list) == NULL)
562 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->sysname_match_list)) {
563 if (fnmatch(udev_list_entry_get_name(list_entry), sysname, 0) != 0)
570 static int scan_dir_and_add_devices(struct udev_enumerate *udev_enumerate,
571 const char *basedir, const char *subdir1, const char *subdir2)
573 struct udev *udev = udev_enumerate_get_udev(udev_enumerate);
574 char path[UTIL_PATH_SIZE];
581 l = util_strpcpyl(&s, sizeof(path), udev_get_sys_path(udev), "/", basedir, NULL);
583 l = util_strpcpyl(&s, l, "/", subdir1, NULL);
585 util_strpcpyl(&s, l, "/", subdir2, NULL);
589 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
590 char syspath[UTIL_PATH_SIZE];
591 struct udev_device *dev;
593 if (dent->d_name[0] == '.')
596 if (!match_sysname(udev_enumerate, dent->d_name))
599 util_strscpyl(syspath, sizeof(syspath), path, "/", dent->d_name, NULL);
600 dev = udev_device_new_from_syspath(udev_enumerate->udev, syspath);
604 if (!match_tag(udev_enumerate, dev))
606 if (!match_property(udev_enumerate, dev))
608 if (!match_sysattr(udev_enumerate, dev))
611 syspath_add(udev_enumerate, udev_device_get_syspath(dev));
613 udev_device_unref(dev);
619 static bool match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem)
621 struct udev_list_entry *list_entry;
623 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->subsystem_nomatch_list)) {
624 if (fnmatch(udev_list_entry_get_name(list_entry), subsystem, 0) == 0)
627 if (udev_list_get_entry(&udev_enumerate->subsystem_match_list) != NULL) {
628 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->subsystem_match_list)) {
629 if (fnmatch(udev_list_entry_get_name(list_entry), subsystem, 0) == 0)
637 static int scan_dir(struct udev_enumerate *udev_enumerate, const char *basedir, const char *subdir, const char *subsystem)
639 struct udev *udev = udev_enumerate_get_udev(udev_enumerate);
641 char path[UTIL_PATH_SIZE];
645 util_strscpyl(path, sizeof(path), udev_get_sys_path(udev), "/", basedir, NULL);
649 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
650 if (dent->d_name[0] == '.')
652 if (!match_subsystem(udev_enumerate, subsystem != NULL ? subsystem : dent->d_name))
654 scan_dir_and_add_devices(udev_enumerate, basedir, dent->d_name, subdir);
661 * udev_enumerate_add_syspath:
662 * @udev_enumerate: context
663 * @syspath: path of a device
665 * Add a device to the list of devices, to retrieve it back sorted in dependency order.
667 * Returns: 0 on success, otherwise a negative error value.
669 int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath)
671 struct udev_device *udev_device;
673 if (udev_enumerate == NULL)
677 /* resolve to real syspath */
678 udev_device = udev_device_new_from_syspath(udev_enumerate->udev, syspath);
679 if (udev_device == NULL)
681 syspath_add(udev_enumerate, udev_device_get_syspath(udev_device));
682 udev_device_unref(udev_device);
687 * udev_enumerate_scan_devices:
688 * @udev_enumerate: udev enumeration context
690 * Returns: 0 on success, otherwise a negative error value.
692 int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate)
694 struct udev *udev = udev_enumerate_get_udev(udev_enumerate);
695 char base[UTIL_PATH_SIZE];
698 if (udev_enumerate == NULL)
701 if (udev_list_get_entry(&udev_enumerate->tags_match_list) != NULL) {
702 struct udev_list_entry *list_entry;
704 /* scan only tagged devices, use tags reverse-index, instead of searching all devices in /sys */
705 udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_enumerate->tags_match_list)) {
708 char path[UTIL_PATH_SIZE];
710 util_strscpyl(path, sizeof(path), udev_get_dev_path(udev), "/.udev/tags/",
711 udev_list_entry_get_name(list_entry), NULL);
715 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
716 struct udev_device *dev;
717 char syspath[UTIL_PATH_SIZE];
722 if (dent->d_name[0] == '.')
726 l = util_strpcpyl(&s, sizeof(syspath), udev_get_sys_path(udev), NULL);
727 len = readlinkat(dirfd(dir), dent->d_name, s, l);
728 if (len <= 0 || (size_t)len == l)
732 dev = udev_device_new_from_syspath(udev_enumerate->udev, syspath);
735 syspath_add(udev_enumerate, udev_device_get_syspath(dev));
736 udev_device_unref(dev);
741 util_strscpyl(base, sizeof(base), udev_get_sys_path(udev), "/subsystem", NULL);
742 if (stat(base, &statbuf) == 0) {
743 /* we have /subsystem/, forget all the old stuff */
744 dbg(udev, "searching '/subsystem/*/devices/*' dir\n");
745 scan_dir(udev_enumerate, "subsystem", "devices", NULL);
747 dbg(udev, "searching '/bus/*/devices/*' dir\n");
748 scan_dir(udev_enumerate, "bus", "devices", NULL);
749 dbg(udev, "searching '/class/*' dir\n");
750 scan_dir(udev_enumerate, "class", NULL, NULL);
758 * udev_enumerate_scan_subsystems:
759 * @udev_enumerate: udev enumeration context
761 * Returns: 0 on success, otherwise a negative error value.
763 int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate)
765 struct udev *udev = udev_enumerate_get_udev(udev_enumerate);
766 char base[UTIL_PATH_SIZE];
768 const char *subsysdir;
770 if (udev_enumerate == NULL)
773 util_strscpyl(base, sizeof(base), udev_get_sys_path(udev), "/subsystem", NULL);
774 if (stat(base, &statbuf) == 0)
775 subsysdir = "subsystem";
778 if (match_subsystem(udev_enumerate, "subsystem")) {
779 dbg(udev, "searching '%s/*' dir\n", subsysdir);
780 scan_dir_and_add_devices(udev_enumerate, subsysdir, NULL, NULL);
782 if (match_subsystem(udev_enumerate, "drivers")) {
783 dbg(udev, "searching '%s/*/drivers/*' dir\n", subsysdir);
784 scan_dir(udev_enumerate, subsysdir, "drivers", "drivers");