diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2019-09-11 08:50:21 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2019-09-11 09:05:39 +0900 |
commit | 067cc51f2e6eb94305556597f0254f115857ff49 (patch) | |
tree | 12f124c0bf8d8bc9ca0398882000b271719a1916 /src/udev | |
parent | 39b7b6cb4ad4a9765afb4e0b47ca5d9aa004d8c5 (diff) | |
download | systemd-067cc51f2e6eb94305556597f0254f115857ff49.tar.gz systemd-067cc51f2e6eb94305556597f0254f115857ff49.tar.bz2 systemd-067cc51f2e6eb94305556597f0254f115857ff49.zip |
udev: fix multi match
Fixes #13518.
Diffstat (limited to 'src/udev')
-rw-r--r-- | src/udev/udev-rules.c | 81 |
1 files changed, 47 insertions, 34 deletions
diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 1642f10535..fdb77d0730 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -43,10 +43,12 @@ typedef enum { } UdevRuleOperatorType; typedef enum { - MATCH_TYPE_EMPTY, /* empty string */ - MATCH_TYPE_PLAIN, /* no special characters */ - MATCH_TYPE_GLOB, /* shell globs ?,*,[] */ - MATCH_TYPE_SUBSYSTEM, /* "subsystem", "bus", or "class" */ + MATCH_TYPE_EMPTY, /* empty string */ + MATCH_TYPE_PLAIN, /* no special characters */ + MATCH_TYPE_PLAIN_WITH_EMPTY, /* no special characters with empty string, e.g., "|foo" */ + MATCH_TYPE_GLOB, /* shell globs ?,*,[] */ + MATCH_TYPE_GLOB_WITH_EMPTY, /* shell globs ?,*,[] with empty string, e.g., "|foo*" */ + MATCH_TYPE_SUBSYSTEM, /* "subsystem", "bus", or "class" */ _MATCH_TYPE_MAX, _MATCH_TYPE_INVALID = -1 } UdevRuleMatchType; @@ -431,35 +433,30 @@ static int rule_line_add_token(UdevRuleLine *rule_line, UdevRuleTokenType type, if (type < TK_M_TEST || type == TK_M_RESULT) { /* Convert value string to nulstr. */ - len = strlen(value); - if (len > 1 && (value[len - 1] == '|' || strstr(value, "||"))) { - /* In this case, just replacing '|' -> '\0' does not work... */ - _cleanup_free_ char *tmp = NULL; - char *i, *j; - bool v = true; - - tmp = strdup(value); - if (!tmp) - return log_oom(); - - for (i = tmp, j = value; *i != '\0'; i++) - if (*i == '|') - v = true; - else { - if (v) { - *j++ = '\0'; - v = false; - } - *j++ = *i; - } - j[0] = j[1] = '\0'; - } else { - /* Simple conversion. */ - char *i; - - for (i = value; *i != '\0'; i++) - if (*i == '|') - *i = '\0'; + bool bar = true, empty = false; + char *a, *b; + + for (a = b = value; *a != '\0'; a++) { + if (*a != '|') { + *b++ = *a; + bar = false; + } else { + if (bar) + empty = true; + else + *b++ = '\0'; + bar = true; + } + } + *b = '\0'; + if (bar) + empty = true; + + if (empty) { + if (match_type == MATCH_TYPE_GLOB) + match_type = MATCH_TYPE_GLOB_WITH_EMPTY; + if (match_type == MATCH_TYPE_PLAIN) + match_type = MATCH_TYPE_PLAIN_WITH_EMPTY; } } } @@ -1325,7 +1322,17 @@ static bool token_match_string(UdevRuleToken *token, const char *str) { match = isempty(str); break; case MATCH_TYPE_SUBSYSTEM: - value = "subsystem\0class\0bus\0"; + NULSTR_FOREACH(i, "subsystem\0class\0bus\0") + if (streq(i, str)) { + match = true; + break; + } + break; + case MATCH_TYPE_PLAIN_WITH_EMPTY: + if (isempty(str)) { + match = true; + break; + } _fallthrough_; case MATCH_TYPE_PLAIN: NULSTR_FOREACH(i, value) @@ -1334,6 +1341,12 @@ static bool token_match_string(UdevRuleToken *token, const char *str) { break; } break; + case MATCH_TYPE_GLOB_WITH_EMPTY: + if (isempty(str)) { + match = true; + break; + } + _fallthrough_; case MATCH_TYPE_GLOB: NULSTR_FOREACH(i, value) if ((fnmatch(i, str, 0) == 0)) { |