* Try to read the location of the git directory from the .git file, * return path to git directory if found. The return value comes from * a shared buffer. * * On failure, if return_error_code is not NULL, return_error_code * will be set to an error code and NULL will be returned. If * return_error_code is NULL the function will die instead (for most * cases). */
| 954 | * cases). |
| 955 | */ |
| 956 | const char *read_gitfile_gently(const char *path, int *return_error_code) |
| 957 | { |
| 958 | const int max_file_size = 1 << 20; /* 1MB */ |
| 959 | int error_code = 0; |
| 960 | char *buf = NULL; |
| 961 | char *dir = NULL; |
| 962 | const char *slash; |
| 963 | struct stat st; |
| 964 | int fd; |
| 965 | ssize_t len; |
| 966 | static struct strbuf realpath = STRBUF_INIT; |
| 967 | |
| 968 | if (stat(path, &st)) { |
| 969 | if (errno == ENOENT || errno == ENOTDIR) |
| 970 | error_code = READ_GITFILE_ERR_MISSING; |
| 971 | else |
| 972 | error_code = READ_GITFILE_ERR_STAT_FAILED; |
| 973 | goto cleanup_return; |
| 974 | } |
| 975 | if (S_ISDIR(st.st_mode)) { |
| 976 | error_code = READ_GITFILE_ERR_IS_A_DIR; |
| 977 | goto cleanup_return; |
| 978 | } |
| 979 | if (!S_ISREG(st.st_mode)) { |
| 980 | error_code = READ_GITFILE_ERR_NOT_A_FILE; |
| 981 | goto cleanup_return; |
| 982 | } |
| 983 | if (st.st_size > max_file_size) { |
| 984 | error_code = READ_GITFILE_ERR_TOO_LARGE; |
| 985 | goto cleanup_return; |
| 986 | } |
| 987 | fd = open(path, O_RDONLY); |
| 988 | if (fd < 0) { |
| 989 | error_code = READ_GITFILE_ERR_OPEN_FAILED; |
| 990 | goto cleanup_return; |
| 991 | } |
| 992 | buf = xmallocz(st.st_size); |
| 993 | len = read_in_full(fd, buf, st.st_size); |
| 994 | close(fd); |
| 995 | if (len != st.st_size) { |
| 996 | error_code = READ_GITFILE_ERR_READ_FAILED; |
| 997 | goto cleanup_return; |
| 998 | } |
| 999 | if (!starts_with(buf, "gitdir: ")) { |
| 1000 | error_code = READ_GITFILE_ERR_INVALID_FORMAT; |
| 1001 | goto cleanup_return; |
| 1002 | } |
| 1003 | while (buf[len - 1] == '\n' || buf[len - 1] == '\r') |
| 1004 | len--; |
| 1005 | if (len < 9) { |
| 1006 | error_code = READ_GITFILE_ERR_NO_PATH; |
| 1007 | goto cleanup_return; |
| 1008 | } |
| 1009 | buf[len] = '\0'; |
| 1010 | dir = buf + 8; |
| 1011 | |
| 1012 | if (!is_absolute_path(dir) && (slash = strrchr(path, '/'))) { |
| 1013 | size_t pathlen = slash+1 - path; |
no test coverage detected