X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fudev%2Fudevadm-hwdb.c;h=10b490ee2ba666fcb957538816c68c18541ac96c;hp=4017526d1cda012a020ae47a0bfc9bb5c8d6bc6e;hb=3cf7b686e6b29f78de0af5929602cae4482f6d49;hpb=3a4431ef720b18daf2936bf162c0c3946b80e5b3 diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c index 4017526d1..10b490ee2 100644 --- a/src/udev/udevadm-hwdb.c +++ b/src/udev/udevadm-hwdb.c @@ -1,7 +1,7 @@ /*** This file is part of systemd. - Copyright 2012 Kay Sievers + Copyright 2012 Kay Sievers systemd is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -84,14 +84,12 @@ static int trie_children_cmp(const void *v1, const void *v2) { static int node_add_child(struct trie *trie, struct trie_node *node, struct trie_node *node_child, uint8_t c) { struct trie_child_entry *child; - int err = 0; /* extend array, add new entry, sort for bisection */ child = realloc(node->children, (node->children_count + 1) * sizeof(struct trie_child_entry)); - if (!child) { - err = -ENOMEM; - goto out; - } + if (!child) + return -ENOMEM; + node->children = child; trie->children_count++; node->children[node->children_count].c = c; @@ -99,8 +97,8 @@ static int node_add_child(struct trie *trie, struct trie_node *node, struct trie node->children_count++; qsort(node->children, node->children_count, sizeof(struct trie_child_entry), trie_children_cmp); trie->nodes_count++; -out: - return err; + + return 0; } static struct trie_node *node_lookup(const struct trie_node *node, uint8_t c) { @@ -183,46 +181,44 @@ static int trie_insert(struct trie *trie, struct trie_node *node, const char *se struct trie_node *child; for (p = 0; (c = trie->strings->buf[node->prefix_off + p]); p++) { - char *s; + _cleanup_free_ char *s = NULL; ssize_t off; + _cleanup_free_ struct trie_node *new_child = NULL; if (c == search[i + p]) continue; /* split node */ - child = calloc(sizeof(struct trie_node), 1); - if (!child) { - err = -ENOMEM; - goto out; - } + new_child = calloc(sizeof(struct trie_node), 1); + if (!new_child) + return -ENOMEM; /* move values from parent to child */ - child->prefix_off = node->prefix_off + p+1; - child->children = node->children; - child->children_count = node->children_count; - child->values = node->values; - child->values_count = node->values_count; + new_child->prefix_off = node->prefix_off + p+1; + new_child->children = node->children; + new_child->children_count = node->children_count; + new_child->values = node->values; + new_child->values_count = node->values_count; /* update parent; use strdup() because the source gets realloc()d */ s = strndup(trie->strings->buf + node->prefix_off, p); - if (!s) { - err = -ENOMEM; - goto out; - } + if (!s) + return -ENOMEM; + off = strbuf_add_string(trie->strings, s, p); - free(s); - if (off < 0) { - err = off; - goto out; - } + if (off < 0) + return off; + node->prefix_off = off; node->children = NULL; node->children_count = 0; node->values = NULL; node->values_count = 0; - err = node_add_child(trie, node, child, c); + err = node_add_child(trie, node, new_child, c); if (err) - goto out; + return err; + + new_child = NULL; /* avoid cleanup */ break; } i += p; @@ -237,27 +233,28 @@ static int trie_insert(struct trie *trie, struct trie_node *node, const char *se /* new child */ child = calloc(sizeof(struct trie_node), 1); - if (!child) { - err = -ENOMEM; - goto out; - } + if (!child) + return -ENOMEM; + off = strbuf_add_string(trie->strings, search + i+1, strlen(search + i+1)); if (off < 0) { - err = off; - goto out; + free(child); + return off; } + child->prefix_off = off; err = node_add_child(trie, node, child, c); - if (err) - goto out; + if (err) { + free(child); + return err; + } + return trie_node_add_value(trie, child, key, value); } node = child; i++; } -out: - return err; } struct trie_f { @@ -409,14 +406,12 @@ static int import_file(struct trie *trie, const char *filename) { FILE *f; char line[LINE_MAX]; char match[LINE_MAX]; - char cond[LINE_MAX]; f = fopen(filename, "re"); if (f == NULL) return -errno; match[0] = '\0'; - cond[0] = '\0'; while (fgets(line, sizeof(line), f)) { size_t len; @@ -426,7 +421,6 @@ static int import_file(struct trie *trie, const char *filename) { /* new line, new record */ if (line[0] == '\n') { match[0] = '\0'; - cond[0] = '\0'; continue; } @@ -439,20 +433,10 @@ static int import_file(struct trie *trie, const char *filename) { /* start of new record */ if (match[0] == '\0') { strcpy(match, line); - cond[0] = '\0'; - continue; - } - - if (line[0] == '+') { - strcpy(cond, line); continue; } - /* TODO: support +; skip the entire record until we support it */ - if (cond[0] != '\0') - continue; - - /* value lines */ + /* value line */ if (line[0] == ' ') { char *value; @@ -462,27 +446,33 @@ static int import_file(struct trie *trie, const char *filename) { value[0] = '\0'; value++; trie_insert(trie, trie->root, match, line, value); + continue; } + + log_error("Error parsing line '%s' in '%s\n", line, filename); } fclose(f); return 0; } static void help(void) { - printf("Usage: udevadm hwdb [--create] [--help]\n" + printf("Usage: udevadm hwdb OPTIONS\n" " --update update the hardware database\n" - " --test query database and print result\n" + " --test= query database and print result\n" + " --root= alternative root path in the filesystem\n" " --help\n\n"); } static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { static const struct option options[] = { { "update", no_argument, NULL, 'u' }, + { "root", required_argument, NULL, 'r' }, { "test", required_argument, NULL, 't' }, { "help", no_argument, NULL, 'h' }, {} }; const char *test = NULL; + const char *root = ""; bool update = false; struct trie *trie = NULL; int err; @@ -491,7 +481,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { for (;;) { int option; - option = getopt_long(argc, argv, "ut:h", options, NULL); + option = getopt_long(argc, argv, "ut:r:h", options, NULL); if (option == -1) break; @@ -502,6 +492,9 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { case 't': test = optarg; break; + case 'r': + root = optarg; + break; case 'h': help(); return EXIT_SUCCESS; @@ -515,6 +508,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { if (update) { char **files, **f; + _cleanup_free_ char *hwdb_bin = NULL; trie = calloc(sizeof(struct trie), 1); if (!trie) { @@ -537,7 +531,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { } trie->nodes_count++; - err = conf_files_list_strv(&files, ".hwdb", (const char **)conf_file_dirs); + err = conf_files_list_strv(&files, ".hwdb", root, conf_file_dirs); if (err < 0) { log_error("failed to enumerate hwdb files: %s\n", strerror(-err)); rc = EXIT_FAILURE; @@ -565,10 +559,14 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { log_debug("strings dedup'ed: %8zu bytes (%8zu)\n", trie->strings->dedup_len, trie->strings->dedup_count); - mkdir_parents("/etc/udev/hwdb.bin", 0755); - err = trie_store(trie, "/etc/udev/hwdb.bin"); + if (asprintf(&hwdb_bin, "%s/etc/udev/hwdb.bin", root) < 0) { + rc = EXIT_FAILURE; + goto out; + } + mkdir_parents(hwdb_bin, 0755); + err = trie_store(trie, hwdb_bin); if (err < 0) { - log_error("Failure writing hardware database '%s': %s", "/etc/udev/hwdb.bin", strerror(-err)); + log_error("Failure writing database %s: %s", hwdb_bin, strerror(-err)); rc = EXIT_FAILURE; } }