]> git.ipfire.org Git - thirdparty/git.git/blobdiff - attr.c
Sync with Git 2.31.6
[thirdparty/git.git] / attr.c
diff --git a/attr.c b/attr.c
index f826ba21deb74cd4a678055811cc8515eb544035..d7b8f60e7b414db9bf3f398183d1de851367164f 100644 (file)
--- 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;