There are at least two locations in the code that check for gitfiles. Each one is slightly different for pretty good reasons. Work towards a common API by abstracting the "is this a gitfile" question into a single function. Signed-off-by: Phil Hord <hordp@xxxxxxxxx> diff --git a/builtin/clone.c b/builtin/clone.c index 488f48e..5110399 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -120,13 +120,7 @@ static char *get_repo_path(const char *repo, int *is_bundle) return xstrdup(absolute_path(path)); } else if (S_ISREG(st.st_mode) && st.st_size > 8) { /* Is it a "gitfile"? */ - char signature[8]; - int len, fd = open(path, O_RDONLY); - if (fd < 0) - continue; - len = read_in_full(fd, signature, 8); - close(fd); - if (len != 8 || strncmp(signature, "gitdir: ", 8)) + if (!is_gitfile(path)) continue; path = read_gitfile(path); if (path) { diff --git a/cache.h b/cache.h index 7eeb8cf..61e1b0f 100644 --- a/cache.h +++ b/cache.h @@ -441,6 +441,7 @@ extern const char *get_git_work_tree(void); extern const char *read_gitfile(const char *path); extern const char *resolve_gitdir(const char *suspect); extern void set_git_work_tree(const char *tree); +extern int is_gitfile(const char *path); #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES" diff --git a/setup.c b/setup.c index 61c22e6..a3d5a41 100644 --- a/setup.c +++ b/setup.c @@ -358,7 +358,7 @@ const char *read_gitfile(const char *path) if (stat(path, &st)) return NULL; - if (!S_ISREG(st.st_mode)) + if (!is_gitfile(path)) return NULL; fd = open(path, O_RDONLY); if (fd < 0) @@ -368,9 +368,6 @@ const char *read_gitfile(const char *path) close(fd); if (len != st.st_size) die("Error reading %s", path); - buf[len] = '\0'; - if (prefixcmp(buf, "gitdir: ")) - die("Invalid gitfile format: %s", path); while (buf[len - 1] == '\n' || buf[len - 1] == '\r') len--; if (len < 9) @@ -397,6 +394,32 @@ const char *read_gitfile(const char *path) return path; } +/* + * See if the referenced file looks like a 'gitfile'. + * Does not try to determine if the referenced gitdir is actually valid. + */ +int is_gitfile(const char *path) +{ + struct stat st; + char buf[9]; + int fd, len; + if (stat(path, &st)) + return 0; + if (!S_ISREG(st.st_mode)) + return 0; + if (st.st_size < 10 || st.st_size > PATH_MAX) + return 0; + + fd = open(path, O_RDONLY); + if (fd < 0) + return 0; + len = read_in_full(fd, buf, sizeof(buf)); + close(fd); + if (len != sizeof(buf)) + return 0; + return !prefixcmp(buf, "gitdir: "); +} + static const char *setup_explicit_git_dir(const char *gitdirenv, char *cwd, int len, int *nongit_ok) -- 1.7.7.505.ga09f6 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html