X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev%2Flib%2Flibudev-enumerate.c;h=fc853b8d631098adb79091e5bb30e8fa03760d32;hp=458be5861a527569d12a697e042ce3baa0e7c62b;hb=e345e2670a8c17f5e1145cc554b7a7646e271032;hpb=8753fadf2a6ecead372e71b8bf9336cf29f9c958 diff --git a/udev/lib/libudev-enumerate.c b/udev/lib/libudev-enumerate.c index 458be5861..fc853b8d6 100644 --- a/udev/lib/libudev-enumerate.c +++ b/udev/lib/libudev-enumerate.c @@ -17,8 +17,6 @@ * along with this program. If not, see . */ -#include "config.h" - #include #include #include @@ -31,9 +29,41 @@ #include "libudev.h" #include "libudev-private.h" +struct udev_enumerate { + struct udev *udev; + int refcount; + struct list_node devices_list; +}; + +struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) +{ + if (udev_enumerate == NULL) + return NULL; + udev_enumerate->refcount++; + return udev_enumerate; +} + +void udev_enumerate_unref(struct udev_enumerate *udev_enumerate) +{ + if (udev_enumerate == NULL) + return; + udev_enumerate->refcount--; + if (udev_enumerate->refcount > 0) + return; + list_cleanup(udev_enumerate->udev, &udev_enumerate->devices_list); + free(udev_enumerate); +} + +struct udev_list *udev_enumerate_get_list(struct udev_enumerate *udev_enumerate) +{ + if (udev_enumerate == NULL) + return NULL; + return list_get_entry(&udev_enumerate->devices_list); +} + static int devices_scan_subsystem(struct udev *udev, const char *basedir, const char *subsystem, const char *subdir, - struct list_head *device_list) + struct list_node *device_list) { char path[UTIL_PATH_SIZE]; DIR *dir; @@ -57,7 +87,7 @@ static int devices_scan_subsystem(struct udev *udev, util_strlcat(syspath, "/", sizeof(syspath)); util_strlcat(syspath, dent->d_name, sizeof(syspath)); util_resolve_sys_link(udev, syspath, sizeof(syspath)); - util_name_list_add(udev, device_list, syspath, NULL, 1); + list_insert_entry(udev, device_list, syspath, NULL, 1); } closedir(dir); return 0; @@ -65,7 +95,7 @@ static int devices_scan_subsystem(struct udev *udev, static int devices_scan_subsystems(struct udev *udev, const char *basedir, const char *subsystem, const char *subdir, - struct list_head *device_list) + struct list_node *device_list) { char path[UTIL_PATH_SIZE]; DIR *dir; @@ -109,85 +139,47 @@ static int devices_delay(struct udev *udev, const char *syspath) return 0; } -static int devices_call(struct udev *udev, const char *syspath, - int (*cb)(struct udev *udev, - const char *syspath, const char *subsystem, const char *name, - void *data), - void *data, - int *cb_rc) -{ - char subsystem[UTIL_PATH_SIZE]; - const char *name; - - name = strrchr(syspath, '/'); - if (name == NULL) - return -1; - name++; - - if (util_get_sys_subsystem(udev, syspath, subsystem, sizeof(subsystem)) < 2) - return -1; - *cb_rc = cb(udev, syspath, subsystem, name, data); - return 0; -} - /** - * udev_enumerate_devices: - * @udev_device: udev device - * @cb: function to be called for every property found - * @data: data to be passed to the function + * udev_enumerate_new_from_subsystems: + * @udev: udev library context + * @subsystem: the subsystem to enumerate * - * Retrieve the property key/value pairs belonging to the - * udev device. For every key/value pair, the passed function will be - * called. If the function returns 1, remaning properties will be - * ignored. - * - * Returns: the number of properties passed to the caller, or a negative value on error + * Returns: an enumeration context **/ -int udev_enumerate_devices(struct udev *udev, const char *subsystem, - int (*cb)(struct udev *udev, - const char *syspath, const char *subsystem, const char *name, void *data), - void *data) +struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev, const char *subsystem) { + struct udev_enumerate *udev_enumerate; char base[UTIL_PATH_SIZE]; struct stat statbuf; - struct list_head device_list; - struct util_name_entry *loop_device; - struct util_name_entry *tmp_device; - int cb_rc = 0; - int count = 0; + struct udev_list *list; + + if (udev == NULL) + return NULL; - INIT_LIST_HEAD(&device_list); + udev_enumerate = malloc(sizeof(struct udev_enumerate)); + if (udev_enumerate == NULL) + return NULL; + memset(udev_enumerate, 0x00, (sizeof(struct udev_enumerate))); + udev_enumerate->refcount = 1; + udev_enumerate->udev = udev; + list_init(&udev_enumerate->devices_list); /* if we have /sys/subsystem/, forget all the old stuff */ util_strlcpy(base, udev_get_sys_path(udev), sizeof(base)); util_strlcat(base, "/subsystem", sizeof(base)); if (stat(base, &statbuf) == 0) { - devices_scan_subsystems(udev, "/subsystem", subsystem, "/devices", &device_list); + devices_scan_subsystems(udev, "/subsystem", subsystem, "/devices", &udev_enumerate->devices_list); } else { - devices_scan_subsystems(udev, "/bus", subsystem, "/devices", &device_list); - devices_scan_subsystems(udev, "/class", subsystem, NULL, &device_list); - } - - list_for_each_entry_safe(loop_device, tmp_device, &device_list, node) { - if (devices_delay(udev, loop_device->name)) - continue; - if (cb_rc == 0) - if (devices_call(udev, loop_device->name, cb, data, &cb_rc) == 0) - count++; - list_del(&loop_device->node); - free(loop_device->name); - free(loop_device); + devices_scan_subsystems(udev, "/bus", subsystem, "/devices", &udev_enumerate->devices_list); + devices_scan_subsystems(udev, "/class", subsystem, NULL, &udev_enumerate->devices_list); } - /* handle remaining delayed devices */ - list_for_each_entry_safe(loop_device, tmp_device, &device_list, node) { - if (cb_rc == 0) - if (devices_call(udev, loop_device->name, cb, data, &cb_rc) == 0) - count++; - list_del(&loop_device->node); - free(loop_device->name); - free(loop_device); + /* sort delayed devices to the end of the list */ + list = list_get_entry(&udev_enumerate->devices_list); + while (list != NULL) { + if (devices_delay(udev, udev_list_entry_get_name(list))) + list_move_entry_to_end(list, &udev_enumerate->devices_list); + list = udev_list_entry_get_next(list); } - - return count; + return udev_enumerate; }