X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=udev%2Fudev-rules.c;h=77029f7bec024e2ec9d90164520816b202cc59e4;hb=11ae7578505caa8df5604c6c86c82e9558439b30;hp=2746bd551e80de6d373a680069ff7e60b9c3946d;hpb=ac218d9cc8344755654f6be34f8c60863fe2fb33;p=elogind.git diff --git a/udev/udev-rules.c b/udev/udev-rules.c index 2746bd551..77029f7be 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 { @@ -543,11 +547,12 @@ static int wait_for_file(struct udev_device *dev, const char *file, int timeout) { struct udev *udev = udev_device_get_udev(dev); char filepath[UTIL_PATH_SIZE]; - char devicepath[UTIL_PATH_SIZE] = ""; + char devicepath[UTIL_PATH_SIZE]; struct stat stats; int loop = timeout * WAIT_LOOP_PER_SECOND; /* a relative path is a device attribute */ + devicepath[0] = '\0'; if (file[0] != '/') { util_strlcpy(devicepath, udev_get_sys_path(udev), sizeof(devicepath)); util_strlcat(devicepath, udev_device_get_devpath(dev), sizeof(devicepath)); @@ -813,18 +818,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 +944,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 +1711,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 +1727,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 +1762,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,42 +1770,48 @@ 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; } static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct udev_event *event, struct token *cur) { - char attr[UTIL_PATH_SIZE]; const char *key_name = &rules->buf[cur->key.attr_off]; const char *key_value = &rules->buf[cur->key.value_off]; - char value[UTIL_NAME_SIZE] = ""; + char value[UTIL_NAME_SIZE]; size_t len; - util_strlcpy(attr, key_name, sizeof(attr)); - util_resolve_subsys_kernel(event->udev, attr, value, sizeof(value), 1); + value[0] = '\0'; + if (key_name[0] == '[') { + char attr[UTIL_PATH_SIZE]; + + util_strlcpy(attr, key_name, sizeof(attr)); + util_resolve_subsys_kernel(event->udev, attr, value, sizeof(value), 1); + } if (value[0] == '\0') { const char *val; val = udev_device_get_sysattr_value(dev, key_name); - if (val != NULL) - util_strlcpy(value, val, sizeof(value)); + if (val == NULL) + return -1; + util_strlcpy(value, val, sizeof(value)); } - if (value[0]=='\0') - return -1; /* strip trailing whitespace of value, if not asked to match for it */ len = strlen(key_value); @@ -1814,6 +1834,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; @@ -1821,8 +1842,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event /* loop through token list, match, run actions or forward to next rule */ cur = &rules->tokens[0]; rule = cur; - while (cur != NULL && cur->type != TK_END) { - enum escape_type esc = ESCAPE_UNSET; + while (1) { unsigned int idx; dump_token(rules, cur); @@ -2298,11 +2318,11 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event cur = &rules->tokens[cur->key.rule_goto]; continue; case TK_A_LAST_RULE: - break; + case TK_END: + return 0; case TK_M_PARENTS_MAX: case TK_M_MAX: - case TK_END: case TK_UNSET: err(rules->udev, "wrong type %u\n", cur->type); goto nomatch; @@ -2314,9 +2334,8 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event /* fast-forward to next rule */ idx = rule->rule.next_rule; if (idx == 0) - break; + return 0; dbg(rules->udev, "forward to rule: %u\n", idx); cur = &rules->tokens[idx]; } - return 0; }