From: Kay Sievers Date: Fri, 26 Sep 2008 17:44:53 +0000 (+0200) Subject: libudev: rework list handling X-Git-Tag: 174~1527 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;ds=sidebyside;h=e345e2670a8c17f5e1145cc554b7a7646e271032;p=elogind.git libudev: rework list handling --- diff --git a/TODO b/TODO index 5c8cdc379..56899a94c 100644 --- a/TODO +++ b/TODO @@ -3,7 +3,6 @@ o add DVB variables to kernel, and drop shell script rule o add watershed extra - o replace list.h with ccan list.h which is gpl-v2-or-later version o get all distros to agree on a default set of rules o rework rules to a match-action list, instead of a rules array o log warning if the kernel uses CONFIG_SYSFS_DEPRECATED*=y, diff --git a/extras/collect/collect.c b/extras/collect/collect.c index 8c141d2a5..14184a5e0 100644 --- a/extras/collect/collect.c +++ b/extras/collect/collect.c @@ -31,7 +31,7 @@ #include #include -#include "../../udev/lib/list.h" +#include "../../udev/list.h" #define TMPFILE UDEV_PREFIX "/dev/.udev/collect" #define BUFSIZE 16 diff --git a/udev/Makefile.am b/udev/Makefile.am index f15330b4f..6f9acce5a 100644 --- a/udev/Makefile.am +++ b/udev/Makefile.am @@ -25,7 +25,7 @@ common_files = \ udev_sysfs.c \ udev_utils.c \ udev_utils_file.c \ - lib/list.h \ + list.h \ lib/libudev.h \ lib/libudev-private.h \ lib/libudev.c \ diff --git a/udev/lib/Makefile.am b/udev/lib/Makefile.am index 0386465e8..e800cf7f4 100644 --- a/udev/lib/Makefile.am +++ b/udev/lib/Makefile.am @@ -24,8 +24,7 @@ libudev_la_SOURCES =\ libudev-device.c \ libudev-enumerate.c \ libudev-ctrl.c \ - libudev-monitor.c \ - list.h + libudev-monitor.c libudev_la_LDFLAGS = \ -version-info $(LIBUDEV_LT_CURRENT):$(LIBUDEV_LT_REVISION):$(LIBUDEV_LT_AGE) \ diff --git a/udev/lib/exported_symbols b/udev/lib/exported_symbols index 9650ef4d9..0203b1c1f 100644 --- a/udev/lib/exported_symbols +++ b/udev/lib/exported_symbols @@ -9,9 +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_list_entry_get_next +udev_list_entry_get_name +udev_list_entry_get_value udev_device_new_from_syspath udev_device_new_from_devnum udev_device_get_parent diff --git a/udev/lib/libudev-device.c b/udev/lib/libudev-device.c index de4bd48e1..6da6cd93e 100644 --- a/udev/lib/libudev-device.c +++ b/udev/lib/libudev-device.c @@ -39,8 +39,8 @@ struct udev_device { const char *sysname; char *devnode; char *subsystem; - struct list_head devlink_list; - struct list_head properties_list; + struct list_node devlink_list; + struct list_node properties_list; char *action; int event_timeout; char *driver; @@ -52,7 +52,7 @@ struct udev_device { int num_fake_partitions; int devlink_priority; int ignore_remove; - struct list_head attr_list; + struct list_node attr_list; int info_loaded; }; @@ -206,9 +206,9 @@ struct udev_device *device_init(struct udev *udev) memset(udev_device, 0x00, sizeof(struct udev_device)); udev_device->refcount = 1; udev_device->udev = udev; - INIT_LIST_HEAD(&udev_device->devlink_list); - INIT_LIST_HEAD(&udev_device->properties_list); - INIT_LIST_HEAD(&udev_device->attr_list); + list_init(&udev_device->devlink_list); + list_init(&udev_device->properties_list); + list_init(&udev_device->attr_list); info(udev_device->udev, "udev_device: %p created\n", udev_device); return udev_device; } @@ -287,7 +287,7 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de while (list != NULL) { struct udev_device *device_loop; - device_loop = udev_device_new_from_syspath(udev, udev_list_get_name(list)); + device_loop = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list)); if (device_loop != NULL) { if (udev_device_get_devnum(device_loop) == devnum) { device = device_loop; @@ -295,7 +295,7 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de } udev_device_unref(device_loop); } - list = udev_list_get_next(list); + list = udev_list_entry_get_next(list); } udev_enumerate_unref(enumerate); return device; @@ -511,9 +511,9 @@ const char *udev_device_get_subsystem(struct udev_device *udev_device) * * 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. + * udev_list_entry_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 + * udev_list_entry_get_name(). The path is an absolute path, and starts with * the device directory. * * Returns: the first entry of the device node link list @@ -532,7 +532,7 @@ struct udev_list *udev_device_get_devlinks_list(struct udev_device *udev_device) * @udev_device: udev device * * Retrieve the list of key/value device properties of the udev - * device. The next list entry can be retrieved with udev_list_next(), + * device. The next list entry can be retrieved with udev_list_entry_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(). @@ -598,11 +598,11 @@ const char *udev_device_get_attr_value(struct udev_device *udev_device, const ch /* look for possibly already cached result */ 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_value(list); + if (strcmp(udev_list_entry_get_name(list), attr) == 0) { + info(udev_device->udev, "got '%s' (%s) from cache\n", attr, udev_list_entry_get_value(list)); + return udev_list_entry_get_value(list); } - list = udev_list_get_next(list); + list = udev_list_entry_get_next(list); } util_strlcpy(path, udev_device_get_syspath(udev_device), sizeof(path)); @@ -627,8 +627,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); - list = list_insert(udev_device->udev, &udev_device->attr_list, attr, pos, 0); - val = udev_list_get_value(list); + list = list_insert_entry(udev_device->udev, &udev_device->attr_list, attr, pos, 0); + val = udev_list_entry_get_value(list); } } goto out; @@ -659,8 +659,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); - list = list_insert(udev_device->udev, &udev_device->attr_list, attr, value, 0); - val = udev_list_get_value(list); + list = list_insert_entry(udev_device->udev, &udev_device->attr_list, attr, value, 0); + val = udev_list_entry_get_value(list); out: return val; } @@ -697,14 +697,14 @@ int device_set_devnode(struct udev_device *udev_device, const char *devnode) int device_add_devlink(struct udev_device *udev_device, const char *devlink) { - if (list_insert(udev_device->udev, &udev_device->devlink_list, devlink, NULL, 0) == NULL) + if (list_insert_entry(udev_device->udev, &udev_device->devlink_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 (list_insert(udev_device->udev, &udev_device->properties_list, key, value, 0) == NULL) + if (list_insert_entry(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 6d638670c..fc853b8d6 100644 --- a/udev/lib/libudev-enumerate.c +++ b/udev/lib/libudev-enumerate.c @@ -32,7 +32,7 @@ struct udev_enumerate { struct udev *udev; int refcount; - struct list_head devices_list; + struct list_node devices_list; }; struct udev_enumerate *udev_enumerate_ref(struct udev_enumerate *udev_enumerate) @@ -63,7 +63,7 @@ struct udev_list *udev_enumerate_get_list(struct udev_enumerate *udev_enumerate) 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; @@ -87,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)); - list_insert(udev, device_list, syspath, NULL, 1); + list_insert_entry(udev, device_list, syspath, NULL, 1); } closedir(dir); return 0; @@ -95,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; @@ -162,7 +162,7 @@ struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev, con memset(udev_enumerate, 0x00, (sizeof(struct udev_enumerate))); udev_enumerate->refcount = 1; udev_enumerate->udev = udev; - INIT_LIST_HEAD(&udev_enumerate->devices_list); + 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)); @@ -177,9 +177,9 @@ struct udev_enumerate *udev_enumerate_new_from_subsystems(struct udev *udev, con /* 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); + 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 udev_enumerate; } diff --git a/udev/lib/libudev-list.c b/udev/lib/libudev-list.c new file mode 100644 index 000000000..553edf69f --- /dev/null +++ b/udev/lib/libudev-list.c @@ -0,0 +1,193 @@ +/* + * libudev - interface to udev device information + * + * Copyright (C) 2008 Kay Sievers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include "libudev.h" +#include "libudev-private.h" + +struct udev_list { + struct udev *udev; + struct list_node node; + struct list_node *list; + char *name; + char *value; +}; + +static struct udev_list *node_to_entry(struct list_node *node) +{ + char *list; + + list = (char *)node; + list -= offsetof(struct udev_list, node); + return (struct udev_list *)list; +} + +void list_init(struct list_node *list) +{ + list->next = list; + list->prev = list; +} + +static int list_empty(struct list_node *list) +{ + return list->next == list; +} + +#if 0 +static void list_add(struct list_node *new, struct list_node *list) +{ + struct list_node *next = list->next; + + next->prev = new; + new->next = next; + new->prev = list; + list->next = new; +} +#endif + +static void list_add_to_end(struct list_node *new, struct list_node *list) +{ + struct list_node *prev = list->prev; + + list->prev = new; + new->next = list; + new->prev = prev; + prev->next = new; +} + +static void list_del(struct list_node *entry) +{ + struct list_node *prev = entry->prev; + struct list_node *next = entry->next; + + next->prev = prev; + prev->next = next; +} + +#define list_for_each_entry(pos, list) \ + for (pos = node_to_entry((list)->next); \ + &pos->node != (list); \ + pos = node_to_entry(pos->node.next)) + +#define list_for_each_entry_safe(pos, tmp, list) \ + for (pos = node_to_entry((list)->next), \ + tmp = node_to_entry(pos->node.next); \ + &pos->node != (list); \ + pos = tmp, tmp = node_to_entry(tmp->node.next)) + +struct udev_list *list_insert_entry(struct udev *udev, struct list_node *list, + const char *name, const char *value, int sort) +{ + struct udev_list *list_loop; + struct udev_list *list_new; + + /* avoid duplicate entries */ + list_for_each_entry(list_loop, list) { + if (strcmp(list_loop->name, name) == 0) { + dbg(udev, "'%s' is already in the list\n", name); + return list_loop; + } + } + + if (sort) { + list_for_each_entry(list_loop, list) { + if (strcmp(list_loop->name, name) > 0) + break; + } + } + + list_new = malloc(sizeof(struct udev_list)); + if (list_new == NULL) + return NULL; + memset(list_new, 0x00, sizeof(struct udev_list)); + list_new->udev = udev; + list_new->list = list; + list_new->name = strdup(name); + if (list_new->name == NULL) { + free(list_new); + return NULL; + } + if (value != NULL) { + list_new->value = strdup(value); + if (list_new->value == NULL) { + free(list_new); + return NULL; + } + } + dbg(udev, "adding '%s=%s'\n", list_new->name, list_new->value); + list_add_to_end(&list_new->node, &list_loop->node); + return list_new; +} + +void list_move_entry_to_end(struct udev_list *list_entry, struct list_node *list) +{ + list_del(&list_entry->node); + list_add_to_end(&list_entry->node, list); +} + +void list_cleanup(struct udev *udev, struct list_node *list) +{ + struct udev_list *list_loop; + struct udev_list *list_tmp; + + list_for_each_entry_safe(list_loop, list_tmp, list) { + list_del(&list_loop->node); + free(list_loop->name); + free(list_loop->value); + free(list_loop); + } +} + +struct udev_list *list_get_entry(struct list_node *list) +{ + if (list_empty(list)) + return NULL; + return node_to_entry(list->next); +} + +struct udev_list *udev_list_entry_get_next(struct udev_list *list_entry) +{ + struct list_node *next; + + next = list_entry->node.next; + /* empty list or no more emtries */ + if (next == list_entry->list) + return NULL; + return node_to_entry(next); +} + +const char *udev_list_entry_get_name(struct udev_list *list_entry) +{ + if (list_entry == NULL) + return NULL; + return list_entry->name; +} + +const char *udev_list_entry_get_value(struct udev_list *list_entry) +{ + if (list_entry == NULL) + return NULL; + return list_entry->value; +} diff --git a/udev/lib/libudev-private.h b/udev/lib/libudev-private.h index 5be798317..6abd7b7c2 100644 --- a/udev/lib/libudev-private.h +++ b/udev/lib/libudev-private.h @@ -22,7 +22,6 @@ #include #include "libudev.h" -#include "list.h" #ifdef USE_LOG #ifdef USE_DEBUG @@ -106,22 +105,20 @@ 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); +struct list_node { + struct list_node *next, *prev; +}; +extern void list_init(struct list_node *list); +extern struct udev_list *list_insert_entry(struct udev *udev, struct list_node *name_list, + const char *name, const char *value, int sort); +extern struct udev_list *list_get_entry(struct list_node *list); +extern void list_move_entry_to_end(struct udev_list *list_entry, struct list_node *list); +extern void list_cleanup(struct udev *udev, struct list_node *name_list); /* libudev-utils */ #define UTIL_PATH_SIZE 1024 #define UTIL_LINE_SIZE 2048 #define UTIL_NAME_SIZE 512 -struct util_name_entry { - struct list_head node; - char *name; - char *value; - int *i; -}; 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); diff --git a/udev/lib/libudev.h b/udev/lib/libudev.h index d2e57d418..28a37af17 100644 --- a/udev/lib/libudev.h +++ b/udev/lib/libudev.h @@ -55,9 +55,9 @@ extern void udev_selinux_setfscreatecon(struct udev *udev, const char *file, uns 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); +extern struct udev_list *udev_list_entry_get_next(struct udev_list *list_entry); +extern const char *udev_list_entry_get_name(struct udev_list *list_entry); +extern const char *udev_list_entry_get_value(struct udev_list *list_entry); /* sys devices */ extern struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath); diff --git a/udev/lib/test-libudev.c b/udev/lib/test-libudev.c index 19968a173..f361ab12a 100644 --- a/udev/lib/test-libudev.c +++ b/udev/lib/test-libudev.c @@ -63,18 +63,18 @@ static void print_device(struct udev_device *device) count = 0; list = udev_device_get_devlinks_list(device); while (list != NULL) { - printf("link: '%s'\n", udev_list_get_name(list)); + printf("link: '%s'\n", udev_list_entry_get_name(list)); count++; - list = udev_list_get_next(list); + list = udev_list_entry_get_next(list); } printf("found %i links\n", count); 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)); + printf("property: '%s=%s'\n", udev_list_entry_get_name(list), udev_list_entry_get_value(list)); count++; - list = udev_list_get_next(list); + list = udev_list_entry_get_next(list); } printf("found %i properties\n", count); @@ -154,7 +154,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) while (list != NULL) { struct udev_device *device; - device = udev_device_new_from_syspath(udev, udev_list_get_name(list)); + device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list)); if (device != NULL) { printf("device: '%s' (%s) '%s'\n", udev_device_get_syspath(device), @@ -163,7 +163,7 @@ static int test_enumerate(struct udev *udev, const char *subsystem) udev_device_unref(device); count++; } - list = udev_list_get_next(list); + list = udev_list_entry_get_next(list); } udev_enumerate_unref(enumerate); printf("found %i devices\n\n", count); diff --git a/udev/lib/list.h b/udev/list.h similarity index 100% rename from udev/lib/list.h rename to udev/list.h diff --git a/udev/udev.h b/udev/udev.h index b8ae5f00a..102f15d0b 100644 --- a/udev/udev.h +++ b/udev/udev.h @@ -26,7 +26,7 @@ #define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE 1 #include "lib/libudev.h" #include "lib/libudev-private.h" -#include "lib/list.h" +#include "list.h" #define ALLOWED_CHARS "#+-.:=@_" #define ALLOWED_CHARS_FILE ALLOWED_CHARS "/" diff --git a/udev/udevadm-info.c b/udev/udevadm-info.c index 2f41b7adf..f9e2bb207 100644 --- a/udev/udevadm-info.c +++ b/udev/udevadm-info.c @@ -152,14 +152,14 @@ static void print_record(struct udev_device *device) 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); + printf("S: %s\n", &udev_list_entry_get_name(list)[len+1]); + list = udev_list_entry_get_next(list); } 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); + printf("E: %s=%s\n", udev_list_entry_get_name(list), udev_list_entry_get_value(list)); + list = udev_list_entry_get_next(list); } printf("\n"); @@ -196,13 +196,13 @@ static int export_devices(struct udev *udev) while (list != NULL) { struct udev_device *device; - device = udev_device_new_from_syspath(udev, udev_list_get_name(list)); + device = udev_device_new_from_syspath(udev, udev_list_entry_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); + list = udev_list_entry_get_next(list); } udev_enumerate_unref(enumerate); return 0; @@ -419,14 +419,14 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) list = udev_device_get_devlinks_list(device); while (list != NULL) { if (root) { - printf("%s", udev_list_get_name(list)); + printf("%s", udev_list_entry_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]); + printf("%s", &udev_list_entry_get_name(list)[len+1]); } - list = udev_list_get_next(list); + list = udev_list_entry_get_next(list); if (list != NULL) printf(" "); } @@ -438,8 +438,8 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) case QUERY_ENV: 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("%s=%s\n", udev_list_entry_get_name(list), udev_list_entry_get_value(list)); + list = udev_list_entry_get_next(list); } break; case QUERY_ALL: diff --git a/udev/udevadm-monitor.c b/udev/udevadm-monitor.c index 26efa528a..6cfad2d3b 100644 --- a/udev/udevadm-monitor.c +++ b/udev/udevadm-monitor.c @@ -171,8 +171,8 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) 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("%s=%s\n", udev_list_entry_get_name(list), udev_list_entry_get_value(list)); + list = udev_list_entry_get_next(list); } printf("\n"); } @@ -192,8 +192,8 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) 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("%s=%s\n", udev_list_entry_get_name(list), udev_list_entry_get_value(list)); + list = udev_list_entry_get_next(list); } printf("\n"); }