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=ca5e30e4a13a5c4521c08d17bc70859eada87752;hb=e345e2670a8c17f5e1145cc554b7a7646e271032;hpb=38f27948cdafd8a4b90a6b4f1f54b89891983506 diff --git a/udev/lib/libudev-enumerate.c b/udev/lib/libudev-enumerate.c index ca5e30e4a..fc853b8d6 100644 --- a/udev/lib/libudev-enumerate.c +++ b/udev/lib/libudev-enumerate.c @@ -29,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; @@ -55,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; @@ -63,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; @@ -108,72 +140,46 @@ static int devices_delay(struct udev *udev, const char *syspath) } /** - * udev_enumerate_devices: + * udev_enumerate_new_from_subsystems: * @udev: udev library context * @subsystem: the subsystem to enumerate - * @cb: function to be called for every device found - * @data: data to be passed to the function * - * Returns: the number of devices 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_device *udev_device, 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) { - struct udev_device *device; - - device = udev_device_new_from_syspath(udev, loop_device->name); - if (device != NULL) { - cb_rc = cb(device, data); - count++; - udev_device_unref(device); - } - } - 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) { - struct udev_device *device; - - device = udev_device_new_from_syspath(udev, loop_device->name); - if (device != NULL) { - cb_rc = cb(device, data); - count++; - udev_device_unref(device); - } - } - 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; }