Skip to content

Commit

Permalink
Win32: mingw_chdir: change to symlink-resolved directory
Browse files Browse the repository at this point in the history
If symlinks are enabled, resolve all symlinks when changing directories,
as required by POSIX.

Note: Git's real_path() function bases its link resolution algorithm on
this property of chdir(). Unfortunately, the current directory on Windows
is limited to only MAX_PATH (260) characters. Therefore using symlinks and
long paths in combination may be problematic.

Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
  • Loading branch information
kblees authored and dscho committed Sep 18, 2024
1 parent ab63096 commit d40f2b0
Showing 1 changed file with 18 additions and 1 deletion.
19 changes: 18 additions & 1 deletion compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,24 @@ int mingw_chdir(const char *dirname)
wchar_t wdirname[MAX_LONG_PATH];
if (xutftowcs_long_path(wdirname, dirname) < 0)
return -1;
result = _wchdir(wdirname);

if (has_symlinks) {
HANDLE hnd = CreateFileW(wdirname, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hnd == INVALID_HANDLE_VALUE) {
errno = err_win_to_posix(GetLastError());
return -1;
}
if (!GetFinalPathNameByHandleW(hnd, wdirname, ARRAY_SIZE(wdirname), 0)) {
errno = err_win_to_posix(GetLastError());
CloseHandle(hnd);
return -1;
}
CloseHandle(hnd);
}

result = _wchdir(normalize_ntpath(wdirname));
current_directory_len = GetCurrentDirectoryW(0, NULL);
return result;
}
Expand Down

0 comments on commit d40f2b0

Please sign in to comment.