summaryrefslogtreecommitdiff
path: root/src/udev
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2019-09-11 08:50:21 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2019-09-11 09:05:39 +0900
commit067cc51f2e6eb94305556597f0254f115857ff49 (patch)
tree12f124c0bf8d8bc9ca0398882000b271719a1916 /src/udev
parent39b7b6cb4ad4a9765afb4e0b47ca5d9aa004d8c5 (diff)
downloadsystemd-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.c81
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)) {