X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;ds=sidebyside;f=udev%2Fudev-rules.c;h=c036482759787380010f8f52c3a9037d1186e7f2;hb=fb045134706a50f12361e37f936a87d62e757db3;hp=fac418e526a625099d8b96adec4711b50fd2b3fb;hpb=e3196993f1f7fdd9fb7fbf4eeb397080554ae920;p=elogind.git diff --git a/udev/udev-rules.c b/udev/udev-rules.c index fac418e52..c03648275 100644 --- a/udev/udev-rules.c +++ b/udev/udev-rules.c @@ -103,7 +103,6 @@ enum string_glob_type { GL_SPLIT, /* multi-value A|B */ GL_SPLIT_GLOB, /* multi-value with glob A*|B* */ GL_SOMETHING, /* commonly used "?*" */ - GL_FORMAT, }; /* tokens of a rule are sorted/handled in this order */ @@ -230,7 +229,6 @@ static const char *string_glob_str(enum string_glob_type type) [GL_SPLIT] = "split", [GL_SPLIT_GLOB] = "split-glob", [GL_SOMETHING] = "split-glob", - [GL_FORMAT] = "format", }; return string_glob_strs[type]; @@ -706,8 +704,7 @@ static int import_property_from_string(struct udev_device *dev, char *line) info(udev, "updating devpath from '%s' to '%s'\n", udev_device_get_devpath(dev), val); - util_strlcpy(syspath, udev_get_sys_path(udev), sizeof(syspath)); - util_strlcat(syspath, val, sizeof(syspath)); + util_strscpyl(syspath, sizeof(syspath), udev_get_sys_path(udev), val, NULL); udev_device_set_syspath(dev, syspath); } else { struct udev_list_entry *entry; @@ -799,12 +796,9 @@ static int wait_for_file(struct udev_device *dev, const char *file, int timeout) /* 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)); - - util_strlcpy(filepath, devicepath, sizeof(filepath)); - util_strlcat(filepath, "/", sizeof(filepath)); - util_strlcat(filepath, file, sizeof(filepath)); + util_strscpyl(devicepath, sizeof(devicepath), + udev_get_sys_path(udev), udev_device_get_devpath(dev), NULL); + util_strscpyl(filepath, sizeof(filepath), devicepath, "/", file, NULL); file = filepath; } @@ -829,17 +823,21 @@ static int wait_for_file(struct udev_device *dev, const char *file, int timeout) static int attr_subst_subdir(char *attr, size_t len) { - char *pos; int found = 0; - pos = strstr(attr, "/*/"); - if (pos != NULL) { - char str[UTIL_PATH_SIZE]; + if (strstr(attr, "/*/")) { + char *pos; + char dirname[UTIL_PATH_SIZE]; + const char *tail; DIR *dir; - pos[1] = '\0'; - util_strlcpy(str, &pos[2], sizeof(str)); - dir = opendir(attr); + util_strscpy(dirname, sizeof(dirname), attr); + pos = strstr(dirname, "/*/"); + if (pos == NULL) + return -1; + pos[0] = '\0'; + tail = &pos[2]; + dir = opendir(dirname); if (dir != NULL) { struct dirent *dent; @@ -848,18 +846,14 @@ static int attr_subst_subdir(char *attr, size_t len) if (dent->d_name[0] == '.') continue; - util_strlcat(attr, dent->d_name, len); - util_strlcat(attr, str, len); + util_strscpyl(attr, len, dirname, "/", dent->d_name, tail, NULL); if (stat(attr, &stats) == 0) { found = 1; break; } - pos[1] = '\0'; } closedir(dir); } - if (!found) - util_strlcat(attr, str, len); } return found; @@ -1060,29 +1054,23 @@ static int rule_add_key(struct rule_tmp *rule_tmp, enum token_type type, } glob = GL_PLAIN; - if (value != NULL) { - if (type < TK_M_MAX) { - /* check if we need to split or call fnmatch() while matching rules */ - 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) { - glob = GL_SPLIT_GLOB; - } else if (has_split) { - glob = GL_SPLIT; - } 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) - glob = GL_FORMAT; + if (value != NULL && type < TK_M_MAX) { + /* check if we need to split or call fnmatch() while matching rules */ + 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) { + glob = GL_SPLIT_GLOB; + } else if (has_split) { + glob = GL_SPLIT; + } else if (has_glob) { + if (strcmp(value, "?*") == 0) + glob = GL_SOMETHING; + else + glob = GL_GLOB; } } @@ -1319,22 +1307,16 @@ static int add_rule(struct udev_rules *rules, char *line, char *pos; struct stat statbuf; - util_strlcpy(file, value, sizeof(file)); + /* allow programs in /lib/udev called without the path */ + if (value[0] != '/') + util_strscpyl(file, sizeof(file), UDEV_PREFIX "/lib/udev/", value, NULL); + else + util_strscpy(file, sizeof(file), value); pos = strchr(file, ' '); if (pos) pos[0] = '\0'; - - /* allow programs in /lib/udev called without the path */ - if (strchr(file, '/') == NULL) { - util_strlcpy(file, UDEV_PREFIX "/lib/udev/", sizeof(file)); - util_strlcat(file, value, sizeof(file)); - pos = strchr(file, ' '); - if (pos) - pos[0] = '\0'; - } - dbg(rules->udev, "IMPORT auto mode for '%s'\n", file); - if (!lstat(file, &statbuf) && (statbuf.st_mode & S_IXUSR)) { + if (stat(file, &statbuf) == 0 && (statbuf.st_mode & S_IXUSR)) { dbg(rules->udev, "IMPORT will be executed (autotype)\n"); rule_add_key(&rule_tmp, TK_M_IMPORT_PROG, op, value, NULL); } else { @@ -1431,7 +1413,7 @@ static int add_rule(struct udev_rules *rules, char *line, } else if ((rules->resolve_names > 0) && strchr("$%", value[0]) == NULL) { uid = add_uid(rules, value); rule_add_key(&rule_tmp, TK_A_OWNER_ID, op, NULL, &uid); - } else if (rules->resolve_names == 0) { + } else if (rules->resolve_names >= 0) { rule_add_key(&rule_tmp, TK_A_OWNER, op, value, NULL); } rule_tmp.rule.rule.flags = 1; @@ -1448,7 +1430,7 @@ static int add_rule(struct udev_rules *rules, char *line, } else if ((rules->resolve_names > 0) && strchr("$%", value[0]) == NULL) { gid = add_gid(rules, value); rule_add_key(&rule_tmp, TK_A_GROUP_ID, op, NULL, &gid); - } else if (rules->resolve_names == 0) { + } else if (rules->resolve_names >= 0) { rule_add_key(&rule_tmp, TK_A_GROUP, op, value, NULL); } rule_tmp.rule.rule.flags = 1; @@ -1610,6 +1592,7 @@ static int parse_file(struct udev_rules *rules, const char *filename, unsigned s if (strcmp(label, &rules->buf[rules->tokens[j].rule.label_off]) != 0) continue; rules->tokens[i].key.rule_goto = j; + break; } if (rules->tokens[i].key.rule_goto == 0) err(rules->udev, "GOTO '%s' has no matching label in: '%s'\n", label, filename); @@ -1650,10 +1633,8 @@ static int add_matching_files(struct udev *udev, struct udev_list_node *file_lis if (strcmp(ext, suffix) != 0) continue; } - dbg(udev, "put file '%s/%s' into list\n", dirname, dent->d_name); - - snprintf(filename, sizeof(filename), "%s/%s", dirname, dent->d_name); - filename[sizeof(filename)-1] = '\0'; + util_strscpyl(filename, sizeof(filename), dirname, "/", dent->d_name, NULL); + dbg(udev, "put file '%s' into list\n", filename); udev_list_entry_add(udev, file_list, filename, NULL, 1, 1); } @@ -1713,8 +1694,7 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) add_matching_files(udev, &file_list, SYSCONFDIR "/udev/rules.d", ".rules"); /* read dynamic/temporary rules */ - util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - util_strlcat(filename, "/.udev/rules.d", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/rules.d", NULL); if (stat(filename, &statbuf) != 0) { util_create_path(udev, filename); udev_selinux_setfscreatecon(udev, filename, S_IFDIR|0755); @@ -1894,7 +1874,7 @@ static int match_key(struct udev_rules *rules, struct token *token, const char * { char value[UTIL_PATH_SIZE]; - util_strlcpy(value, &rules->buf[token->key.value_off], sizeof(value)); + util_strscpy(value, sizeof(value), &rules->buf[token->key.value_off]); key_value = value; while (key_value != NULL) { pos = strchr(key_value, '|'); @@ -1913,7 +1893,6 @@ static int match_key(struct udev_rules *rules, struct token *token, const char * case GL_SOMETHING: match = (val[0] != '\0'); break; - case GL_FORMAT: case GL_UNSET: return -1; } @@ -1941,7 +1920,7 @@ static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct if (key_name[0] == '[') { char attr[UTIL_PATH_SIZE]; - util_strlcpy(attr, key_name, sizeof(attr)); + util_strscpy(attr, sizeof(attr), key_name); util_resolve_subsys_kernel(event->udev, attr, value, sizeof(value), 1); } if (value[0] == '\0') { @@ -1950,7 +1929,7 @@ static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct val = udev_device_get_sysattr_value(dev, key_name); if (val == NULL) return -1; - util_strlcpy(value, val, sizeof(value)); + util_strscpy(value, sizeof(value), val); } /* strip trailing whitespace of value, if not asked to match for it */ @@ -2061,8 +2040,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event char filename[UTIL_PATH_SIZE]; int found; - util_strlcpy(filename, &rules->buf[cur->key.value_off], sizeof(filename)); - udev_event_apply_format(event, filename, sizeof(filename)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], filename, sizeof(filename)); found = (wait_for_file(event->dev, filename, 10) == 0); if (!found && (cur->key.op != OP_NOMATCH)) goto nomatch; @@ -2134,18 +2112,16 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event struct stat statbuf; int match; - util_strlcpy(filename, &rules->buf[cur->key.value_off], sizeof(filename)); - udev_event_apply_format(event, filename, sizeof(filename)); - if (util_resolve_subsys_kernel(event->udev, NULL, filename, sizeof(filename), 0) != 0) + udev_event_apply_format(event, &rules->buf[cur->key.value_off], filename, sizeof(filename)); + if (util_resolve_subsys_kernel(event->udev, filename, filename, sizeof(filename), 0) != 0) { if (filename[0] != '/') { char tmp[UTIL_PATH_SIZE]; - util_strlcpy(tmp, udev_device_get_syspath(event->dev), sizeof(tmp)); - util_strlcat(tmp, "/", sizeof(tmp)); - util_strlcat(tmp, filename, sizeof(tmp)); - util_strlcpy(filename, tmp, sizeof(filename)); + util_strscpy(tmp, sizeof(tmp), filename); + util_strscpyl(filename, sizeof(filename), + udev_device_get_syspath(event->dev), "/", tmp, NULL); } - + } attr_subst_subdir(filename, sizeof(filename)); match = (stat(filename, &statbuf) == 0); @@ -2169,8 +2145,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event free(event->program_result); event->program_result = NULL; - util_strlcpy(program, &rules->buf[cur->key.value_off], sizeof(program)); - udev_event_apply_format(event, program, sizeof(program)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], program, sizeof(program)); envp = udev_device_get_properties_envp(event->dev); info(event->udev, "PROGRAM '%s' %s:%u\n", program, @@ -2199,8 +2174,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event { char import[UTIL_PATH_SIZE]; - util_strlcpy(import, &rules->buf[cur->key.value_off], sizeof(import)); - udev_event_apply_format(event, import, sizeof(import)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], import, sizeof(import)); if (import_file_into_properties(event->dev, import) != 0) if (cur->key.op != OP_NOMATCH) goto nomatch; @@ -2210,8 +2184,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event { char import[UTIL_PATH_SIZE]; - util_strlcpy(import, &rules->buf[cur->key.value_off], sizeof(import)); - udev_event_apply_format(event, import, sizeof(import)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], import, sizeof(import)); info(event->udev, "IMPORT '%s' %s:%u\n", import, &rules->buf[rule->rule.filename_off], @@ -2225,8 +2198,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event { char import[UTIL_PATH_SIZE]; - util_strlcpy(import, &rules->buf[cur->key.value_off], sizeof(import)); - udev_event_apply_format(event, import, sizeof(import)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], import, sizeof(import)); if (import_parent_into_properties(event->dev, import) != 0) if (cur->key.op != OP_NOMATCH) goto nomatch; @@ -2268,8 +2240,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event break; if (cur->key.op == OP_ASSIGN_FINAL) event->owner_final = 1; - util_strlcpy(owner, &rules->buf[cur->key.value_off], sizeof(owner)); - udev_event_apply_format(event, owner, sizeof(owner)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], owner, sizeof(owner)); event->uid = util_lookup_user(event->udev, owner); info(event->udev, "OWNER %u %s:%u\n", event->uid, @@ -2285,8 +2256,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event break; if (cur->key.op == OP_ASSIGN_FINAL) event->group_final = 1; - util_strlcpy(group, &rules->buf[cur->key.value_off], sizeof(group)); - udev_event_apply_format(event, group, sizeof(group)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], group, sizeof(group)); event->gid = util_lookup_group(event->udev, group); info(event->udev, "GROUP %u %s:%u\n", event->gid, @@ -2303,8 +2273,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event break; if (cur->key.op == OP_ASSIGN_FINAL) event->mode_final = 1; - util_strlcpy(mode, &rules->buf[cur->key.value_off], sizeof(mode)); - udev_event_apply_format(event, mode, sizeof(mode)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], mode, sizeof(mode)); event->mode = strtol(mode, &endptr, 8); if (endptr[0] != '\0') { err(event->udev, "invalide mode '%s' set default mode 0660\n", mode); @@ -2358,8 +2327,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event char temp_value[UTIL_NAME_SIZE]; struct udev_list_entry *entry; - util_strlcpy(temp_value, value, sizeof(temp_value)); - udev_event_apply_format(event, temp_value, sizeof(temp_value)); + udev_event_apply_format(event, value, temp_value, sizeof(temp_value)); entry = udev_device_add_property(event->dev, name, temp_value); /* store in db */ udev_list_entry_set_flag(entry, 1); @@ -2378,8 +2346,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event break; if (cur->key.op == OP_ASSIGN_FINAL) event->name_final = 1; - util_strlcpy(name_str, name, sizeof(name_str)); - udev_event_apply_format(event, name_str, sizeof(name_str)); + udev_event_apply_format(event, name, name_str, sizeof(name_str)); if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) { count = udev_util_replace_chars(name_str, "/"); if (count > 0) @@ -2410,8 +2377,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event udev_device_cleanup_devlinks_list(event->dev); /* allow multiple symlinks separated by spaces */ - util_strlcpy(temp, &rules->buf[cur->key.value_off], sizeof(temp)); - udev_event_apply_format(event, temp, sizeof(temp)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], temp, sizeof(temp)); if (esc == ESCAPE_UNSET) count = udev_util_replace_chars(temp, "/ "); else if (esc == ESCAPE_REPLACE) @@ -2429,9 +2395,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event pos, &rules->buf[rule->rule.filename_off], rule->rule.filename_line); - util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, pos, sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", pos, NULL); udev_device_add_devlink(event->dev, filename); while (isspace(next[1])) next++; @@ -2443,9 +2407,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event pos, &rules->buf[rule->rule.filename_off], rule->rule.filename_line); - util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, pos, sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", pos, NULL); udev_device_add_devlink(event->dev, filename); } } @@ -2463,17 +2425,11 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event char value[UTIL_NAME_SIZE]; FILE *f; - util_strlcpy(attr, key_name, sizeof(attr)); - if (util_resolve_subsys_kernel(event->udev, key_name, attr, sizeof(attr), 0) != 0) { - util_strlcpy(attr, udev_device_get_syspath(event->dev), sizeof(attr)); - util_strlcat(attr, "/", sizeof(attr)); - util_strlcat(attr, key_name, sizeof(attr)); - } - + if (util_resolve_subsys_kernel(event->udev, key_name, attr, sizeof(attr), 0) != 0) + util_strscpyl(attr, sizeof(attr), udev_device_get_syspath(event->dev), "/", key_name, NULL); attr_subst_subdir(attr, sizeof(attr)); - util_strlcpy(value, &rules->buf[cur->key.value_off], sizeof(value)); - udev_event_apply_format(event, value, sizeof(value)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], value, sizeof(value)); info(event->udev, "ATTR '%s' writing '%s' %s:%u\n", attr, value, &rules->buf[rule->rule.filename_off], rule->rule.filename_line); @@ -2504,6 +2460,8 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event break; } case TK_A_GOTO: + if (cur->key.rule_goto == 0) + break; cur = &rules->tokens[cur->key.rule_goto]; continue; case TK_A_LAST_RULE: