mingw: do resolve symlinks in getcwd()

As pointed out in https://github.com/git-for-windows/git/issues/1676,
the `git rev-parse --is-inside-work-tree` command currently fails when
the current directory's path contains symbolic links.

The underlying reason for this bug is that `getcwd()` is supposed to
resolve symbolic links, but our `mingw_getcwd()` implementation did not.

We do have all the building blocks for that, though: the
`GetFinalPathByHandleW()` function will resolve symbolic links. However,
we only called that function if `GetLongPathNameW()` failed, for
historical reasons: the latter function was supported for a long time,
but the former API function was introduced only with Windows Vista, and
we used to support also Windows XP. With that support having been
dropped, we are free to call the symbolic link-resolving function right
away.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
Johannes Schindelin
2020-01-01 21:07:22 +01:00
parent b48c1c1e9a
commit 6d49ea61fc

View File

@@ -1211,18 +1211,16 @@ char *mingw_getcwd(char *pointer, int len)
{ {
wchar_t cwd[MAX_PATH], wpointer[MAX_PATH]; wchar_t cwd[MAX_PATH], wpointer[MAX_PATH];
DWORD ret = GetCurrentDirectoryW(ARRAY_SIZE(cwd), cwd); DWORD ret = GetCurrentDirectoryW(ARRAY_SIZE(cwd), cwd);
HANDLE hnd;
if (!ret || ret >= ARRAY_SIZE(cwd)) { if (!ret || ret >= ARRAY_SIZE(cwd)) {
errno = ret ? ENAMETOOLONG : err_win_to_posix(GetLastError()); errno = ret ? ENAMETOOLONG : err_win_to_posix(GetLastError());
return NULL; return NULL;
} }
ret = GetLongPathNameW(cwd, wpointer, ARRAY_SIZE(wpointer)); hnd = CreateFileW(cwd, 0,
if (!ret && GetLastError() == ERROR_ACCESS_DENIED) { FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
HANDLE hnd = CreateFileW(cwd, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, if (hnd != INVALID_HANDLE_VALUE) {
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hnd == INVALID_HANDLE_VALUE)
return NULL;
ret = GetFinalPathNameByHandleW(hnd, wpointer, ARRAY_SIZE(wpointer), 0); ret = GetFinalPathNameByHandleW(hnd, wpointer, ARRAY_SIZE(wpointer), 0);
CloseHandle(hnd); CloseHandle(hnd);
if (!ret || ret >= ARRAY_SIZE(wpointer)) if (!ret || ret >= ARRAY_SIZE(wpointer))
@@ -1231,13 +1229,11 @@ char *mingw_getcwd(char *pointer, int len)
return NULL; return NULL;
return pointer; return pointer;
} }
if (!ret || ret >= ARRAY_SIZE(wpointer)) if (GetFileAttributesW(cwd) == INVALID_FILE_ATTRIBUTES) {
return NULL;
if (GetFileAttributesW(wpointer) == INVALID_FILE_ATTRIBUTES) {
errno = ENOENT; errno = ENOENT;
return NULL; return NULL;
} }
if (xwcstoutf(pointer, wpointer, len) < 0) if (xwcstoutf(pointer, cwd, len) < 0)
return NULL; return NULL;
convert_slashes(pointer); convert_slashes(pointer);
return pointer; return pointer;