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=f36eafaff6a01055461435a3d256e9ff03047308;hb=e345e2670a8c17f5e1145cc554b7a7646e271032;hpb=b21b95d7222f32940c8e9462c361e45041c9f7d6 diff --git a/udev/lib/libudev-enumerate.c b/udev/lib/libudev-enumerate.c index f36eafaff..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 @@ -30,36 +28,66 @@ #include "libudev.h" #include "libudev-private.h" -#include "../udev.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[PATH_SIZE]; + char path[UTIL_PATH_SIZE]; DIR *dir; struct dirent *dent; - size_t len; - len = strlcpy(path, udev_get_sys_path(udev), sizeof(path)); - strlcat(path, basedir, sizeof(path)); - strlcat(path, "/", sizeof(path)); - strlcat(path, subsystem, sizeof(path)); + util_strlcpy(path, udev_get_sys_path(udev), sizeof(path)); + util_strlcat(path, basedir, sizeof(path)); + util_strlcat(path, "/", sizeof(path)); + util_strlcat(path, subsystem, sizeof(path)); if (subdir != NULL) - strlcat(path, subdir, sizeof(path)); + util_strlcat(path, subdir, sizeof(path)); dir = opendir(path); if (dir == NULL) return -1; for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - char devpath[PATH_SIZE]; + char syspath[UTIL_PATH_SIZE]; if (dent->d_name[0] == '.') continue; - strlcpy(devpath, &path[len], sizeof(devpath)); - strlcat(devpath, "/", sizeof(devpath)); - strlcat(devpath, dent->d_name, sizeof(devpath)); - util_resolve_sys_link(udev, devpath, sizeof(devpath)); - name_list_add(udev, device_list, devpath, 1); + util_strlcpy(syspath, path, sizeof(syspath)); + util_strlcat(syspath, "/", sizeof(syspath)); + util_strlcat(syspath, dent->d_name, sizeof(syspath)); + util_resolve_sys_link(udev, syspath, sizeof(syspath)); + list_insert_entry(udev, device_list, syspath, NULL, 1); } closedir(dir); return 0; @@ -67,17 +95,17 @@ 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[PATH_SIZE]; + char path[UTIL_PATH_SIZE]; DIR *dir; struct dirent *dent; if (subsystem != NULL) return devices_scan_subsystem(udev, basedir, subsystem, subdir, device_list); - strlcpy(path, udev_get_sys_path(udev), sizeof(path)); - strlcat(path, basedir, sizeof(path)); + util_strlcpy(path, udev_get_sys_path(udev), sizeof(path)); + util_strlcat(path, basedir, sizeof(path)); dir = opendir(path); if (dir == NULL) return -1; @@ -90,101 +118,68 @@ static int devices_scan_subsystems(struct udev *udev, return 0; } -static int devices_delay(struct udev *udev, const char *devpath) +static int devices_delay(struct udev *udev, const char *syspath) { static const char *delay_device_list[] = { "/block/md", "/block/dm-", NULL }; + size_t len; int i; + len = strlen(udev_get_sys_path(udev)); + for (i = 0; delay_device_list[i] != NULL; i++) { - if (strstr(devpath, delay_device_list[i]) != NULL) { - info(udev, "delaying: %s\n", devpath); + if (strstr(&syspath[len], delay_device_list[i]) != NULL) { + info(udev, "delaying: %s\n", syspath); return 1; } } return 0; } -static int devices_call(struct udev *udev, const char *devpath, - int (*cb)(struct udev *udev, - const char *devpath, const char *subsystem, const char *name, - void *data), - void *data, - int *cb_rc) -{ - char subsystem[NAME_SIZE]; - const char *name; - - name = strrchr(devpath, '/'); - if (name == NULL) - return -1; - name++; - - if (util_get_sys_subsystem(udev, devpath, subsystem, sizeof(subsystem)) < 2) - return -1; - *cb_rc = cb(udev, devpath, 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 - * - * 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. + * udev_enumerate_new_from_subsystems: + * @udev: udev library context + * @subsystem: the subsystem to enumerate * - * 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 *devpath, const char *subsystem, const char *name, void *data), - void *data) +struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev, const char *subsystem) { - char base[PATH_SIZE]; + struct udev_enumerate *udev_enumerate; + char base[UTIL_PATH_SIZE]; struct stat statbuf; - struct list_head device_list; - struct name_entry *loop_device; - struct name_entry *tmp_device; - int cb_rc = 0; - int count = 0; + struct udev_list *list; - INIT_LIST_HEAD(&device_list); + if (udev == NULL) + return NULL; + + 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 */ - strlcpy(base, udev_get_sys_path(udev), sizeof(base)); - strlcat(base, "/subsystem", sizeof(base)); + 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); + devices_scan_subsystems(udev, "/bus", subsystem, "/devices", &udev_enumerate->devices_list); + devices_scan_subsystems(udev, "/class", subsystem, NULL, &udev_enumerate->devices_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); + /* 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); } - - /* 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); - } - - return count; + return udev_enumerate; }