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