mirror of
https://github.com/systemd/systemd.git
synced 2025-08-23 05:49:52 +03:00
hwdb: store file-name and file-number with properties
Extend the hwdb to store the source file-name and file-number for each property. We simply extend the stored value struct with the new information. It is fully backwards compatible and old readers will continue to work. The libudev/sd-hwdb reader is updated in a followup. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
This commit is contained in:
@ -85,6 +85,8 @@ struct trie_child_entry {
|
|||||||
struct trie_value_entry {
|
struct trie_value_entry {
|
||||||
size_t key_off;
|
size_t key_off;
|
||||||
size_t value_off;
|
size_t value_off;
|
||||||
|
size_t filename_off;
|
||||||
|
size_t line_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int trie_children_cmp(const void *v1, const void *v2) {
|
static int trie_children_cmp(const void *v1, const void *v2) {
|
||||||
@ -157,14 +159,19 @@ static int trie_values_cmp(const void *v1, const void *v2, void *arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int trie_node_add_value(struct trie *trie, struct trie_node *node,
|
static int trie_node_add_value(struct trie *trie, struct trie_node *node,
|
||||||
const char *key, const char *value) {
|
const char *key, const char *value,
|
||||||
ssize_t k, v;
|
const char *filename, size_t line_number) {
|
||||||
|
ssize_t k, v, fn;
|
||||||
struct trie_value_entry *val;
|
struct trie_value_entry *val;
|
||||||
|
int r;
|
||||||
|
|
||||||
k = strbuf_add_string(trie->strings, key, strlen(key));
|
k = strbuf_add_string(trie->strings, key, strlen(key));
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
return k;
|
return k;
|
||||||
v = strbuf_add_string(trie->strings, value, strlen(value));
|
v = strbuf_add_string(trie->strings, value, strlen(value));
|
||||||
|
if (v < 0)
|
||||||
|
return v;
|
||||||
|
fn = strbuf_add_string(trie->strings, filename, strlen(filename));
|
||||||
if (v < 0)
|
if (v < 0)
|
||||||
return v;
|
return v;
|
||||||
|
|
||||||
@ -176,8 +183,20 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node,
|
|||||||
|
|
||||||
val = xbsearch_r(&search, node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie);
|
val = xbsearch_r(&search, node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie);
|
||||||
if (val) {
|
if (val) {
|
||||||
|
/*
|
||||||
|
* At this point we have 2 identical properties on the same match-string. We
|
||||||
|
* strictly order them by filename+line-number, since we know the dynamic
|
||||||
|
* runtime lookup does the same for multiple matching nodes.
|
||||||
|
*/
|
||||||
|
r = strcmp(filename, trie->strings->buf + val->filename_off);
|
||||||
|
if (r < 0 ||
|
||||||
|
(r == 0 && line_number < val->line_number))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* replace existing earlier key with new value */
|
/* replace existing earlier key with new value */
|
||||||
val->value_off = v;
|
val->value_off = v;
|
||||||
|
val->filename_off = fn;
|
||||||
|
val->line_number = line_number;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,13 +209,16 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node,
|
|||||||
node->values = val;
|
node->values = val;
|
||||||
node->values[node->values_count].key_off = k;
|
node->values[node->values_count].key_off = k;
|
||||||
node->values[node->values_count].value_off = v;
|
node->values[node->values_count].value_off = v;
|
||||||
|
node->values[node->values_count].filename_off = fn;
|
||||||
|
node->values[node->values_count].line_number = line_number;
|
||||||
node->values_count++;
|
node->values_count++;
|
||||||
qsort_r(node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie);
|
qsort_r(node->values, node->values_count, sizeof(struct trie_value_entry), trie_values_cmp, trie);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int trie_insert(struct trie *trie, struct trie_node *node, const char *search,
|
static int trie_insert(struct trie *trie, struct trie_node *node, const char *search,
|
||||||
const char *key, const char *value) {
|
const char *key, const char *value,
|
||||||
|
const char *filename, uint64_t line_number) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
@ -250,7 +272,7 @@ static int trie_insert(struct trie *trie, struct trie_node *node, const char *se
|
|||||||
|
|
||||||
c = search[i];
|
c = search[i];
|
||||||
if (c == '\0')
|
if (c == '\0')
|
||||||
return trie_node_add_value(trie, node, key, value);
|
return trie_node_add_value(trie, node, key, value, filename, line_number);
|
||||||
|
|
||||||
child = node_lookup(node, c);
|
child = node_lookup(node, c);
|
||||||
if (!child) {
|
if (!child) {
|
||||||
@ -274,7 +296,7 @@ static int trie_insert(struct trie *trie, struct trie_node *node, const char *se
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return trie_node_add_value(trie, child, key, value);
|
return trie_node_add_value(trie, child, key, value, filename, line_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
node = child;
|
node = child;
|
||||||
@ -303,7 +325,7 @@ static void trie_store_nodes_size(struct trie_f *trie, struct trie_node *node) {
|
|||||||
for (i = 0; i < node->children_count; i++)
|
for (i = 0; i < node->children_count; i++)
|
||||||
trie->strings_off += sizeof(struct trie_child_entry_f);
|
trie->strings_off += sizeof(struct trie_child_entry_f);
|
||||||
for (i = 0; i < node->values_count; i++)
|
for (i = 0; i < node->values_count; i++)
|
||||||
trie->strings_off += sizeof(struct trie_value_entry_f);
|
trie->strings_off += sizeof(struct trie_value_entry2_f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node) {
|
static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node) {
|
||||||
@ -349,12 +371,14 @@ static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node) {
|
|||||||
|
|
||||||
/* append values array */
|
/* append values array */
|
||||||
for (i = 0; i < node->values_count; i++) {
|
for (i = 0; i < node->values_count; i++) {
|
||||||
struct trie_value_entry_f v = {
|
struct trie_value_entry2_f v = {
|
||||||
.key_off = htole64(trie->strings_off + node->values[i].key_off),
|
.key_off = htole64(trie->strings_off + node->values[i].key_off),
|
||||||
.value_off = htole64(trie->strings_off + node->values[i].value_off),
|
.value_off = htole64(trie->strings_off + node->values[i].value_off),
|
||||||
|
.filename_off = htole64(trie->strings_off + node->values[i].filename_off),
|
||||||
|
.line_number = htole64(node->values[i].line_number),
|
||||||
};
|
};
|
||||||
|
|
||||||
fwrite(&v, sizeof(struct trie_value_entry_f), 1, trie->f);
|
fwrite(&v, sizeof(struct trie_value_entry2_f), 1, trie->f);
|
||||||
trie->values_count++;
|
trie->values_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,7 +399,7 @@ static int trie_store(struct trie *trie, const char *filename) {
|
|||||||
.header_size = htole64(sizeof(struct trie_header_f)),
|
.header_size = htole64(sizeof(struct trie_header_f)),
|
||||||
.node_size = htole64(sizeof(struct trie_node_f)),
|
.node_size = htole64(sizeof(struct trie_node_f)),
|
||||||
.child_entry_size = htole64(sizeof(struct trie_child_entry_f)),
|
.child_entry_size = htole64(sizeof(struct trie_child_entry_f)),
|
||||||
.value_entry_size = htole64(sizeof(struct trie_value_entry_f)),
|
.value_entry_size = htole64(sizeof(struct trie_value_entry2_f)),
|
||||||
};
|
};
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -431,14 +455,15 @@ static int trie_store(struct trie *trie, const char *filename) {
|
|||||||
log_debug("child pointers: %8"PRIu64" bytes (%8"PRIu64")",
|
log_debug("child pointers: %8"PRIu64" bytes (%8"PRIu64")",
|
||||||
t.children_count * sizeof(struct trie_child_entry_f), t.children_count);
|
t.children_count * sizeof(struct trie_child_entry_f), t.children_count);
|
||||||
log_debug("value pointers: %8"PRIu64" bytes (%8"PRIu64")",
|
log_debug("value pointers: %8"PRIu64" bytes (%8"PRIu64")",
|
||||||
t.values_count * sizeof(struct trie_value_entry_f), t.values_count);
|
t.values_count * sizeof(struct trie_value_entry2_f), t.values_count);
|
||||||
log_debug("string store: %8zu bytes", trie->strings->len);
|
log_debug("string store: %8zu bytes", trie->strings->len);
|
||||||
log_debug("strings start: %8"PRIu64, t.strings_off);
|
log_debug("strings start: %8"PRIu64, t.strings_off);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int insert_data(struct trie *trie, char **match_list, char *line, const char *filename) {
|
static int insert_data(struct trie *trie, char **match_list, char *line,
|
||||||
|
const char *filename, size_t line_number) {
|
||||||
char *value, **entry;
|
char *value, **entry;
|
||||||
|
|
||||||
value = strchr(line, '=');
|
value = strchr(line, '=');
|
||||||
@ -460,7 +485,7 @@ static int insert_data(struct trie *trie, char **match_list, char *line, const c
|
|||||||
}
|
}
|
||||||
|
|
||||||
STRV_FOREACH(entry, match_list)
|
STRV_FOREACH(entry, match_list)
|
||||||
trie_insert(trie, trie->root, *entry, line, value);
|
trie_insert(trie, trie->root, *entry, line, value, filename, line_number);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -474,6 +499,7 @@ static int import_file(struct trie *trie, const char *filename) {
|
|||||||
_cleanup_fclose_ FILE *f = NULL;
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
char line[LINE_MAX];
|
char line[LINE_MAX];
|
||||||
_cleanup_strv_free_ char **match_list = NULL;
|
_cleanup_strv_free_ char **match_list = NULL;
|
||||||
|
size_t line_number = 0;
|
||||||
char *match = NULL;
|
char *match = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -485,6 +511,8 @@ static int import_file(struct trie *trie, const char *filename) {
|
|||||||
size_t len;
|
size_t len;
|
||||||
char *pos;
|
char *pos;
|
||||||
|
|
||||||
|
++line_number;
|
||||||
|
|
||||||
/* comment line */
|
/* comment line */
|
||||||
if (line[0] == '#')
|
if (line[0] == '#')
|
||||||
continue;
|
continue;
|
||||||
@ -546,7 +574,7 @@ static int import_file(struct trie *trie, const char *filename) {
|
|||||||
|
|
||||||
/* first data */
|
/* first data */
|
||||||
state = HW_DATA;
|
state = HW_DATA;
|
||||||
insert_data(trie, match_list, line, filename);
|
insert_data(trie, match_list, line, filename, line_number);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HW_DATA:
|
case HW_DATA:
|
||||||
@ -564,7 +592,7 @@ static int import_file(struct trie *trie, const char *filename) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
insert_data(trie, match_list, line, filename);
|
insert_data(trie, match_list, line, filename, line_number);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -70,3 +70,11 @@ struct trie_value_entry_f {
|
|||||||
le64_t key_off;
|
le64_t key_off;
|
||||||
le64_t value_off;
|
le64_t value_off;
|
||||||
} _packed_;
|
} _packed_;
|
||||||
|
|
||||||
|
/* v2 extends v1 with filename and line-number */
|
||||||
|
struct trie_value_entry2_f {
|
||||||
|
le64_t key_off;
|
||||||
|
le64_t value_off;
|
||||||
|
le64_t filename_off;
|
||||||
|
le64_t line_number;
|
||||||
|
} _packed_;
|
||||||
|
Reference in New Issue
Block a user