hwdb: allow list of lookup keys per given record
This allows to specify: dmi:bvn*:bvr*:bd*:svnVENDOR:pn:Model 231*:pvr* dmi:bvn*:bvr*:bd*:svnVENDOR:pn:Series 12*:pvr* KEY_A=value KEY_B=value Instead of: dmi:bvn*:bvr*:bd*:svnVENDOR:pn:Model 231*:pvr* KEY_A=value KEY_B=value dmi:bvn*:bvr*:bd*:svnVENDOR:pn:Series 12*:pvr* KEY_A=value KEY_B=value
This commit is contained in:
parent
f09114bcc7
commit
06639c0940
|
@ -21,6 +21,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
|
@ -402,56 +403,122 @@ out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int import_file(struct trie *trie, const char *filename) {
|
static int insert_data(struct trie *trie, struct udev_list *match_list,
|
||||||
|
char *line, const char *filename) {
|
||||||
|
char *value;
|
||||||
|
struct udev_list_entry *entry;
|
||||||
|
|
||||||
|
value = strchr(line, '=');
|
||||||
|
if (!value) {
|
||||||
|
log_error("Error, key/value pair expected but got '%s' in '%s':\n", line, filename);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
value[0] = '\0';
|
||||||
|
value++;
|
||||||
|
|
||||||
|
if (line[0] == '\0' || value[0] == '\0') {
|
||||||
|
log_error("Error, empty key or value '%s' in '%s':\n", line, filename);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
udev_list_entry_foreach(entry, udev_list_get_entry(match_list))
|
||||||
|
trie_insert(trie, trie->root, udev_list_entry_get_name(entry), line, value);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int import_file(struct udev *udev, struct trie *trie, const char *filename) {
|
||||||
|
enum {
|
||||||
|
HW_MATCH,
|
||||||
|
HW_DATA,
|
||||||
|
HW_NONE,
|
||||||
|
} state = HW_NONE;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char line[LINE_MAX];
|
char line[LINE_MAX];
|
||||||
char match[LINE_MAX];
|
struct udev_list match_list;
|
||||||
|
|
||||||
|
udev_list_init(udev, &match_list, false);
|
||||||
|
|
||||||
f = fopen(filename, "re");
|
f = fopen(filename, "re");
|
||||||
if (f == NULL)
|
if (f == NULL)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
match[0] = '\0';
|
|
||||||
while (fgets(line, sizeof(line), f)) {
|
while (fgets(line, sizeof(line), f)) {
|
||||||
size_t len;
|
size_t len;
|
||||||
|
char *pos;
|
||||||
|
|
||||||
|
/* comment line */
|
||||||
if (line[0] == '#')
|
if (line[0] == '#')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* new line, new record */
|
/* strip trailing comment */
|
||||||
if (line[0] == '\n') {
|
pos = strchr(line, '#');
|
||||||
match[0] = '\0';
|
if (pos)
|
||||||
continue;
|
pos[0] = '\0';
|
||||||
}
|
|
||||||
|
|
||||||
/* remove newline */
|
/* strip trailing whitespace */
|
||||||
len = strlen(line);
|
len = strlen(line);
|
||||||
if (len < 2)
|
while (len > 0 && isspace(line[len-1]))
|
||||||
continue;
|
len--;
|
||||||
line[len-1] = '\0';
|
line[len] = '\0';
|
||||||
|
|
||||||
/* start of new record */
|
switch (state) {
|
||||||
if (match[0] == '\0') {
|
case HW_NONE:
|
||||||
strcpy(match, line);
|
if (len == 0)
|
||||||
continue;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* value line */
|
if (line[0] == ' ') {
|
||||||
if (line[0] == ' ') {
|
log_error("Error, MATCH expected but got '%s' in '%s':\n", line, filename);
|
||||||
char *value;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
value = strchr(line, '=');
|
/* start of record, first match */
|
||||||
if (!value)
|
state = HW_MATCH;
|
||||||
continue;
|
udev_list_entry_add(&match_list, line, NULL);
|
||||||
value[0] = '\0';
|
break;
|
||||||
value++;
|
|
||||||
trie_insert(trie, trie->root, match, line, value);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_error("Error parsing line '%s' in '%s\n", line, filename);
|
case HW_MATCH:
|
||||||
|
if (len == 0) {
|
||||||
|
log_error("Error, DATA expected but got empty line in '%s':\n", filename);
|
||||||
|
state = HW_NONE;
|
||||||
|
udev_list_cleanup(&match_list);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* another match */
|
||||||
|
if (line[0] != ' ') {
|
||||||
|
udev_list_entry_add(&match_list, line, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* first data */
|
||||||
|
state = HW_DATA;
|
||||||
|
insert_data(trie, &match_list, line, filename);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HW_DATA:
|
||||||
|
/* end of record */
|
||||||
|
if (len == 0) {
|
||||||
|
state = HW_NONE;
|
||||||
|
udev_list_cleanup(&match_list);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line[0] != ' ') {
|
||||||
|
log_error("Error, DATA expected but got '%s' in '%s':\n", line, filename);
|
||||||
|
state = HW_NONE;
|
||||||
|
udev_list_cleanup(&match_list);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
insert_data(trie, &match_list, line, filename);
|
||||||
|
break;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
udev_list_cleanup(&match_list);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,7 +606,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
STRV_FOREACH(f, files) {
|
STRV_FOREACH(f, files) {
|
||||||
log_debug("reading file '%s'", *f);
|
log_debug("reading file '%s'", *f);
|
||||||
import_file(trie, *f);
|
import_file(udev, trie, *f);
|
||||||
}
|
}
|
||||||
strv_free(files);
|
strv_free(files);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue