Commit 3c68bfcd088dd5a1ef06b98ea7fd203bb048fa42

Edward Thomson 2015-02-04T18:24:31

stat: don't remove trailing '/' from root on win32 `p_stat` calls `git_win32_path_from_utf8`, which canonicalizes the path. Do not further try to modify the path, else we trim the trailing slash from a root directory and try to access `C:` instead of `C:/`.

diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index e446cca..346f537 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -448,12 +448,8 @@ int p_stat(const char* path, struct stat* buf)
 	git_win32_path path_w;
 	int len;
 
-	if ((len = git_win32_path_from_utf8(path_w, path)) < 0)
-		return -1;
-
-	git_win32__path_trim_end(path_w, len);
-
-	if (lstat_w(path_w, buf, false) < 0)
+	if ((len = git_win32_path_from_utf8(path_w, path)) < 0 ||
+		lstat_w(path_w, buf, false) < 0)
 		return -1;
 
 	/* The item is a symbolic link or mount point. No need to iterate
diff --git a/tests/core/stat.c b/tests/core/stat.c
index 2e4abfb..bd9b990 100644
--- a/tests/core/stat.c
+++ b/tests/core/stat.c
@@ -95,3 +95,20 @@ void test_core_stat__0(void)
 	cl_assert_error(ENOTDIR);
 }
 
+void test_core_stat__root(void)
+{
+	const char *sandbox = clar_sandbox_path();
+	git_buf root = GIT_BUF_INIT;
+	int root_len;
+	struct stat st;
+
+	root_len = git_path_root(sandbox);
+	cl_assert(root_len >= 0);
+
+	git_buf_set(&root, sandbox, root_len+1);
+
+	cl_must_pass(p_stat(root.ptr, &st));
+	cl_assert(S_ISDIR(st.st_mode));
+
+	git_buf_free(&root);
+}