udevadm-hwdb.c revision 8b516fdea74127327b0945bb50690bd70c6b6692
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen This file is part of systemd.
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen Copyright 2012 Kay Sievers <kay@vrfy.org>
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen systemd is free software; you can redistribute it and/or modify it
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen under the terms of the GNU Lesser General Public License as published by
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen the Free Software Foundation; either version 2.1 of the License, or
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen (at your option) any later version.
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen systemd is distributed in the hope that it will be useful, but
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen WITHOUT ANY WARRANTY; without even the implied warranty of
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen Lesser General Public License for more details.
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen You should have received a copy of the GNU Lesser General Public License
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen along with systemd; If not, see <http://www.gnu.org/licenses/>.
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen * Generic udev properties, key/value database based on modalias strings.
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen * Uses a Patricia/radix trie to index all matches for efficient lookup.
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensenstatic const char * const conf_file_dirs[] = {
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen/* in-memory trie objects */
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen /* prefix, common part for all children of this node */
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen /* sorted array of pointers to children nodes */
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen /* sorted array of key/value pairs */
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen/* children array item with char (0-255) index */
struct trie_value_entry {
static int node_add_child(struct trie *trie, struct trie_node *node, struct trie_node *node_child, uint8_t c) {
if (!child)
return -ENOMEM;
search.c = c;
child = bsearch(&search, node->children, node->children_count, sizeof(struct trie_child_entry), trie_children_cmp);
if (child)
return NULL;
size_t i;
ssize_t k, v;
.key_off = k,
.value_off = v,
val = xbsearch_r(&search, node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie);
if (val) {
if (!val)
return -ENOMEM;
size_t i = 0;
int err = 0;
size_t p;
uint8_t c;
if (c == search[i + p])
if (!new_child)
return -ENOMEM;
return -ENOMEM;
if (off < 0)
return off;
if (err)
return err;
c = search[i];
if (!child) {
if (!child)
return -ENOMEM;
if (off < 0) {
return off;
if (err) {
return err;
struct trie_f {
FILE *f;
uint64_t i;
uint64_t i;
struct trie_node_f n = {
if (!children)
return -ENOMEM;
if (child_off < 0) {
return child_off;
struct trie_value_entry_f v = {
return node_off;
struct trie_f t = {
struct trie_header_f h = {
int err;
if (err < 0)
return err;
if (err < 0) {
fclose(t.f);
return -errno;
if (err < 0) {
fclose(t.f);
return -errno;
if (err)
fclose(t.f);
char *value;
if (!value) {
return -EINVAL;
value++;
line++;
return -EINVAL;
FILE *f;
if (f == NULL)
return -errno;
char *pos;
if (pos)
len--;
switch (state) {
case HW_NONE:
if (len == 0)
case HW_MATCH:
if (len == 0) {
case HW_DATA:
if (len == 0) {
fclose(f);
static void help(void) {
bool update = false;
int err, c;
update = true;
case ARG_USR:
help();
return EXIT_SUCCESS;
return EXIT_FAILURE;
return EXIT_FAILURE;
if (update) {
char **files, **f;
if (!trie) {
goto out;
goto out;
goto out;
if (err < 0) {
goto out;
if (!hwdb_bin) {
goto out;
if (err < 0) {
if (test) {
if (hwdb) {
out:
if (trie) {
return rc;