summaryrefslogtreecommitdiffstats
path: root/src/util/win32/posix_w32.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/win32/posix_w32.c')
-rw-r--r--src/util/win32/posix_w32.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/src/util/win32/posix_w32.c b/src/util/win32/posix_w32.c
index 3fec469..ace2320 100644
--- a/src/util/win32/posix_w32.c
+++ b/src/util/win32/posix_w32.c
@@ -787,13 +787,19 @@ int p_rmdir(const char *path)
char *p_realpath(const char *orig_path, char *buffer)
{
git_win32_path orig_path_w, buffer_w;
+ DWORD long_len;
if (git_win32_path_from_utf8(orig_path_w, orig_path) < 0)
return NULL;
- /* Note that if the path provided is a relative path, then the current directory
+ /*
+ * POSIX realpath performs two functions: first, it turns relative
+ * paths into absolute paths. For this, we need GetFullPathName.
+ *
+ * Note that if the path provided is a relative path, then the current directory
* is used to resolve the path -- which is a concurrency issue because the current
- * directory is a process-wide variable. */
+ * directory is a process-wide variable.
+ */
if (!GetFullPathNameW(orig_path_w, GIT_WIN_PATH_UTF16, buffer_w, NULL)) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
errno = ENAMETOOLONG;
@@ -803,9 +809,26 @@ char *p_realpath(const char *orig_path, char *buffer)
return NULL;
}
- /* The path must exist. */
- if (GetFileAttributesW(buffer_w) == INVALID_FILE_ATTRIBUTES) {
- errno = ENOENT;
+ /*
+ * Then, the path is canonicalized. eg, on macOS,
+ * "/TMP" -> "/private/tmp". For this, we need GetLongPathName.
+ */
+ if ((long_len = GetLongPathNameW(buffer_w, buffer_w, GIT_WIN_PATH_UTF16)) == 0) {
+ DWORD error = GetLastError();
+
+ if (error == ERROR_FILE_NOT_FOUND ||
+ error == ERROR_PATH_NOT_FOUND)
+ errno = ENOENT;
+ else if (error == ERROR_ACCESS_DENIED)
+ errno = EPERM;
+ else
+ errno = EINVAL;
+
+ return NULL;
+ }
+
+ if (long_len > GIT_WIN_PATH_UTF16) {
+ errno = ENAMETOOLONG;
return NULL;
}
@@ -821,7 +844,6 @@ char *p_realpath(const char *orig_path, char *buffer)
return NULL;
git_fs_path_mkposix(buffer);
-
return buffer;
}