summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2014-10-11 14:34:24 -0400
committerEdward Thomson <ethomson@microsoft.com>2014-10-25 15:07:22 -0400
commitb2fa95a0828eba77ba3dbdc6fff021871d9185ec (patch)
tree340af83faabbdf487f90d31b1c13ab8164435558
parent01a1be3fb1323fdd65e231d5af37f4dcc9531b89 (diff)
downloadlibgit2-b2fa95a0828eba77ba3dbdc6fff021871d9185ec.tar.gz
p_lstat win32: don't canonicalize volume mounts
A reparse point that is an IO_REPARSE_TAG_MOUNT_POINT could be a junction or an actual filesystem mount point. (Who knew?) If it's the latter, its reparse point will report the actual volume information \??\Volume{GUID}\ and we should not attempt to dereference that further, instead readlink should report EINVAL since it's not a symlink / junction and its original path was canonical. Yes, really.
-rw-r--r--src/win32/posix_w32.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index 34938431a..c6169e816 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -110,6 +110,11 @@ GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
return (time_t)winTime;
}
+static bool path_is_volume(wchar_t *target, size_t target_len)
+{
+ return (target_len && wcsncmp(target, L"\\??\\Volume{", 11) == 0);
+}
+
/* On success, returns the length, in characters, of the path stored in dest.
* On failure, returns a negative value. */
static int readlink_w(
@@ -156,7 +161,13 @@ static int readlink_w(
goto on_error;
}
- if (target_len) {
+ if (path_is_volume(target, target_len)) {
+ /* This path is a reparse point that represents another volume mounted
+ * at this location, it is not a symbolic link our input was canonical.
+ */
+ errno = EINVAL;
+ error = -1;
+ } else if (target_len) {
/* The path may need to have a prefix removed. */
target_len = git_win32__canonicalize_path(target, target_len);