summaryrefslogtreecommitdiff
path: root/src/udev/udevadm-hwdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/udev/udevadm-hwdb.c')
-rw-r--r--src/udev/udevadm-hwdb.c99
1 files changed, 53 insertions, 46 deletions
diff --git a/src/udev/udevadm-hwdb.c b/src/udev/udevadm-hwdb.c
index 00c0d3d4c4..3e849aaed6 100644
--- a/src/udev/udevadm-hwdb.c
+++ b/src/udev/udevadm-hwdb.c
@@ -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 {
@@ -471,18 +468,21 @@ static int import_file(struct trie *trie, const char *filename) {
static void help(void) {
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;
}
}