chiark / gitweb /
udevadm: do not free node on success
[elogind.git] / src / udev / udevadm-hwdb.c
index fd288db1cb73d68cf162743b46c0ca807225e0b1..b18b28aca72ce393cdef2c5f7583a1fb97d68475 100644 (file)
@@ -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;
+                        char _cleanup_free_ *s = NULL;
                         ssize_t off;
+                        struct trie_node _cleanup_free_ *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 {
@@ -469,20 +466,23 @@ static int import_file(struct trie *trie, const char *filename) {
 }
 
 static void help(void) {
-        printf("Usage: udevadm hwdb [--create] [--help]\n"
+        printf("Usage: udevadm hwdb OPTIONS\n"
                "  --update            update the hardware database\n"
-               "  --test <modalias>   query database and print result\n"
+               "  --test=<modalias>   query database and print result\n"
+               "  --root=<path>       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 +491,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 +502,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 +518,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 +541,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,11 +569,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(HWDB_BIN, 0755);
-                err = trie_store(trie, 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",
-                                  HWDB_BIN, strerror(-err));
+                        log_error("Failure writing database %s: %s", hwdb_bin, strerror(-err));
                         rc = EXIT_FAILURE;
                 }
         }