token_type_and_data_eq(a, b);
}
+static bool nulstr_tokens_conflict(const UdevRuleToken *a, const UdevRuleToken *b) {
+ assert(a);
+ assert(b);
+
+ if (!(a->type == b->type &&
+ type_has_nulstr_value(a->type) &&
+ a->op == b->op &&
+ a->op == OP_MATCH &&
+ a->match_type == b->match_type &&
+ a->match_type == MATCH_TYPE_PLAIN &&
+ a->attr_subst_type == b->attr_subst_type &&
+ a->attr_match_remove_trailing_whitespace == b->attr_match_remove_trailing_whitespace &&
+ token_type_and_data_eq(a, b)))
+ return false;
+
+ NULSTR_FOREACH(i, a->value)
+ if (nulstr_contains(b->value, i))
+ return false;
+
+ return true;
+}
+
static void udev_check_unused_labels(UdevRuleLine *line) {
assert(line);
LIST_FOREACH(tokens, token, line->tokens)
LIST_FOREACH(tokens, i, token->tokens_next) {
- if (!tokens_eq(token, i))
+ bool new_conflicts = false, new_duplicates = false;
+
+ if (tokens_eq(token, i)) {
+ if (!duplicates && token->op == i->op)
+ new_duplicates = true;
+ if (!conflicts && conflicting_op(token->op, i->op))
+ new_conflicts = true;
+ } else if (!conflicts && nulstr_tokens_conflict(token, i))
+ new_conflicts = true;
+ else
continue;
- if (!duplicates && token->op == i->op) {
- duplicates = true;
+
+ if (new_duplicates) {
+ duplicates = new_duplicates;
log_line_warning(line, "duplicate expressions");
}
- if (!conflicts && conflicting_op(token->op, i->op)) {
- conflicts = true;
+ if (new_conflicts) {
+ conflicts = new_conflicts;
log_line_error(line, "conflicting match expressions, the line takes no effect");
}
if (conflicts && duplicates)
test_syntax_error 'KERNEL=="", KERNEL=="?*", NAME="a"' 'conflicting match expressions, the line takes no effect'
test_syntax_error 'KERNEL=="abc", KERNEL!="abc", NAME="b"' 'conflicting match expressions, the line takes no effect'
test_syntax_error 'KERNEL=="|a|b", KERNEL!="b|a|", NAME="c"' 'conflicting match expressions, the line takes no effect'
+test_syntax_error 'KERNEL=="a|b", KERNEL=="c|d|e", NAME="f"' 'conflicting match expressions, the line takes no effect'
# shellcheck disable=SC2016
test_syntax_error 'ENV{DISKSEQ}=="?*", ENV{DEVTYPE}!="partition", ENV{DISKSEQ}!="?*" ENV{ID_IGNORE_DISKSEQ}!="1", SYMLINK+="disk/by-diskseq/$env{DISKSEQ}"' \
'conflicting match expressions, the line takes no effect'
cat >"${rules}" <<'EOF'
KERNEL=="a|b", KERNEL=="a|c", NAME="d"
KERNEL=="a|b", KERNEL!="a|c", NAME="d"
+KERNEL!="a", KERNEL!="b", NAME="c"
+KERNEL=="|a", KERNEL=="|b", NAME="c"
EOF
assert_0 "${rules}"