X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=attr.c;fp=attr.c;h=d7b8f60e7b414db9bf3f398183d1de851367164f;hb=8a755eddf5bf256613bc584f32cd44401a25897c;hp=f826ba21deb74cd4a678055811cc8515eb544035;hpb=82689d5e5d3f41da2ab1fbf9fbe7aacfd6da74c1;p=thirdparty%2Fgit.git diff --git a/attr.c b/attr.c index f826ba21de..d7b8f60e7b 100644 --- a/attr.c +++ b/attr.c @@ -278,6 +278,10 @@ struct match_attr { static const char blank[] = " \t\r\n"; +/* Flags usable in read_attr() and parse_attr_line() family of functions. */ +#define READ_ATTR_MACRO_OK (1<<0) +#define READ_ATTR_NOFOLLOW (1<<1) + /* * Parse a whitespace-delimited attribute state (i.e., "attr", * "-attr", "!attr", or "attr=value") from the string starting at src. @@ -331,7 +335,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp, } static struct match_attr *parse_attr_line(const char *line, const char *src, - int lineno, int macro_ok) + int lineno, unsigned flags) { size_t namelen, num_attr, i; const char *cp, *name, *states; @@ -359,7 +363,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src, if (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen && starts_with(name, ATTRIBUTE_MACRO_PREFIX)) { - if (!macro_ok) { + if (!(flags & READ_ATTR_MACRO_OK)) { fprintf_ln(stderr, _("%s not allowed: %s:%d"), name, src, lineno); goto fail_return; @@ -657,11 +661,11 @@ static void handle_attr_line(struct attr_stack *res, const char *line, const char *src, int lineno, - int macro_ok) + unsigned flags) { struct match_attr *a; - a = parse_attr_line(line, src, lineno, macro_ok); + a = parse_attr_line(line, src, lineno, flags); if (!a) return; ALLOC_GROW_BY(res->attrs, res->num_matches, 1, res->alloc); @@ -676,7 +680,8 @@ static struct attr_stack *read_attr_from_array(const char **list) CALLOC_ARRAY(res, 1); while ((line = *(list++)) != NULL) - handle_attr_line(res, line, "[builtin]", ++lineno, 1); + handle_attr_line(res, line, "[builtin]", ++lineno, + READ_ATTR_MACRO_OK); return res; } @@ -702,19 +707,25 @@ void git_attr_set_direction(enum git_attr_direction new_direction) direction = new_direction; } -static struct attr_stack *read_attr_from_file(const char *path, int macro_ok) +static struct attr_stack *read_attr_from_file(const char *path, unsigned flags) { struct strbuf buf = STRBUF_INIT; - FILE *fp = fopen_or_warn(path, "r"); + int fd; + FILE *fp; struct attr_stack *res; int lineno = 0; - int fd; struct stat st; - if (!fp) - return NULL; + if (flags & READ_ATTR_NOFOLLOW) + fd = open_nofollow(path, O_RDONLY); + else + fd = open(path, O_RDONLY); - fd = fileno(fp); + if (fd < 0) { + warn_on_fopen_errors(path); + return NULL; + } + fp = xfdopen(fd, "r"); if (fstat(fd, &st)) { warning_errno(_("cannot fstat gitattributes file '%s'"), path); fclose(fp); @@ -730,7 +741,7 @@ static struct attr_stack *read_attr_from_file(const char *path, int macro_ok) while (strbuf_getline(&buf, fp) != EOF) { if (!lineno && starts_with(buf.buf, utf8_bom)) strbuf_remove(&buf, 0, strlen(utf8_bom)); - handle_attr_line(res, buf.buf, path, ++lineno, macro_ok); + handle_attr_line(res, buf.buf, path, ++lineno, flags); } fclose(fp); @@ -738,9 +749,9 @@ static struct attr_stack *read_attr_from_file(const char *path, int macro_ok) return res; } -static struct attr_stack *read_attr_from_index(const struct index_state *istate, +static struct attr_stack *read_attr_from_index(struct index_state *istate, const char *path, - int macro_ok) + unsigned flags) { struct attr_stack *res; char *buf, *sp; @@ -766,27 +777,27 @@ static struct attr_stack *read_attr_from_index(const struct index_state *istate, ep = strchrnul(sp, '\n'); more = (*ep == '\n'); *ep = '\0'; - handle_attr_line(res, sp, path, ++lineno, macro_ok); + handle_attr_line(res, sp, path, ++lineno, flags); sp = ep + more; } free(buf); return res; } -static struct attr_stack *read_attr(const struct index_state *istate, - const char *path, int macro_ok) +static struct attr_stack *read_attr(struct index_state *istate, + const char *path, unsigned flags) { struct attr_stack *res = NULL; if (direction == GIT_ATTR_INDEX) { - res = read_attr_from_index(istate, path, macro_ok); + res = read_attr_from_index(istate, path, flags); } else if (!is_bare_repository()) { if (direction == GIT_ATTR_CHECKOUT) { - res = read_attr_from_index(istate, path, macro_ok); + res = read_attr_from_index(istate, path, flags); if (!res) - res = read_attr_from_file(path, macro_ok); + res = read_attr_from_file(path, flags); } else if (direction == GIT_ATTR_CHECKIN) { - res = read_attr_from_file(path, macro_ok); + res = read_attr_from_file(path, flags); if (!res) /* * There is no checked out .gitattributes file @@ -794,7 +805,7 @@ static struct attr_stack *read_attr(const struct index_state *istate, * We allow operation in a sparsely checked out * work tree, so read from it. */ - res = read_attr_from_index(istate, path, macro_ok); + res = read_attr_from_index(istate, path, flags); } } @@ -865,10 +876,11 @@ static void push_stack(struct attr_stack **attr_stack_p, } } -static void bootstrap_attr_stack(const struct index_state *istate, +static void bootstrap_attr_stack(struct index_state *istate, struct attr_stack **stack) { struct attr_stack *e; + unsigned flags = READ_ATTR_MACRO_OK; if (*stack) return; @@ -879,23 +891,23 @@ static void bootstrap_attr_stack(const struct index_state *istate, /* system-wide frame */ if (git_attr_system()) { - e = read_attr_from_file(git_etc_gitattributes(), 1); + e = read_attr_from_file(git_etc_gitattributes(), flags); push_stack(stack, e, NULL, 0); } /* home directory */ if (get_home_gitattributes()) { - e = read_attr_from_file(get_home_gitattributes(), 1); + e = read_attr_from_file(get_home_gitattributes(), flags); push_stack(stack, e, NULL, 0); } /* root directory */ - e = read_attr(istate, GITATTRIBUTES_FILE, 1); + e = read_attr(istate, GITATTRIBUTES_FILE, flags | READ_ATTR_NOFOLLOW); push_stack(stack, e, xstrdup(""), 0); /* info frame */ if (startup_info->have_repository) - e = read_attr_from_file(git_path_info_attributes(), 1); + e = read_attr_from_file(git_path_info_attributes(), flags); else e = NULL; if (!e) @@ -903,7 +915,7 @@ static void bootstrap_attr_stack(const struct index_state *istate, push_stack(stack, e, NULL, 0); } -static void prepare_attr_stack(const struct index_state *istate, +static void prepare_attr_stack(struct index_state *istate, const char *path, int dirlen, struct attr_stack **stack) { @@ -981,7 +993,7 @@ static void prepare_attr_stack(const struct index_state *istate, strbuf_add(&pathbuf, path + pathbuf.len, (len - pathbuf.len)); strbuf_addf(&pathbuf, "/%s", GITATTRIBUTES_FILE); - next = read_attr(istate, pathbuf.buf, 0); + next = read_attr(istate, pathbuf.buf, READ_ATTR_NOFOLLOW); /* reset the pathbuf to not include "/.gitattributes" */ strbuf_setlen(&pathbuf, len); @@ -1103,7 +1115,7 @@ static void determine_macros(struct all_attrs_item *all_attrs, * If check->check_nr is non-zero, only attributes in check[] are collected. * Otherwise all attributes are collected. */ -static void collect_some_attrs(const struct index_state *istate, +static void collect_some_attrs(struct index_state *istate, const char *path, struct attr_check *check) { @@ -1132,7 +1144,7 @@ static void collect_some_attrs(const struct index_state *istate, fill(path, pathlen, basename_offset, check->stack, check->all_attrs, rem); } -void git_check_attr(const struct index_state *istate, +void git_check_attr(struct index_state *istate, const char *path, struct attr_check *check) { @@ -1149,7 +1161,7 @@ void git_check_attr(const struct index_state *istate, } } -void git_all_attrs(const struct index_state *istate, +void git_all_attrs(struct index_state *istate, const char *path, struct attr_check *check) { int i;