summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2014-10-13 16:52:44 -0400
committerEdward Thomson <ethomson@edwardthomson.com>2014-10-13 16:52:44 -0400
commitc6e26210520663b4de07102b8b3035dd7675ef08 (patch)
tree0a16e49570dcc200880e71a12dbc33cf74dc2b66
parentc0c8570c5104a3047564fd5a1cfe1cacb0ed935d (diff)
parent969b6a4710451b3e905757093dce4977cd596635 (diff)
downloadlibgit2-c6e26210520663b4de07102b8b3035dd7675ef08.tar.gz
Merge pull request #2615 from ethomson/mount_points
Mount points
-rw-r--r--src/path.c42
-rw-r--r--src/win32/posix_w32.c13
2 files changed, 38 insertions, 17 deletions
diff --git a/src/path.c b/src/path.c
index 21b6e18d6..143c564e8 100644
--- a/src/path.c
+++ b/src/path.c
@@ -515,23 +515,33 @@ bool git_path_is_empty_dir(const char *path)
WIN32_FIND_DATAW findData;
HANDLE hFind = FindFirstFileW(filter_w, &findData);
+ /* FindFirstFile will fail if there are no children to the given
+ * path, which can happen if the given path is a file (and obviously
+ * has no children) or if the given path is an empty mount point.
+ * (Most directories have at least directory entries '.' and '..',
+ * but ridiculously another volume mounted in another drive letter's
+ * path space do not, and thus have nothing to enumerate.) If
+ * FindFirstFile fails, check if this is a directory-like thing
+ * (a mount point).
+ */
+ if (hFind == INVALID_HANDLE_VALUE)
+ return git_path_isdir(path);
+
/* If the find handle was created successfully, then it's a directory */
- if (hFind != INVALID_HANDLE_VALUE) {
- empty = true;
-
- do {
- /* Allow the enumeration to return . and .. and still be considered
- * empty. In the special case of drive roots (i.e. C:\) where . and
- * .. do not occur, we can still consider the path to be an empty
- * directory if there's nothing there. */
- if (!git_path_is_dot_or_dotdotW(findData.cFileName)) {
- empty = false;
- break;
- }
- } while (FindNextFileW(hFind, &findData));
-
- FindClose(hFind);
- }
+ empty = true;
+
+ do {
+ /* Allow the enumeration to return . and .. and still be considered
+ * empty. In the special case of drive roots (i.e. C:\) where . and
+ * .. do not occur, we can still consider the path to be an empty
+ * directory if there's nothing there. */
+ if (!git_path_is_dot_or_dotdotW(findData.cFileName)) {
+ empty = false;
+ break;
+ }
+ } while (FindNextFileW(hFind, &findData));
+
+ FindClose(hFind);
}
return empty;
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index 0023f95ff..7b4555719 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -131,6 +131,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(
@@ -177,7 +182,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);