| |
| |
| #include <dirent.h> |
| #include <errno.h> |
| #include <fnmatch.h> |
| #include <stdbool.h> |
| #include <stddef.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/stat.h> |
| |
| #include "libudev.h" |
| #include "sd-device.h" |
| |
| #include "alloc-util.h" |
| #include "device-enumerator-private.h" |
| #include "device-util.h" |
| #include "libudev-device-internal.h" |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| struct udev_enumerate { |
| struct udev *udev; |
| int refcount; |
| struct udev_list devices_list; |
| bool devices_uptodate:1; |
| |
| sd_device_enumerator *enumerator; |
| }; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ struct udev_enumerate *udev_enumerate_new(struct udev *udev) { |
| _cleanup_free_ struct udev_enumerate *udev_enumerate = NULL; |
| int r; |
| |
| assert_return_errno(udev, NULL, EINVAL); |
| |
| udev_enumerate = new0(struct udev_enumerate, 1); |
| if (!udev_enumerate) { |
| errno = ENOMEM; |
| return NULL; |
| } |
| |
| r = sd_device_enumerator_new(&udev_enumerate->enumerator); |
| if (r < 0) { |
| errno = -r; |
| return NULL; |
| } |
| |
| r = sd_device_enumerator_allow_uninitialized(udev_enumerate->enumerator); |
| if (r < 0) { |
| errno = -r; |
| return NULL; |
| } |
| |
| udev_enumerate->refcount = 1; |
| udev_enumerate->udev = udev; |
| |
| udev_list_init(udev, &udev_enumerate->devices_list, false); |
| |
| return TAKE_PTR(udev_enumerate); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) { |
| if (udev_enumerate) |
| udev_enumerate->refcount++; |
| |
| return udev_enumerate; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate) { |
| if (udev_enumerate && (-- udev_enumerate->refcount) == 0) { |
| udev_list_cleanup(&udev_enumerate->devices_list); |
| sd_device_enumerator_unref(udev_enumerate->enumerator); |
| free(udev_enumerate); |
| } |
| |
| return NULL; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ struct udev *udev_enumerate_get_udev(struct udev_enumerate *udev_enumerate) { |
| assert_return_errno(udev_enumerate, NULL, EINVAL); |
| |
| return udev_enumerate->udev; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ struct udev_list_entry *udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) { |
| struct udev_list_entry *e; |
| |
| assert_return_errno(udev_enumerate, NULL, EINVAL); |
| |
| if (!udev_enumerate->devices_uptodate) { |
| sd_device *device; |
| |
| udev_list_cleanup(&udev_enumerate->devices_list); |
| |
| FOREACH_DEVICE_AND_SUBSYSTEM(udev_enumerate->enumerator, device) { |
| const char *syspath; |
| int r; |
| |
| r = sd_device_get_syspath(device, &syspath); |
| if (r < 0) { |
| errno = -r; |
| return NULL; |
| } |
| |
| udev_list_entry_add(&udev_enumerate->devices_list, syspath, NULL); |
| } |
| |
| udev_enumerate->devices_uptodate = true; |
| } |
| |
| e = udev_list_get_entry(&udev_enumerate->devices_list); |
| if (!e) |
| errno = ENODATA; |
| |
| return e; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { |
| assert_return(udev_enumerate, -EINVAL); |
| |
| if (!subsystem) |
| return 0; |
| |
| return sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, true); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ int udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerate, const char *subsystem) { |
| assert_return(udev_enumerate, -EINVAL); |
| |
| if (!subsystem) |
| return 0; |
| |
| return sd_device_enumerator_add_match_subsystem(udev_enumerate->enumerator, subsystem, false); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ int udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) { |
| assert_return(udev_enumerate, -EINVAL); |
| |
| if (!sysattr) |
| return 0; |
| |
| return sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, true); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ int udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, const char *sysattr, const char *value) { |
| assert_return(udev_enumerate, -EINVAL); |
| |
| if (!sysattr) |
| return 0; |
| |
| return sd_device_enumerator_add_match_sysattr(udev_enumerate->enumerator, sysattr, value, false); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, const char *property, const char *value) { |
| assert_return(udev_enumerate, -EINVAL); |
| |
| if (!property) |
| return 0; |
| |
| return sd_device_enumerator_add_match_property(udev_enumerate->enumerator, property, value); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ int udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, const char *tag) { |
| assert_return(udev_enumerate, -EINVAL); |
| |
| if (!tag) |
| return 0; |
| |
| return sd_device_enumerator_add_match_tag(udev_enumerate->enumerator, tag); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ int udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, struct udev_device *parent) { |
| assert_return(udev_enumerate, -EINVAL); |
| |
| if (!parent) |
| return 0; |
| |
| return sd_device_enumerator_add_match_parent(udev_enumerate->enumerator, parent->device); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ int udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enumerate) { |
| assert_return(udev_enumerate, -EINVAL); |
| |
| return device_enumerator_add_match_is_initialized(udev_enumerate->enumerator); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ int udev_enumerate_add_match_sysname(struct udev_enumerate *udev_enumerate, const char *sysname) { |
| assert_return(udev_enumerate, -EINVAL); |
| |
| if (!sysname) |
| return 0; |
| |
| return sd_device_enumerator_add_match_sysname(udev_enumerate->enumerator, sysname); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ int udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, const char *syspath) { |
| _cleanup_(sd_device_unrefp) sd_device *device = NULL; |
| int r; |
| |
| assert_return(udev_enumerate, -EINVAL); |
| |
| if (!syspath) |
| return 0; |
| |
| r = sd_device_new_from_syspath(&device, syspath); |
| if (r < 0) |
| return r; |
| |
| r = device_enumerator_add_device(udev_enumerate->enumerator, device); |
| if (r < 0) |
| return r; |
| |
| return 0; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) { |
| assert_return(udev_enumerate, -EINVAL); |
| |
| return device_enumerator_scan_devices(udev_enumerate->enumerator); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| _public_ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) { |
| assert_return(udev_enumerate, -EINVAL); |
| |
| return device_enumerator_scan_subsystems(udev_enumerate->enumerator); |
| } |