hwdb: improve and test syntax error messages

Since syntax error are non-fatal, downgrade them to warnings.
Use log_syntax to have uniform formatting including the line number.
State machine states like DATA and MATCH are internal, user-facing
messages should use the names from hwdb(7): match, property, record.
Also change "key/value" to "key-value", since there's no alternative
here, both parts must be present.

[/tmp/tmp.KFwEhm74n4/etc/udev/hwdb.d/10-bad.hwdb:2] Property expected, ignoring record with no properties
[/tmp/tmp.KFwEhm74n4/etc/udev/hwdb.d/10-bad.hwdb:5] Property expected, ignoring record with no properties
[/tmp/tmp.KFwEhm74n4/etc/udev/hwdb.d/10-bad.hwdb:9] Property expected, ignoring record with no properties
[/tmp/tmp.KFwEhm74n4/etc/udev/hwdb.d/10-bad.hwdb:11] Key/value pair expected but got " NO_VALUE", ignoring
[/tmp/tmp.KFwEhm74n4/etc/udev/hwdb.d/10-bad.hwdb:18] Property or empty line expected, got "BAD:7:match at wrong place", ignoring record
[/tmp/tmp.KFwEhm74n4/etc/udev/hwdb.d/10-bad.hwdb:22] Property or empty line expected, got "BAD:8:match at wrong place", ignoring record
[/tmp/tmp.KFwEhm74n4/etc/udev/hwdb.d/10-bad.hwdb:23] Match expected but got indented property " Z=z", ignoring line

squash! hwdb: improve syntax error messages
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2016-12-01 10:55:32 -05:00
parent 8ce2069263
commit 49141e0cd1
4 changed files with 67 additions and 15 deletions

View File

@ -1700,7 +1700,8 @@ EXTRA_DIST += \
test/bus-policy/signals.conf \
test/bus-policy/check-own-rules.conf \
test/bus-policy/many-rules.conf \
test/bus-policy/test.conf
test/bus-policy/test.conf \
test/hwdb/10-bad.hwdb
EXTRA_DIST += \

View File

@ -39,7 +39,7 @@
#include "verbs.h"
/*
* Generic udev properties, key/value database based on modalias strings.
* Generic udev properties, key-value database based on modalias strings.
* Uses a Patricia/radix trie to index all matches for efficient lookup.
*/
@ -70,7 +70,7 @@ struct trie_node {
struct trie_child_entry *children;
uint8_t children_count;
/* sorted array of key/value pairs */
/* sorted array of key-value pairs */
struct trie_value_entry *values;
size_t values_count;
};
@ -81,7 +81,7 @@ struct trie_child_entry {
struct trie_node *child;
};
/* value array item with key/value pairs */
/* value array item with key-value pairs */
struct trie_value_entry {
size_t key_off;
size_t value_off;
@ -457,10 +457,9 @@ static int insert_data(struct trie *trie, char **match_list, char *line,
char *value, **entry;
value = strchr(line, '=');
if (!value) {
log_error("Error, key/value pair expected but got '%s' in '%s':", line, filename);
return -EINVAL;
}
if (!value)
return log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL,
"Key-value pair expected but got \"%s\", ignoring", line);
value[0] = '\0';
value++;
@ -469,10 +468,9 @@ static int insert_data(struct trie *trie, char **match_list, char *line,
while (isblank(line[0]) && isblank(line[1]))
line++;
if (line[0] == '\0' || value[0] == '\0') {
log_error("Error, empty key or value '%s' in '%s':", line, filename);
return -EINVAL;
}
if (line[0] == '\0' || value[0] == '\0')
return log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL,
"Empty %s in \"%s\", ignoring", line[0] == '\0' ? "key" : "value", line);
STRV_FOREACH(entry, match_list)
trie_insert(trie, trie->root, *entry, line, value, filename, file_priority, line_number);
@ -524,7 +522,8 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
break;
if (line[0] == ' ') {
log_error("Error, MATCH expected but got '%s' in '%s':", line, filename);
log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL,
"Match expected but got indented property \"%s\", ignoring line", line);
break;
}
@ -543,7 +542,9 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
case HW_MATCH:
if (len == 0) {
log_error("Error, DATA expected but got empty line in '%s':", filename);
log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL,
"Property expected, ignoring record with no properties");
state = HW_NONE;
strv_clear(match_list);
break;
@ -576,7 +577,8 @@ static int import_file(struct trie *trie, const char *filename, uint16_t file_pr
}
if (line[0] != ' ') {
log_error("Error, DATA expected but got '%s' in '%s':", line, filename);
log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL,
"Property or empty line expected, got \"%s\", ignoring record", line);
state = HW_NONE;
strv_clear(match_list);
break;

View File

@ -33,6 +33,7 @@ trap "rm -rf '$D'" EXIT INT QUIT PIPE
mkdir -p "$D/etc/udev"
ln -s "$ROOTDIR/hwdb" "$D/etc/udev/hwdb.d"
# Test "good" properties" — no warnings or errors allowed
err=$("$SYSTEMD_HWDB" update --root "$D" 2>&1 >/dev/null) && rc= || rc=$?
if [ -n "$err" ]; then
echo "$err"
@ -47,3 +48,25 @@ if [ ! -e "$D/etc/udev/hwdb.bin" ]; then
echo "$D/etc/udev/hwdb.bin was not generated"
exit 1
fi
# Test "bad" properties" — warnings required, errors not allowed
rm -f "$D/etc/udev/hwdb.bin" "$D/etc/udev/hwdb.d"
ln -s "$ROOTDIR/test/hwdb" "$D/etc/udev/hwdb.d"
err=$("$SYSTEMD_HWDB" update --root "$D" 2>&1 >/dev/null) && rc= || rc=$?
if [ -n "$rc" ]; then
echo "$SYSTEMD_HWDB returned $rc"
exit $rc
fi
if [ -n "$err" ]; then
echo "Expected warnings"
echo "$err"
else
echo "$SYSTEMD_HWDB unexpectedly printed no warnings"
exit 1
fi
if [ ! -e "$D/etc/udev/hwdb.bin" ]; then
echo "$D/etc/udev/hwdb.bin was not generated"
exit 1
fi

26
test/hwdb/10-bad.hwdb Normal file
View File

@ -0,0 +1,26 @@
BAD:1:no properties
BAD:2:no properties
BAD:2:no properties
BAD:3:no properties
BAD:3:no properties
BAD:3:no properties
GOOD:5:bad property
NO_VALUE
GOOD:6:bad property
=NO_NAME
NO_VALUE=
BAD:7:match at wrong place
X=Y
BAD:7:match at wrong place
BAD:8:match at wrong place
X=Y
BAD:8:match at wrong place
Z=z
BAD:8:match at EOF