X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev%2Fudev-rules.c;h=4df9eb35c859eba383b72a4602227f54fae6e905;hp=2746bd551e80de6d373a680069ff7e60b9c3946d;hb=3e5c759543f57e6aabb8142ef194d5e4d45722d8;hpb=ac218d9cc8344755654f6be34f8c60863fe2fb33 diff --git a/udev/udev-rules.c b/udev/udev-rules.c index 2746bd551..4df9eb35c 100644 --- a/udev/udev-rules.c +++ b/udev/udev-rules.c @@ -57,21 +57,25 @@ static const char *operation_str[] = { enum string_glob_type { GL_UNSET, - GL_PLAIN, - GL_GLOB, - GL_SPLIT, - GL_SPLIT_GLOB, + GL_PLAIN, /* no special chars */ + GL_GLOB, /* shell globs ?,*,[] */ + GL_SPLIT, /* multi-value A|B */ + GL_SPLIT_GLOB, /* multi-value with glob A*|B* */ + GL_SOMETHING, /* commonly used "?*" */ GL_FORMAT, }; +#ifdef DEBUG static const char *string_glob_str[] = { [GL_UNSET] = "UNSET", [GL_PLAIN] = "plain", [GL_GLOB] = "glob", [GL_SPLIT] = "split", [GL_SPLIT_GLOB] = "split-glob", + [GL_SOMETHING] = "split-glob", [GL_FORMAT] = "format", }; +#endif /* tokens of a rule are sorted/handled in this order */ enum token_type { @@ -813,18 +817,22 @@ static int rule_add_token(struct rule_tmp *rule_tmp, enum token_type type, if (value != NULL) { if (type < TK_M_MAX) { /* check if we need to split or call fnmatch() while matching rules */ - int has_split = 0; - int has_glob = 0; + int has_split; + int has_glob; has_split = (strchr(value, '|') != NULL); has_glob = (strchr(value, '*') != NULL || strchr(value, '?') != NULL || strchr(value, '[') != NULL || strchr(value, ']') != NULL); - if (has_split && has_glob) + if (has_split && has_glob) { glob = GL_SPLIT_GLOB; - else if (has_split) + } else if (has_split) { glob = GL_SPLIT; - else if (has_glob) - glob = GL_GLOB; + } else if (has_glob) { + if (strcmp(value, "?*") == 0) + glob = GL_SOMETHING; + else + glob = GL_GLOB; + } } else { /* check if we need to substitute format strings for matching rules */ if (strchr(value, '%') != NULL || strchr(value, '$') != NULL) @@ -935,6 +943,7 @@ static void dump_token(struct udev_rules *rules, struct token *token) dbg(rules->udev, "* %s\n", token_str[type]); break; case TK_M_PARENTS_MAX: + case TK_M_MAX: case TK_UNSET: dbg(rules->udev, "unknown type %u\n", type); break; @@ -1701,7 +1710,6 @@ void udev_rules_unref(struct udev_rules *rules) static int match_key(struct udev_rules *rules, struct token *token, const char *val) { - const char *key_name = token_str[token->type]; char *key_value = &rules->buf[token->key.value_off]; char *pos; int match = 0; @@ -1718,21 +1726,26 @@ static int match_key(struct udev_rules *rules, struct token *token, const char * break; case GL_SPLIT: { - char value[UTIL_PATH_SIZE]; + const char *split; + size_t len; - util_strlcpy(value, &rules->buf[token->key.value_off], sizeof(value)); - key_value = value; - while (key_value != NULL) { - pos = strchr(key_value, '|'); - if (pos != NULL) { - pos[0] = '\0'; - pos = &pos[1]; - } - dbg(rules->udev, "match %s '%s' <-> '%s'\n", key_name, key_value, val); - match = (strcmp(key_value, val) == 0); - if (match) + split = &rules->buf[token->key.value_off]; + len = strlen(val); + while (1) { + const char *next; + + next = strchr(split, '|'); + if (next != NULL) { + size_t matchlen = (size_t)(next - split); + + match = (matchlen == len && strncmp(split, val, matchlen) == 0); + if (match) + break; + } else { + match = (strcmp(split, val) == 0); break; - key_value = pos; + } + split = &next[1]; } break; } @@ -1748,7 +1761,7 @@ static int match_key(struct udev_rules *rules, struct token *token, const char * pos[0] = '\0'; pos = &pos[1]; } - dbg(rules->udev, "match %s '%s' <-> '%s'\n", key_name, key_value, val); + dbg(rules->udev, "match %s '%s' <-> '%s'\n", token_str[token->type], key_value, val); match = (fnmatch(key_value, val, 0) == 0); if (match) break; @@ -1756,20 +1769,23 @@ static int match_key(struct udev_rules *rules, struct token *token, const char * } break; } + case GL_SOMETHING: + match = (val[0] != '\0'); + break; case GL_FORMAT: case GL_UNSET: return -1; } if (match && (token->key.op == OP_MATCH)) { - dbg(rules->udev, "%s is true (matching value)\n", key_name); + dbg(rules->udev, "%s is true (matching value)\n", token_str[token->type]); return 0; } if (!match && (token->key.op == OP_NOMATCH)) { - dbg(rules->udev, "%s is true (non-matching value)\n", key_name); + dbg(rules->udev, "%s is true (non-matching value)\n", token_str[token->type]); return 0; } - dbg(rules->udev, "%s is not true\n", key_name); + dbg(rules->udev, "%s is not true\n", token_str[token->type]); return -1; } @@ -1814,6 +1830,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event { struct token *cur; struct token *rule; + enum escape_type esc = ESCAPE_UNSET; if (rules->tokens == NULL) return -1; @@ -1822,7 +1839,6 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event cur = &rules->tokens[0]; rule = cur; while (cur != NULL && cur->type != TK_END) { - enum escape_type esc = ESCAPE_UNSET; unsigned int idx; dump_token(rules, cur);