From bf7ad0ea662e747701cc66cdd1b33d22b6836cdf Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 25 Sep 2008 04:20:27 -0700 Subject: [PATCH] libudev: replace awkward callback list interfaces with list iterators --- TODO | 2 +- udev/Makefile.am | 3 +- udev/lib/Makefile.am | 1 + udev/lib/exported_symbols | 12 +- udev/lib/libudev-device.c | 125 ++++++++++----------- udev/lib/libudev-enumerate.c | 110 +++++++++--------- udev/lib/libudev-private.h | 12 +- udev/lib/libudev-util.c | 55 --------- udev/lib/libudev.h | 24 ++-- udev/lib/test-libudev.c | 70 +++++++----- udev/udevadm-info.c | 209 ++++++++++++++++------------------- udev/udevadm-monitor.c | 36 +++--- 12 files changed, 316 insertions(+), 343 deletions(-) diff --git a/TODO b/TODO index ef73fbd21..d35da5491 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,6 @@ - o make udev_device_new_from_devnum() work with kernels without /sys/dev/ o enumerate() - add buses and drivers o increase ressize buffer + o set dev_t from "uevent" MAJOR/MINOR o add DVB variables to kernel, and drop shell script rule o add watershed extra diff --git a/udev/Makefile.am b/udev/Makefile.am index 323f508b2..f15330b4f 100644 --- a/udev/Makefile.am +++ b/udev/Makefile.am @@ -29,10 +29,11 @@ common_files = \ lib/libudev.h \ lib/libudev-private.h \ lib/libudev.c \ + lib/libudev-list.c \ + lib/libudev-util.c \ lib/libudev-device.c \ lib/libudev-monitor.c \ lib/libudev-enumerate.c \ - lib/libudev-util.c \ lib/libudev-ctrl.c if USE_SELINUX diff --git a/udev/lib/Makefile.am b/udev/lib/Makefile.am index 7329ab6c6..0386465e8 100644 --- a/udev/lib/Makefile.am +++ b/udev/lib/Makefile.am @@ -19,6 +19,7 @@ include_HEADERS =\ libudev_la_SOURCES =\ libudev-private.h \ libudev.c \ + libudev-list.c \ libudev-util.c \ libudev-device.c \ libudev-enumerate.c \ diff --git a/udev/lib/exported_symbols b/udev/lib/exported_symbols index 6b034d459..e46aecbd3 100644 --- a/udev/lib/exported_symbols +++ b/udev/lib/exported_symbols @@ -9,6 +9,9 @@ udev_get_userdata udev_set_userdata udev_get_sys_path udev_get_dev_path +udev_list_get_next +udev_list_get_name +udev_list_get_value udev_device_new_from_syspath udev_device_new_from_devnum udev_device_get_parent @@ -20,14 +23,17 @@ udev_device_get_devpath udev_device_get_devnode udev_device_get_sysname udev_device_get_subsystem -udev_device_get_devlinks -udev_device_get_properties +udev_device_get_devlinks_list +udev_device_get_properties_list udev_device_get_action udev_device_get_driver udev_device_get_devnum udev_device_get_seqnum udev_device_get_attr_value -udev_enumerate_devices +udev_enumerate_new_from_subsystems +udev_enumerate_ref +udev_enumerate_unref +udev_enumerate_get_devices_list udev_monitor_new_from_socket udev_monitor_new_from_netlink udev_monitor_enable_receiving diff --git a/udev/lib/libudev-device.c b/udev/lib/libudev-device.c index 4a9c81506..a772dbbcf 100644 --- a/udev/lib/libudev-device.c +++ b/udev/lib/libudev-device.c @@ -40,7 +40,7 @@ struct udev_device { char *devname; char *subsystem; struct list_head link_list; - struct list_head env_list; + struct list_head properties_list; char *action; char *driver; char *devpath_old; @@ -189,7 +189,7 @@ struct udev_device *device_init(struct udev *udev) udev_device->refcount = 1; udev_device->udev = udev; INIT_LIST_HEAD(&udev_device->link_list); - INIT_LIST_HEAD(&udev_device->env_list); + INIT_LIST_HEAD(&udev_device->properties_list); INIT_LIST_HEAD(&udev_device->attr_list); info(udev_device->udev, "udev_device: %p created\n", udev_device); return udev_device; @@ -247,6 +247,9 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de { char path[UTIL_PATH_SIZE]; const char *type_str; + struct udev_enumerate *enumerate; + struct udev_list *list; + struct udev_device *device = NULL; if (type == 'b') type_str = "block"; @@ -255,12 +258,32 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de else return NULL; + /* /sys/dev/{block,char}/: links */ snprintf(path, sizeof(path), "%s/dev/%s/%u:%u", udev_get_sys_path(udev), type_str, major(devnum), minor(devnum)); - if (util_resolve_sys_link(udev, path, sizeof(path)) < 0) - return NULL; + if (util_resolve_sys_link(udev, path, sizeof(path)) == 0) + return udev_device_new_from_syspath(udev, path); - return udev_device_new_from_syspath(udev, path); + /* search all sys devices for the major/minor */ + enumerate = udev_enumerate_new_from_subsystems(udev, NULL); + if (enumerate == NULL) + return NULL; + list = udev_enumerate_get_devices_list(enumerate); + while (list != NULL) { + struct udev_device *device_loop; + + device_loop = udev_device_new_from_syspath(udev, udev_list_get_name(list)); + if (device_loop != NULL) { + if (udev_device_get_devnum(device_loop) == devnum) { + device = device_loop; + break; + } + udev_device_unref(device_loop); + } + list = udev_list_get_next(list); + } + udev_enumerate_unref(enumerate); + return device; } static struct udev_device *device_new_from_parent(struct udev_device *udev_device) @@ -357,13 +380,13 @@ void udev_device_unref(struct udev_device *udev_device) free(udev_device->syspath); free(udev_device->devname); free(udev_device->subsystem); - util_name_list_cleanup(udev_device->udev, &udev_device->link_list); - util_name_list_cleanup(udev_device->udev, &udev_device->env_list); + list_cleanup(udev_device->udev, &udev_device->link_list); + list_cleanup(udev_device->udev, &udev_device->properties_list); free(udev_device->action); free(udev_device->driver); free(udev_device->devpath_old); free(udev_device->physdevpath); - util_name_list_cleanup(udev_device->udev, &udev_device->attr_list); + list_cleanup(udev_device->udev, &udev_device->attr_list); info(udev_device->udev, "udev_device: %p released\n", udev_device); free(udev_device); } @@ -466,64 +489,38 @@ const char *udev_device_get_subsystem(struct udev_device *udev_device) } /** - * udev_device_get_devlinks: + * udev_device_get_devlinks_list: * @udev_device: udev device - * @cb: function to be called for every device link found - * @data: data to be passed to the function * - * Retrieve the device links pointing to the device file of the - * udev device. For every device link, the passed function will be - * called with the device link string. - * The path is an absolute path, and starts with the device directory. - * If the function returns 1, remaning device links will be ignored. + * Retrieve the list of device links pointing to the device file of + * the udev device. The next list entry can be retrieved with + * udev_list_next(), which returns #NULL if no more entries exist. + * The devlink path can be retrieved from the list entry by + * udev_list_get_name(). The path is an absolute path, and starts with + * the device directory. * - * Returns: the number of device links passed to the caller, or a negative value on error + * Returns: the first entry of the device node link list **/ -int udev_device_get_devlinks(struct udev_device *udev_device, - int (*cb)(struct udev_device *udev_device, const char *value, void *data), - void *data) +struct udev_list *udev_device_get_devlinks_list(struct udev_device *udev_device) { - struct util_name_entry *name_loop; - int count = 0; - - if (udev_device == NULL) - return -1; - list_for_each_entry(name_loop, &udev_device->link_list, node) { - count++; - if (cb(udev_device, name_loop->name, data) != 0) - break; - } - return count; + return list_get_entry(&udev_device->link_list); } /** - * udev_device_get_properties: + * udev_device_get_properties_list: * @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. + * Retrieve the list of key/value device properties of the udev + * device. The next list entry can be retrieved with udev_list_next(), + * which returns #NULL if no more entries exist. The property name + * can be retrieved from the list entry by udev_list_get_name(), + * the property value by udev_list_get_value(). * - * Returns: the number of properties passed to the caller, or a negative value on error + * Returns: the first entry of the property list **/ -int udev_device_get_properties(struct udev_device *udev_device, - int (*cb)(struct udev_device *udev_device, const char *key, const char *value, void *data), - void *data) +struct udev_list *udev_device_get_properties_list(struct udev_device *udev_device) { - struct util_name_entry *name_loop; - int count = 0; - - if (udev_device == NULL) - return -1; - list_for_each_entry(name_loop, &udev_device->env_list, node) { - count++; - if (cb(udev_device, name_loop->name, name_loop->value, data) != 0) - break; - } - return count; + return list_get_entry(&udev_device->properties_list); } const char *udev_device_get_driver(struct udev_device *udev_device) @@ -563,7 +560,7 @@ unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device) const char *udev_device_get_attr_value(struct udev_device *udev_device, const char *attr) { - struct util_name_entry *name_loop; + struct udev_list *list; char path[UTIL_PATH_SIZE]; char value[UTIL_NAME_SIZE]; struct stat statbuf; @@ -572,11 +569,13 @@ const char *udev_device_get_attr_value(struct udev_device *udev_device, const ch const char *val = NULL; /* look for possibly already cached result */ - list_for_each_entry(name_loop, &udev_device->attr_list, node) { - if (strcmp(name_loop->name, attr) == 0) { - info(udev_device->udev, "'%s' in cache '%s'\n", attr, name_loop->value); - return name_loop->value; + list = list_get_entry(&udev_device->attr_list); + while (list != NULL) { + if (strcmp(udev_list_get_name(list), attr) == 0) { + info(udev_device->udev, "got '%s' (%s) from cache\n", attr, udev_list_get_value(list)); + return udev_list_get_name(list); } + list = udev_list_get_next(list); } util_strlcpy(path, udev_device_get_syspath(udev_device), sizeof(path)); @@ -601,7 +600,8 @@ const char *udev_device_get_attr_value(struct udev_device *udev_device, const ch if (pos != NULL) { pos = &pos[1]; info(udev_device->udev, "cache '%s' with link value '%s'\n", attr, pos); - val = util_name_list_add(udev_device->udev, &udev_device->attr_list, attr, pos, 0)->value; + list = list_insert(udev_device->udev, &udev_device->attr_list, attr, pos, 0); + val = udev_list_get_value(list); } } goto out; @@ -632,7 +632,8 @@ const char *udev_device_get_attr_value(struct udev_device *udev_device, const ch value[size] = '\0'; util_remove_trailing_chars(value, '\n'); info(udev_device->udev, "'%s' has attribute value '%s'\n", path, value); - val = util_name_list_add(udev_device->udev, &udev_device->attr_list, attr, value, 0)->value; + list = list_insert(udev_device->udev, &udev_device->attr_list, attr, value, 0); + val = udev_list_get_value(list); out: return val; } @@ -669,14 +670,14 @@ int device_set_devname(struct udev_device *udev_device, const char *devname) int device_add_devlink(struct udev_device *udev_device, const char *devlink) { - if (util_name_list_add(udev_device->udev, &udev_device->link_list, devlink, NULL, 0) == NULL) + if (list_insert(udev_device->udev, &udev_device->link_list, devlink, NULL, 0) == NULL) return -ENOMEM; return 0; } int device_add_property(struct udev_device *udev_device, const char *key, const char *value) { - if (util_name_list_add(udev_device->udev, &udev_device->env_list, key, value, 0) == NULL) + if (list_insert(udev_device->udev, &udev_device->properties_list, key, value, 0) == NULL) return -ENOMEM; return 0; } diff --git a/udev/lib/libudev-enumerate.c b/udev/lib/libudev-enumerate.c index ca5e30e4a..80df8bd72 100644 --- a/udev/lib/libudev-enumerate.c +++ b/udev/lib/libudev-enumerate.c @@ -29,6 +29,38 @@ #include "libudev.h" #include "libudev-private.h" +struct udev_enumerate { + struct udev *udev; + int refcount; + struct list_head 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_devices_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) @@ -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(udev, device_list, syspath, NULL, 1); } closedir(dir); return 0; @@ -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; + INIT_LIST_HEAD(&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_get_name(list))) + list_move_to_end(list, &udev_enumerate->devices_list); + list = udev_list_get_next(list); } - - return count; + return udev_enumerate; } diff --git a/udev/lib/libudev-private.h b/udev/lib/libudev-private.h index c8063d2d6..c80c940b1 100644 --- a/udev/lib/libudev-private.h +++ b/udev/lib/libudev-private.h @@ -76,7 +76,7 @@ extern int device_set_devlink_priority(struct udev_device *udev_device, int prio extern int device_get_ignore_remove(struct udev_device *udev_device); extern int device_set_ignore_remove(struct udev_device *udev_device, int ignore); -/* udev_ctrl - daemon runtime setup */ +/* libudev-ctrl - daemon runtime setup */ struct udev_ctrl; extern struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socket_path); extern int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl); @@ -102,6 +102,13 @@ extern int udev_ctrl_get_reload_rules(struct udev_ctrl_msg *ctrl_msg); extern const char *udev_ctrl_get_set_env(struct udev_ctrl_msg *ctrl_msg); extern int udev_ctrl_get_set_max_childs(struct udev_ctrl_msg *ctrl_msg); +/* libudev-list */ +extern struct udev_list *list_insert(struct udev *udev, struct list_head *name_list, + const char *name, const char *value, int sort); +extern struct udev_list *list_get_entry(struct list_head *list); +extern void list_move_to_end(struct udev_list *list_entry, struct list_head *list); +extern void list_cleanup(struct udev *udev, struct list_head *name_list); + /* libudev-utils */ #define UTIL_PATH_SIZE 1024 #define UTIL_LINE_SIZE 2048 @@ -115,9 +122,6 @@ struct util_name_entry { extern ssize_t util_get_sys_subsystem(struct udev *udev, const char *syspath, char *subsystem, size_t size); extern ssize_t util_get_sys_driver(struct udev *udev, const char *syspath, char *driver, size_t size); extern int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size); -extern struct util_name_entry *util_name_list_add(struct udev *udev, struct list_head *name_list, - const char *name, const char *value, int sort); -extern void util_name_list_cleanup(struct udev *udev, struct list_head *name_list); extern int util_log_priority(const char *priority); extern size_t util_path_encode(char *s, size_t len); extern size_t util_path_decode(char *s); diff --git a/udev/lib/libudev-util.c b/udev/lib/libudev-util.c index aa544fea2..0e5bc37d4 100644 --- a/udev/lib/libudev-util.c +++ b/udev/lib/libudev-util.c @@ -97,61 +97,6 @@ int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size) return 0; } -struct util_name_entry *util_name_list_add(struct udev *udev, struct list_head *name_list, - const char *name, const char *value, int sort) -{ - struct util_name_entry *name_loop; - struct util_name_entry *name_new; - - /* avoid duplicate entries */ - list_for_each_entry(name_loop, name_list, node) { - if (strcmp(name_loop->name, name) == 0) { - dbg(udev, "'%s' is already in the list\n", name); - return name_loop; - } - } - - if (sort) { - list_for_each_entry(name_loop, name_list, node) { - if (strcmp(name_loop->name, name) > 0) - break; - } - } - - name_new = malloc(sizeof(struct util_name_entry)); - if (name_new == NULL) - return NULL; - memset(name_new, 0x00, sizeof(struct util_name_entry)); - name_new->name = strdup(name); - if (name_new->name == NULL) { - free(name_new); - return NULL; - } - if (value != NULL) { - name_new->value = strdup(value); - if (name_new->value == NULL) { - free(name_new); - return NULL; - } - } - dbg(udev, "adding '%s=%s'\n", name_new->name, name_new->value); - list_add_tail(&name_new->node, &name_loop->node); - return name_new; -} - -void util_name_list_cleanup(struct udev *udev, struct list_head *name_list) -{ - struct util_name_entry *name_loop; - struct util_name_entry *name_tmp; - - list_for_each_entry_safe(name_loop, name_tmp, name_list, node) { - list_del(&name_loop->node); - free(name_loop->name); - free(name_loop->value); - free(name_loop); - } -} - int util_log_priority(const char *priority) { char *endptr; diff --git a/udev/lib/libudev.h b/udev/lib/libudev.h index e71f6b217..014b53175 100644 --- a/udev/lib/libudev.h +++ b/udev/lib/libudev.h @@ -29,7 +29,9 @@ #endif struct udev; +struct udev_list; struct udev_device; +struct udev_enumerate; struct udev_monitor; /* library context */ @@ -52,6 +54,11 @@ extern void udev_selinux_resetfscreatecon(struct udev *udev); extern void udev_selinux_setfscreatecon(struct udev *udev, const char *file, unsigned int mode); extern void udev_selinux_lsetfilecon(struct udev *udev, const char *file, unsigned int mode); +/* list iteration */ +extern struct udev_list *udev_list_get_next(struct udev_list *list_entry); +extern const char *udev_list_get_name(struct udev_list *list_entry); +extern const char *udev_list_get_value(struct udev_list *list_entry); + /* sys devices */ extern struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath); extern struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum); @@ -64,14 +71,8 @@ extern const char *udev_device_get_subsystem(struct udev_device *udev_device); extern const char *udev_device_get_syspath(struct udev_device *udev_device); extern const char *udev_device_get_sysname(struct udev_device *udev_device); extern const char *udev_device_get_devnode(struct udev_device *udev_device); -extern int udev_device_get_devlinks(struct udev_device *udev_device, - int (*cb)(struct udev_device *udev_device, - const char *value, void *data), - void *data); -extern int udev_device_get_properties(struct udev_device *udev_device, - int (*cb)(struct udev_device *udev_device, - const char *key, const char *value, void *data), - void *data); +extern struct udev_list *udev_device_get_devlinks_list(struct udev_device *udev_device); +extern struct udev_list *udev_device_get_properties_list(struct udev_device *udev_device); extern const char *udev_device_get_driver(struct udev_device *udev_device); extern dev_t udev_device_get_devnum(struct udev_device *udev_device); extern const char *udev_device_get_action(struct udev_device *udev_device); @@ -79,9 +80,10 @@ extern unsigned long long int udev_device_get_seqnum(struct udev_device *udev_de extern const char *udev_device_get_attr_value(struct udev_device *udev_device, const char *attr); /* sys enumeration */ -extern int udev_enumerate_devices(struct udev *udev, const char *subsystem, - int (*cb)(struct udev_device *udev_device, void *data), - void *data); +extern struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev, const char *subsystem); +extern struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate); +extern void udev_enumerate_unref(struct udev_enumerate *udev_enumerate); +extern struct udev_list *udev_enumerate_get_devices_list(struct udev_enumerate *udev_enumerate); /* udev and kernel device events */ extern struct udev_monitor *udev_monitor_new_from_socket(struct udev *udev, const char *socket_path); diff --git a/udev/lib/test-libudev.c b/udev/lib/test-libudev.c index 8afd294a2..fed4350c0 100644 --- a/udev/lib/test-libudev.c +++ b/udev/lib/test-libudev.c @@ -37,22 +37,11 @@ static void log_fn(struct udev *udev, vprintf(format, args); } -static int print_devlinks_cb(struct udev_device *udev_device, const char *value, void *data) -{ - printf("link: '%s'\n", value); - return 0; -} - -static int print_properties_cb(struct udev_device *udev_device, const char *key, const char *value, void *data) -{ - printf("property: '%s=%s'\n", key, value); - return 0; -} - static void print_device(struct udev_device *device) { const char *str; int count; + struct udev_list *list; printf("*** device: %p ***\n", device); str = udev_device_get_action(device); @@ -67,10 +56,28 @@ static void print_device(struct udev_device *device) printf("driver: '%s'\n", str); str = udev_device_get_devnode(device); printf("devname: '%s'\n", str); - count = udev_device_get_devlinks(device, print_devlinks_cb, NULL); + + count = 0; + list = udev_device_get_devlinks_list(device); + while (list != NULL) { + printf("link: '%s'\n", udev_list_get_name(list)); + count++; + list = udev_list_get_next(list); + } printf("found %i links\n", count); - count = udev_device_get_properties(device, print_properties_cb, NULL); + + count = 0; + list = udev_device_get_properties_list(device); + while (list != NULL) { + printf("property: '%s=%s'\n", udev_list_get_name(list), udev_list_get_value(list)); + count++; + list = udev_list_get_next(list); + } printf("found %i properties\n", count); + + str = udev_device_get_attr_value(device, "dev"); + printf("attr{dev}: '%s'\n", str); + printf("\n"); } @@ -99,12 +106,14 @@ static int test_device_parents(struct udev *udev, const char *syspath) if (device == NULL) return -1; + printf("looking at parents\n"); device_parent = device; do { print_device(device_parent); device_parent = udev_device_get_parent(device_parent); } while (device_parent != NULL); + printf("looking at parents again\n"); device_parent = device; do { print_device(device_parent); @@ -129,20 +138,31 @@ static int test_device_devnum(struct udev *udev) return 0; } -static int devices_enum_cb(struct udev_device *device, void *data) -{ - printf("device: '%s' (%s) '%s'\n", - udev_device_get_syspath(device), - udev_device_get_subsystem(device), - udev_device_get_sysname(device)); - return 0; -} - static int test_enumerate(struct udev *udev, const char *subsystem) { - int count; + struct udev_enumerate *enumerate; + struct udev_list *list; + int count = 0; - count = udev_enumerate_devices(udev, subsystem, devices_enum_cb, NULL); + enumerate = udev_enumerate_new_from_subsystems(udev, NULL); + if (enumerate == NULL) + return -1; + list = udev_enumerate_get_devices_list(enumerate); + while (list != NULL) { + struct udev_device *device; + + device = udev_device_new_from_syspath(udev, udev_list_get_name(list)); + if (device != NULL) { + printf("device: '%s' (%s) '%s'\n", + udev_device_get_syspath(device), + udev_device_get_subsystem(device), + udev_device_get_sysname(device)); + udev_device_unref(device); + count++; + } + list = udev_list_get_next(list); + } + udev_enumerate_unref(enumerate); printf("found %i devices\n\n", count); return count; } diff --git a/udev/udevadm-info.c b/udev/udevadm-info.c index dbcaaffcd..6a0425769 100644 --- a/udev/udevadm-info.c +++ b/udev/udevadm-info.c @@ -126,127 +126,43 @@ static int print_device_chain(struct udev_device *device) return 0; } -static int print_record_devlinks_cb(struct udev_device *device, const char *value, void *data) -{ - size_t len; - - len = strlen(udev_get_dev_path(udev_device_get_udev(device))); - printf("S: %s\n", &value[len+1]); - return 0; -} - -static int print_record_properties_cb(struct udev_device *device, const char *key, const char *value, void *data) -{ - printf("E: %s=%s\n", key, value); - return 0; -} - static void print_record(struct udev_device *device) { size_t len; int i; + struct udev_list *list; printf("P: %s\n", udev_device_get_devpath(device)); + len = strlen(udev_get_dev_path(udev_device_get_udev(device))); printf("N: %s\n", &udev_device_get_devnode(device)[len+1]); + i = device_get_devlink_priority(device); if (i != 0) printf("L: %i\n", i); + i = device_get_num_fake_partitions(device); if (i != 0) printf("A:%u\n", i); + i = device_get_ignore_remove(device); if (i != 0) printf("R:%u\n", i); - udev_device_get_devlinks(device, print_record_devlinks_cb, NULL); - udev_device_get_properties(device, print_record_properties_cb, NULL); - printf("\n"); -} -static int export_all_cb(struct udev_device *device, void *data) -{ - if (udev_device_get_devnode(device) != NULL) - print_record(device); - return 0; -} - -static struct udev_device *lookup_device_by_name(struct udev *udev, const char *name) -{ - struct udev_device *udev_device = NULL; - LIST_HEAD(name_list); - int count; - struct name_entry *device; - - count = udev_db_get_devices_by_name(udev, name, &name_list); - if (count <= 0) - goto out; - - info(udev, "found %i devices for '%s'\n", count, name); - - /* select the device that matches */ - list_for_each_entry(device, &name_list, node) { - struct udevice *udevice_loop; - char filename[UTIL_PATH_SIZE]; - struct stat statbuf; - - udevice_loop = udev_device_init(udev); - if (udevice_loop == NULL) - break; - if (udev_db_get_device(udevice_loop, device->name) != 0) - goto next; - info(udev, "found db entry '%s'\n", device->name); - /* make sure, we don't get a link of a different device */ - util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, name, sizeof(filename)); - if (stat(filename, &statbuf) != 0) - goto next; - if (major(udevice_loop->devt) > 0 && udevice_loop->devt != statbuf.st_rdev) { - info(udev, "skip '%s', dev_t doesn't match\n", udevice_loop->name); - goto next; - } - util_strlcpy(filename, udev_get_sys_path(udev), sizeof(filename)); - util_strlcat(filename, udevice_loop->dev->devpath, sizeof(filename)); - udev_device = udev_device_new_from_syspath(udev, filename); - udev_device_cleanup(udevice_loop); - break; -next: - udev_device_cleanup(udevice_loop); + list = udev_device_get_devlinks_list(device); + while (list != NULL) { + len = strlen(udev_get_dev_path(udev_device_get_udev(device))); + printf("S: %s\n", &udev_list_get_name(list)[len+1]); + list = udev_list_get_next(list); } -out: - name_list_cleanup(udev, &name_list); - return udev_device; -} - -static int add_devlink_cb(struct udev_device *device, const char *value, void *data) -{ - char **links = data; - if (*links == NULL) { - *links = strdup(value); - } else { - char *str; - - asprintf(&str, "%s %s", *links, value); - free(*links); - *links = str; + list = udev_device_get_properties_list(device); + while (list != NULL) { + printf("E: %s=%s\n", udev_list_get_name(list), udev_list_get_value(list)); + list = udev_list_get_next(list); } - return 0; -} - -static int add_devlink_noroot_cb(struct udev_device *device, const char *value, void *data) -{ - size_t len; - - len = strlen(udev_get_dev_path(udev_device_get_udev(device))); - value = &value[len+1]; - return add_devlink_cb(device, value, data); -} -static int print_property_cb(struct udev_device *device, const char *key, const char *value, void *data) -{ - printf("%s=%s\n", key, value); - return 0; + printf("\n"); } static int stat_device(const char *name, int export, const char *prefix) @@ -268,6 +184,30 @@ static int stat_device(const char *name, int export, const char *prefix) return 0; } +static int export_devices(struct udev *udev) +{ + struct udev_enumerate *enumerate; + struct udev_list *list; + + enumerate = udev_enumerate_new_from_subsystems(udev, NULL); + if (enumerate == NULL) + return -1; + list = udev_enumerate_get_devices_list(enumerate); + while (list != NULL) { + struct udev_device *device; + + device = udev_device_new_from_syspath(udev, udev_list_get_name(list)); + if (device != NULL) { + if (udev_device_get_devnode(device) != NULL) + print_record(device); + udev_device_unref(device); + } + list = udev_list_get_next(list); + } + udev_enumerate_unref(enumerate); + return 0; +} + int udevadm_info(struct udev *udev, int argc, char *argv[]) { struct udev_device *device = NULL; @@ -276,7 +216,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) const char *export_prefix = NULL; char path[UTIL_PATH_SIZE]; char name[UTIL_PATH_SIZE]; - char *links; + struct udev_list *list; int rc = 0; static const struct option options[] = { @@ -313,6 +253,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) while (1) { int option; + struct stat statbuf; option = getopt_long(argc, argv, "aed:n:p:q:rxPVh", options, NULL); if (option == -1) @@ -327,12 +268,37 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) goto exit; } /* remove /dev if given */ - if (strncmp(optarg, udev_get_dev_path(udev), strlen(udev_get_dev_path(udev))) == 0) - util_strlcpy(name, &optarg[strlen(udev_get_dev_path(udev))+1], sizeof(name)); - else + if (strncmp(optarg, udev_get_dev_path(udev), strlen(udev_get_dev_path(udev))) != 0) { + util_strlcpy(name, udev_get_dev_path(udev), sizeof(name)); + util_strlcat(name, "/", sizeof(name)); + util_strlcat(name, optarg, sizeof(name)); + } else { util_strlcpy(name, optarg, sizeof(name)); + } util_remove_trailing_chars(name, '/'); - device = lookup_device_by_name(udev, name); + if (stat(name, &statbuf) < 0) { + fprintf(stderr, "device node not found\n"); + rc = 2; + goto exit; + } else { + char type; + + if (S_ISBLK(statbuf.st_mode)) { + type = 'b'; + } else if (S_ISCHR(statbuf.st_mode)) { + type = 'c'; + } else { + fprintf(stderr, "device node has wrong file type\n"); + rc = 2; + goto exit; + } + device = udev_device_new_from_devnum(udev, type, statbuf.st_rdev); + if (device == NULL) { + fprintf(stderr, "device node not found\n"); + rc = 2; + goto exit; + } + } break; case 'p': if (device != NULL) { @@ -349,6 +315,11 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) } util_remove_trailing_chars(path, '/'); device = udev_device_new_from_syspath(udev, path); + if (device == NULL) { + fprintf(stderr, "device path not found\n"); + rc = 2; + goto exit; + } break; case 'q': action = ACTION_QUERY; @@ -388,7 +359,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) action = ACTION_ATTRIBUTE_WALK; break; case 'e': - udev_enumerate_devices(udev, NULL, export_all_cb, NULL); + export_devices(udev); goto exit; case 'x': export = 1; @@ -445,19 +416,31 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) } break; case QUERY_SYMLINK: - links = NULL; - if (root) - udev_device_get_devlinks(device, add_devlink_cb, &links); - else - udev_device_get_devlinks(device, add_devlink_noroot_cb, &links); - printf("%s\n", links); - free(links); + list = udev_device_get_devlinks_list(device); + while (list != NULL) { + if (root) { + printf("%s", udev_list_get_name(list)); + } else { + size_t len; + + len = strlen(udev_get_dev_path(udev_device_get_udev(device))); + printf("%s", &udev_list_get_name(list)[len+1]); + } + list = udev_list_get_next(list); + if (list != NULL) + printf(" "); + } + printf("\n"); break; case QUERY_PATH: printf("%s\n", udev_device_get_devpath(device)); goto exit; case QUERY_ENV: - udev_device_get_properties(device, print_property_cb, NULL); + list = udev_device_get_properties_list(device); + while (list != NULL) { + printf("%s=%s\n", udev_list_get_name(list), udev_list_get_value(list)); + list = udev_list_get_next(list); + } break; case QUERY_ALL: print_record(device); diff --git a/udev/udevadm-monitor.c b/udev/udevadm-monitor.c index a798a8162..26efa528a 100644 --- a/udev/udevadm-monitor.c +++ b/udev/udevadm-monitor.c @@ -41,18 +41,6 @@ static void asmlinkage sig_handler(int signum) udev_exit = 1; } -static int print_properties_cb(struct udev_device *udev_device, const char *key, const char *value, void *data) -{ - printf("%s=%s\n", key, value); - return 0; -} - -static void print_properties(struct udev_device *device) -{ - udev_device_get_properties(device, print_properties_cb, NULL); - printf("\n"); -} - int udevadm_monitor(struct udev *udev, int argc, char *argv[]) { struct sigaction act; @@ -178,8 +166,16 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) udev_device_get_action(device), udev_device_get_devpath(device), udev_device_get_subsystem(device)); - if (env) - print_properties(device); + if (env) { + struct udev_list *list; + + list = udev_device_get_properties_list(device); + while (list != NULL) { + printf("%s=%s\n", udev_list_get_name(list), udev_list_get_value(list)); + list = udev_list_get_next(list); + } + printf("\n"); + } udev_device_unref(device); } @@ -191,8 +187,16 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) udev_device_get_action(device), udev_device_get_devpath(device), udev_device_get_subsystem(device)); - if (env) - print_properties(device); + if (env) { + struct udev_list *list; + + list = udev_device_get_properties_list(device); + while (list != NULL) { + printf("%s=%s\n", udev_list_get_name(list), udev_list_get_value(list)); + list = udev_list_get_next(list); + } + printf("\n"); + } udev_device_unref(device); } } -- 2.30.2