X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=udev%2Fudev-rules.c;h=1f28e4f09a6fbf5ff24cf523b235281f63ea8b2c;hb=0dd9f015d3a7be6502ba3ec5ebbe6bcc9b056755;hp=40947685d0125ffb3b2b789eddf2694a2093a0be;hpb=3f3aa9f57cdd1aacf9fba1c90bacd1840392b7e8;p=elogind.git diff --git a/udev/udev-rules.c b/udev/udev-rules.c index 40947685d..1f28e4f09 100644 --- a/udev/udev-rules.c +++ b/udev/udev-rules.c @@ -16,6 +16,7 @@ */ #include +#include #include #include #include @@ -30,6 +31,7 @@ #define PREALLOC_TOKEN 2048 #define PREALLOC_STRBUF 32 * 1024 +#define PREALLOC_TRIE 256 struct uid_gid { unsigned int name_off; @@ -39,7 +41,19 @@ struct uid_gid { }; }; -/* KEY=="", KEY!="", KEY+="", KEY="", KEY:="" */ +struct trie_child { + unsigned int next_idx; + unsigned int node_idx; + unsigned char key; +}; + +struct trie_node { + unsigned int child_idx; + unsigned int last_child_idx; + unsigned int value_off; + unsigned short value_len; +}; + struct udev_rules { struct udev *udev; int resolve_names; @@ -55,7 +69,16 @@ struct udev_rules { size_t buf_max; unsigned int buf_count; - /* during rule parsing, we cache uid/gid lookup results */ + /* during rule parsing, strings are indexed to find duplicates */ + unsigned int *trie_root; + struct trie_node *trie_nodes; + unsigned int trie_nodes_cur; + unsigned int trie_nodes_max; + struct trie_child *trie_childs; + unsigned int trie_childs_cur; + unsigned int trie_childs_max; + + /* during rule parsing, uid/gid lookup results are cached */ struct uid_gid *uids; unsigned int uids_cur; unsigned int uids_max; @@ -64,6 +87,7 @@ struct udev_rules { unsigned int gids_max; }; +/* KEY=="", KEY!="", KEY+="", KEY="", KEY:="" */ enum operation_type { OP_UNSET, @@ -184,80 +208,95 @@ struct rule_tmp { }; #ifdef DEBUG -static const char *operation_str[] = { - [OP_UNSET] = "UNSET", - [OP_MATCH] = "match", - [OP_NOMATCH] = "nomatch", - [OP_MATCH_MAX] = "MATCH_MAX", - - [OP_ADD] = "add", - [OP_ASSIGN] = "assign", - [OP_ASSIGN_FINAL] = "assign-final", -}; +static const char *operation_str(enum operation_type type) +{ + static const char *operation_strs[] = { + [OP_UNSET] = "UNSET", + [OP_MATCH] = "match", + [OP_NOMATCH] = "nomatch", + [OP_MATCH_MAX] = "MATCH_MAX", + + [OP_ADD] = "add", + [OP_ASSIGN] = "assign", + [OP_ASSIGN_FINAL] = "assign-final", +} ; + + return operation_strs[type]; +} -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", -}; +static const char *string_glob_str(enum string_glob_type type) +{ + static const char *string_glob_strs[] = { + [GL_UNSET] = "UNSET", + [GL_PLAIN] = "plain", + [GL_GLOB] = "glob", + [GL_SPLIT] = "split", + [GL_SPLIT_GLOB] = "split-glob", + [GL_SOMETHING] = "split-glob", + [GL_FORMAT] = "format", + }; -static const char *token_str[] = { - [TK_UNSET] = "UNSET", - [TK_RULE] = "RULE", - - [TK_M_ACTION] = "M ACTION", - [TK_M_DEVPATH] = "M DEVPATH", - [TK_M_KERNEL] = "M KERNEL", - [TK_M_DEVLINK] = "M DEVLINK", - [TK_M_NAME] = "M NAME", - [TK_M_ENV] = "M ENV", - [TK_M_SUBSYSTEM] = "M SUBSYSTEM", - [TK_M_DRIVER] = "M DRIVER", - [TK_M_WAITFOR] = "M WAITFOR", - [TK_M_ATTR] = "M ATTR", - - [TK_M_PARENTS_MIN] = "M PARENTS_MIN", - [TK_M_KERNELS] = "M KERNELS", - [TK_M_SUBSYSTEMS] = "M SUBSYSTEMS", - [TK_M_DRIVERS] = "M DRIVERS", - [TK_M_ATTRS] = "M ATTRS", - [TK_M_PARENTS_MAX] = "M PARENTS_MAX", - - [TK_M_TEST] = "M TEST", - [TK_M_PROGRAM] = "M PROGRAM", - [TK_M_IMPORT_FILE] = "M IMPORT_FILE", - [TK_M_IMPORT_PROG] = "M IMPORT_PROG", - [TK_M_IMPORT_PARENT] = "M MPORT_PARENT", - [TK_M_RESULT] = "M RESULT", - [TK_M_MAX] = "M MAX", - - [TK_A_IGNORE_DEVICE] = "A IGNORE_DEVICE", - [TK_A_STRING_ESCAPE_NONE] = "A STRING_ESCAPE_NONE", - [TK_A_STRING_ESCAPE_REPLACE] = "A STRING_ESCAPE_REPLACE", - [TK_A_NUM_FAKE_PART] = "A NUM_FAKE_PART", - [TK_A_DEVLINK_PRIO] = "A DEVLINK_PRIO", - [TK_A_OWNER] = "A OWNER", - [TK_A_GROUP] = "A GROUP", - [TK_A_MODE] = "A MODE", - [TK_A_OWNER_ID] = "A OWNER_ID", - [TK_A_GROUP_ID] = "A GROUP_ID", - [TK_A_MODE_ID] = "A MODE_ID", - [TK_A_ENV] = "A ENV", - [TK_A_NAME] = "A NAME", - [TK_A_DEVLINK] = "A DEVLINK", - [TK_A_EVENT_TIMEOUT] = "A EVENT_TIMEOUT", - [TK_A_IGNORE_REMOVE] = "A IGNORE_REMOVE", - [TK_A_ATTR] = "A ATTR", - [TK_A_RUN] = "A RUN", - [TK_A_GOTO] = "A GOTO", - [TK_A_LAST_RULE] = "A LAST_RULE", - - [TK_END] = "END", -}; + return string_glob_strs[type]; +} + +static const char *token_str(enum token_type type) +{ + static const char *token_strs[] = { + [TK_UNSET] = "UNSET", + [TK_RULE] = "RULE", + + [TK_M_ACTION] = "M ACTION", + [TK_M_DEVPATH] = "M DEVPATH", + [TK_M_KERNEL] = "M KERNEL", + [TK_M_DEVLINK] = "M DEVLINK", + [TK_M_NAME] = "M NAME", + [TK_M_ENV] = "M ENV", + [TK_M_SUBSYSTEM] = "M SUBSYSTEM", + [TK_M_DRIVER] = "M DRIVER", + [TK_M_WAITFOR] = "M WAITFOR", + [TK_M_ATTR] = "M ATTR", + + [TK_M_PARENTS_MIN] = "M PARENTS_MIN", + [TK_M_KERNELS] = "M KERNELS", + [TK_M_SUBSYSTEMS] = "M SUBSYSTEMS", + [TK_M_DRIVERS] = "M DRIVERS", + [TK_M_ATTRS] = "M ATTRS", + [TK_M_PARENTS_MAX] = "M PARENTS_MAX", + + [TK_M_TEST] = "M TEST", + [TK_M_PROGRAM] = "M PROGRAM", + [TK_M_IMPORT_FILE] = "M IMPORT_FILE", + [TK_M_IMPORT_PROG] = "M IMPORT_PROG", + [TK_M_IMPORT_PARENT] = "M MPORT_PARENT", + [TK_M_RESULT] = "M RESULT", + [TK_M_MAX] = "M MAX", + + [TK_A_IGNORE_DEVICE] = "A IGNORE_DEVICE", + [TK_A_STRING_ESCAPE_NONE] = "A STRING_ESCAPE_NONE", + [TK_A_STRING_ESCAPE_REPLACE] = "A STRING_ESCAPE_REPLACE", + [TK_A_NUM_FAKE_PART] = "A NUM_FAKE_PART", + [TK_A_DEVLINK_PRIO] = "A DEVLINK_PRIO", + [TK_A_OWNER] = "A OWNER", + [TK_A_GROUP] = "A GROUP", + [TK_A_MODE] = "A MODE", + [TK_A_OWNER_ID] = "A OWNER_ID", + [TK_A_GROUP_ID] = "A GROUP_ID", + [TK_A_MODE_ID] = "A MODE_ID", + [TK_A_ENV] = "A ENV", + [TK_A_NAME] = "A NAME", + [TK_A_DEVLINK] = "A DEVLINK", + [TK_A_EVENT_TIMEOUT] = "A EVENT_TIMEOUT", + [TK_A_IGNORE_REMOVE] = "A IGNORE_REMOVE", + [TK_A_ATTR] = "A ATTR", + [TK_A_RUN] = "A RUN", + [TK_A_GOTO] = "A GOTO", + [TK_A_LAST_RULE] = "A LAST_RULE", + + [TK_END] = "END", + }; + + return token_strs[type]; +} static void dump_token(struct udev_rules *rules, struct token *token) { @@ -272,13 +311,11 @@ static void dump_token(struct udev_rules *rules, struct token *token) { const char *tks_ptr = (char *)rules->tokens; const char *tk_ptr = (char *)token; - unsigned int off = tk_ptr - tks_ptr; + unsigned int idx = (tk_ptr - tks_ptr) / sizeof(struct token); - dbg(rules->udev, "* RULE %s:%u, off: %u(%u), token_count: %u(%u), label: '%s', flags: 0x%02x\n", + dbg(rules->udev, "* RULE %s:%u, token: %u, count: %u, label: '%s', flags: 0x%02x\n", &rules->buf[token->rule.filename_off], token->rule.filename_line, - off / (unsigned int) sizeof(struct token), off, - token->rule.token_count, - token->rule.token_count * (unsigned int) sizeof(struct token), + idx, token->rule.token_count, &rules->buf[token->rule.label_off], token->rule.flags); break; @@ -306,7 +343,7 @@ static void dump_token(struct udev_rules *rules, struct token *token) case TK_A_MODE: case TK_A_RUN: dbg(rules->udev, "%s %s '%s'(%s)\n", - token_str[type], operation_str[op], value, string_glob_str[glob]); + token_str(type), operation_str(op), value, string_glob_str(glob)); break; case TK_M_ATTR: case TK_M_ATTRS: @@ -314,42 +351,42 @@ static void dump_token(struct udev_rules *rules, struct token *token) case TK_A_ATTR: case TK_A_ENV: dbg(rules->udev, "%s %s '%s' '%s'(%s)\n", - token_str[type], operation_str[op], attr, value, string_glob_str[glob]); + token_str(type), operation_str(op), attr, value, string_glob_str(glob)); break; case TK_A_IGNORE_DEVICE: case TK_A_STRING_ESCAPE_NONE: case TK_A_STRING_ESCAPE_REPLACE: case TK_A_LAST_RULE: case TK_A_IGNORE_REMOVE: - dbg(rules->udev, "%s\n", token_str[type]); + dbg(rules->udev, "%s\n", token_str(type)); break; case TK_M_TEST: dbg(rules->udev, "%s %s '%s'(%s) %#o\n", - token_str[type], operation_str[op], value, string_glob_str[glob], token->key.mode); + token_str(type), operation_str(op), value, string_glob_str(glob), token->key.mode); break; case TK_A_NUM_FAKE_PART: - dbg(rules->udev, "%s %u\n", token_str[type], token->key.num_fake_part); + dbg(rules->udev, "%s %u\n", token_str(type), token->key.num_fake_part); break; case TK_A_DEVLINK_PRIO: - dbg(rules->udev, "%s %s %u\n", token_str[type], operation_str[op], token->key.devlink_prio); + dbg(rules->udev, "%s %s %u\n", token_str(type), operation_str(op), token->key.devlink_prio); break; case TK_A_OWNER_ID: - dbg(rules->udev, "%s %s %u\n", token_str[type], operation_str[op], token->key.uid); + dbg(rules->udev, "%s %s %u\n", token_str(type), operation_str(op), token->key.uid); break; case TK_A_GROUP_ID: - dbg(rules->udev, "%s %s %u\n", token_str[type], operation_str[op], token->key.gid); + dbg(rules->udev, "%s %s %u\n", token_str(type), operation_str(op), token->key.gid); break; case TK_A_MODE_ID: - dbg(rules->udev, "%s %s %#o\n", token_str[type], operation_str[op], token->key.mode); + dbg(rules->udev, "%s %s %#o\n", token_str(type), operation_str(op), token->key.mode); break; case TK_A_EVENT_TIMEOUT: - dbg(rules->udev, "%s %s %u\n", token_str[type], operation_str[op], token->key.event_timeout); + dbg(rules->udev, "%s %s %u\n", token_str(type), operation_str(op), token->key.event_timeout); break; case TK_A_GOTO: - dbg(rules->udev, "%s '%s' %u\n", token_str[type], value, token->key.rule_goto); + dbg(rules->udev, "%s '%s' %u\n", token_str(type), value, token->key.rule_goto); break; case TK_END: - dbg(rules->udev, "* %s\n", token_str[type]); + dbg(rules->udev, "* %s\n", token_str(type)); break; case TK_M_PARENTS_MIN: case TK_M_PARENTS_MAX: @@ -373,31 +410,25 @@ static void dump_rules(struct udev_rules *rules) dump_token(rules, &rules->tokens[i]); } #else -static const char **operation_str; -static const char **token_str; +static inline const char *operation_str(enum operation_type type) { return NULL; } +static inline const char *token_str(enum token_type type) { return NULL; } static inline void dump_token(struct udev_rules *rules, struct token *token) {} static inline void dump_rules(struct udev_rules *rules) {} #endif /* DEBUG */ -/* we could lookup and return existing strings, or tails of strings */ -static int add_string(struct udev_rules *rules, const char *str) +static int add_new_string(struct udev_rules *rules, const char *str, size_t bytes) { - size_t len = strlen(str)+1; int off; - /* offset 0 is always '\0' */ - if (str[0] == '\0') - return 0; - /* grow buffer if needed */ - if (rules->buf_cur + len+1 >= rules->buf_max) { + if (rules->buf_cur + bytes+1 >= rules->buf_max) { char *buf; unsigned int add; /* double the buffer size */ add = rules->buf_max; - if (add < len * 8) - add = len * 8; + if (add < bytes * 8) + add = bytes * 8; buf = realloc(rules->buf, rules->buf_max + add); if (buf == NULL) @@ -407,15 +438,145 @@ static int add_string(struct udev_rules *rules, const char *str) rules->buf_max += add; } off = rules->buf_cur; - memcpy(&rules->buf[rules->buf_cur], str, len); - rules->buf_cur += len; + memcpy(&rules->buf[rules->buf_cur], str, bytes); + rules->buf_cur += bytes; rules->buf_count++; return off; } -static int add_token(struct udev_rules *rules, struct token *token) +static int add_string(struct udev_rules *rules, const char *str) { + unsigned int node_idx; + struct trie_node *new_node; + unsigned int new_node_idx; + unsigned char key; + unsigned short len; + unsigned int depth; + unsigned int off; + + len = strlen(str); + + /* offset 0 is always '\0' */ + if (len == 0) + return 0; + + /* descend root - start from last character of str */ + key = str[len - 1]; + node_idx = rules->trie_root[key]; + depth = 0; + + /* descend suffix trie */ + if (node_idx > 0) { + while (1) { + struct trie_node *node; + unsigned int child_idx; + + node = &rules->trie_nodes[node_idx]; + depth++; + off = node->value_off + node->value_len - len; + + /* match against current node */ + if (depth == len || (node->value_len >= len && memcmp(&rules->buf[off], str, len) == 0)) + return off; + + /* lookup child node */ + key = str[len - 1 - depth]; + child_idx = node->child_idx; + while (child_idx > 0) { + if (rules->trie_childs[child_idx].key == key) + break; + child_idx = rules->trie_childs[child_idx].next_idx; + } + if (child_idx == 0) + break; + node_idx = rules->trie_childs[child_idx].node_idx; + } + } + + /* string not found, add it */ + off = add_new_string(rules, str, len + 1); + + /* grow trie nodes if needed */ + if (rules->trie_nodes_cur >= rules->trie_nodes_max) { + struct trie_node *nodes; + unsigned int add; + + /* double the buffer size */ + add = rules->trie_nodes_max; + if (add < 8) + add = 8; + nodes = realloc(rules->trie_nodes, (rules->trie_nodes_max + add) * sizeof(struct trie_node)); + if (nodes == NULL) + return -1; + dbg(rules->udev, "extend trie nodes from %u to %u\n", + rules->trie_nodes_max, rules->trie_nodes_max + add); + rules->trie_nodes = nodes; + rules->trie_nodes_max += add; + } + + /* grow trie childs if needed */ + if (rules->trie_childs_cur >= rules->trie_childs_max) { + struct trie_child *childs; + unsigned int add; + + /* double the buffer size */ + add = rules->trie_childs_max; + if (add < 8) + add = 8; + + childs = realloc(rules->trie_childs, (rules->trie_childs_max + add) * sizeof(struct trie_child)); + if (childs == NULL) + return -1; + dbg(rules->udev, "extend trie childs from %u to %u\n", + rules->trie_childs_max, rules->trie_childs_max + add); + rules->trie_childs = childs; + rules->trie_childs_max += add; + } + + /* get new node */ + new_node_idx = rules->trie_nodes_cur; + rules->trie_nodes_cur++; + new_node = &rules->trie_nodes[new_node_idx]; + new_node->value_off = off; + new_node->value_len = len; + new_node->child_idx = 0; + new_node->last_child_idx = 0; + + if (depth == 0) { + /* add node to root */ + rules->trie_root[key] = new_node_idx; + } else { + /* add node to parent */ + struct trie_node *parent; + struct trie_child *new_child; + unsigned int new_child_idx; + + /* get new child link for list of childs of parent */ + new_child_idx = rules->trie_childs_cur; + rules->trie_childs_cur++; + new_child = &rules->trie_childs[new_child_idx]; + new_child->next_idx = 0; + new_child->node_idx = new_node_idx; + new_child->key = key; + + /* append child link to list of childs of parent */ + parent = &rules->trie_nodes[node_idx]; + if (parent->child_idx == 0) { + parent->child_idx = new_child_idx; + } else { + struct trie_child *last_child; + + last_child = &rules->trie_childs[parent->last_child_idx]; + last_child->next_idx = new_child_idx; + } + parent->last_child_idx = new_child_idx; + } + return off; +} + +static int add_token(struct udev_rules *rules, struct token *token) +{ /* grow buffer if needed */ if (rules->token_cur+1 >= rules->token_max) { struct token *tokens; @@ -828,7 +989,7 @@ static int get_key(struct udev *udev, char **line, char **key, enum operation_ty return -1; temp[0] = '\0'; temp++; - dbg(udev, "%s '%s'-'%s'\n", operation_str[*op], *key, *value); + dbg(udev, "%s '%s'-'%s'\n", operation_str(*op), *key, *value); /* move line to next key */ *line = temp; @@ -1528,7 +1689,6 @@ static int parse_file(struct udev_rules *rules, const char *filename, unsigned s static int add_matching_files(struct udev *udev, struct udev_list_node *file_list, const char *dirname, const char *suffix) { - struct dirent *ent; DIR *dir; char filename[UTIL_PATH_SIZE]; @@ -1540,26 +1700,28 @@ static int add_matching_files(struct udev *udev, struct udev_list_node *file_lis } while (1) { - ent = readdir(dir); - if (ent == NULL || ent->d_name[0] == '\0') + struct dirent *dent; + + dent = readdir(dir); + if (dent == NULL || dent->d_name[0] == '\0') break; - if ((ent->d_name[0] == '.') || (ent->d_name[0] == '#')) + if (dent->d_name[0] == '.') continue; /* look for file matching with specified suffix */ if (suffix != NULL) { const char *ext; - ext = strrchr(ent->d_name, '.'); + ext = strrchr(dent->d_name, '.'); if (ext == NULL) continue; if (strcmp(ext, suffix) != 0) continue; } - dbg(udev, "put file '%s/%s' into list\n", dirname, ent->d_name); + dbg(udev, "put file '%s/%s' into list\n", dirname, dent->d_name); - snprintf(filename, sizeof(filename), "%s/%s", dirname, ent->d_name); + snprintf(filename, sizeof(filename), "%s/%s", dirname, dent->d_name); filename[sizeof(filename)-1] = '\0'; udev_list_entry_add(udev, file_list, filename, NULL, 1, 1); } @@ -1589,6 +1751,7 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) if (rules->tokens == NULL) return NULL; rules->token_max = PREALLOC_TOKEN; + rules->buf = malloc(PREALLOC_STRBUF); if (rules->buf == NULL) return NULL; @@ -1599,6 +1762,22 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) dbg(udev, "prealloc %zu bytes tokens (%u * %zu bytes), %zu bytes buffer\n", rules->token_max * sizeof(struct token), rules->token_max, sizeof(struct token), rules->buf_max); + rules->trie_nodes = malloc(PREALLOC_TRIE * sizeof(struct trie_node)); + if (rules->trie_nodes == NULL) + return NULL; + rules->trie_nodes_max = PREALLOC_TRIE; + /* offset 0 is reserved for the null trie node */ + rules->trie_nodes_cur = 1; + + rules->trie_childs = malloc(PREALLOC_TRIE * sizeof(struct trie_child)); + if (rules->trie_childs == NULL) + return NULL; + rules->trie_childs_max = PREALLOC_TRIE; + /* offset 0 is reserved for the null child node */ + rules->trie_childs_cur = 1; + + rules->trie_root = calloc(UCHAR_MAX + 1, sizeof(unsigned short)); + if (udev_get_rules_path(udev) != NULL) { /* custom rules location for testing */ add_matching_files(udev, &file_list, udev_get_rules_path(udev), ".rules"); @@ -1709,8 +1888,24 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) rules->buf_max = rules->buf_cur; } } - info(udev, "shrunk to %lu bytes tokens (%u * %zu bytes), %zu bytes buffer\n", + info(udev, "rules use %zu bytes tokens (%u * %zu bytes), %zu bytes buffer\n", rules->token_max * sizeof(struct token), rules->token_max, sizeof(struct token), rules->buf_max); + info(udev, "temporary index used %zu bytes (%u * %zu bytes nodes, %u * %zu bytes child links)\n", + rules->trie_nodes_cur * sizeof(struct trie_node) + rules->trie_childs_cur * sizeof(struct trie_child), + rules->trie_nodes_cur, sizeof(struct trie_node), + rules->trie_childs_cur, sizeof(struct trie_child)); + + /* cleanup trie */ + free(rules->trie_nodes); + rules->trie_nodes = NULL; + rules->trie_nodes_cur = 0; + rules->trie_nodes_max = 0; + free(rules->trie_childs); + rules->trie_childs = NULL; + rules->trie_childs_cur = 0; + rules->trie_childs_max = 0; + free(rules->trie_root); + rules->trie_root = NULL; /* cleanup uid/gid cache */ free(rules->uids); @@ -1732,6 +1927,9 @@ void udev_rules_unref(struct udev_rules *rules) return; free(rules->tokens); free(rules->buf); + free(rules->trie_nodes); + free(rules->trie_childs); + free(rules->trie_root); free(rules->uids); free(rules->gids); free(rules); @@ -1790,7 +1988,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", token_str[token->type], 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; @@ -1807,14 +2005,14 @@ static int match_key(struct udev_rules *rules, struct token *token, const char * } if (match && (token->key.op == OP_MATCH)) { - dbg(rules->udev, "%s is true (matching value)\n", token_str[token->type]); + 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", token_str[token->type]); + dbg(rules->udev, "%s is true (non-matching value)\n", token_str(token->type)); return 0; } - dbg(rules->udev, "%s is not true\n", token_str[token->type]); + dbg(rules->udev, "%s is not true\n", token_str(token->type)); return -1; }