fileops: Fix stat() on directories for W32 The `stat` methods were having issues when called with a trailing slash in Windows platforms. We now use GetFileAttributes() where possible, which doesn't have this restriction.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
diff --git a/src/fileops.c b/src/fileops.c
index 275934c..fa45fde 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -93,31 +93,20 @@ int git_futils_creat_locked_withpath(const char *path, int mode)
int git_futils_isdir(const char *path)
{
- struct stat st;
- int len, stat_error;
-
- assert(path);
-
- len = strlen(path);
-
- /* win32: stat path for folders cannot end in a slash */
- if (path[len - 1] == '/') {
- char *path_fixed = NULL;
- path_fixed = git__strdup(path);
- path_fixed[len - 1] = 0;
- stat_error = p_stat(path_fixed, &st);
- free(path_fixed);
- } else {
- stat_error = p_stat(path, &st);
- }
-
- if (stat_error < GIT_SUCCESS)
+#ifdef GIT_WIN32
+ DWORD attr = GetFileAttributes(path);
+ if (attr == INVALID_FILE_ATTRIBUTES)
return GIT_ERROR;
- if (!S_ISDIR(st.st_mode))
+ return (attr & FILE_ATTRIBUTE_DIRECTORY) ? GIT_SUCCESS : GIT_ERROR;
+
+#else
+ struct stat st;
+ if (p_stat(path, &st) < GIT_SUCCESS)
return GIT_ERROR;
- return GIT_SUCCESS;
+ return S_ISDIR(st.st_mode) ? GIT_SUCCESS : GIT_ERROR;
+#endif
}
int git_futils_isfile(const char *path)
diff --git a/src/repository.c b/src/repository.c
index 48c8e2b..c820608 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -377,7 +377,7 @@ static int retrieve_device(dev_t *device_out, const char *path)
assert(device_out);
- if (p_stat(path, &path_info))
+ if (p_lstat(path, &path_info))
return git__throw(GIT_EOSERR, "Failed to get file informations: %s", path);
*device_out = path_info.st_dev;
diff --git a/src/win32/posix.c b/src/win32/posix.c
index 610a416..dfa4e1a 100644
--- a/src/win32/posix.c
+++ b/src/win32/posix.c
@@ -190,13 +190,22 @@ int p_hide_directory__w32(const char *path)
return error;
}
-int p_realpath(const char *orig_path, char *buffer)
+char *p_realpath(const char *orig_path, char *buffer)
{
- int ret = GetFullPathName(orig_path, GIT_PATH_MAX, buffer, NULL);
- if (!ret || ret > GIT_PATH_MAX)
- return GIT_EOSERR;
+ int ret, alloc = 0;
+
+ if (buffer == NULL) {
+ buffer = (char *)git__malloc(GIT_PATH_MAX);
+ alloc = 1;
+ }
+
+ ret = GetFullPathName(orig_path, GIT_PATH_MAX, buffer, NULL);
+ if (!ret || ret > GIT_PATH_MAX) {
+ if (alloc) free(buffer);
+ return NULL;
+ }
git_path_mkposix(buffer);
- return GIT_SUCCESS;
+ return buffer;
}
diff --git a/src/win32/posix.h b/src/win32/posix.h
index 3b5bff8..90571ae 100644
--- a/src/win32/posix.h
+++ b/src/win32/posix.h
@@ -21,6 +21,6 @@ extern int p_unlink(const char *path);
extern int p_lstat(const char *file_name, struct stat *buf);
extern int p_readlink(const char *link, char *target, size_t target_len);
extern int p_hide_directory__w32(const char *path);
-extern int p_realpath(const char *orig_path, char *buffer);
+extern char *p_realpath(const char *orig_path, char *buffer);
#endif