mingw: allow `mingw_chdir()` to change to symlink-resolved directories
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 <karsten.blees@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Karsten Blees committed
Jan 9, 2026 at 20:05 UTC
43745a7d55daa1aa0937a3c6e8b521bd026a31f1
1 file changed
+19
-1
compat/mingw.c
+19
-1
@@ -866,9 +866,27 @@ int mingw_access(const char *filename, int mode)
866
int mingw_chdir(const char *dirname)
867
{
868
wchar_t wdirname[MAX_PATH];
869
+
870
if (xutftowcs_path(wdirname, dirname) < 0)
871
return -1;
871
- return _wchdir(wdirname);
872
+
873
+ if (has_symlinks) {
874
+ HANDLE hnd = CreateFileW(wdirname, 0,
875
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
876
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
877
+ if (hnd == INVALID_HANDLE_VALUE) {
878
+ errno = err_win_to_posix(GetLastError());
879
+ return -1;
880
+ }
881
+ if (!GetFinalPathNameByHandleW(hnd, wdirname, ARRAY_SIZE(wdirname), 0)) {
882
+ errno = err_win_to_posix(GetLastError());
883
+ CloseHandle(hnd);
884
+ return -1;
885
+ }
886
+ CloseHandle(hnd);
887
+ }
888
+
889
+ return _wchdir(normalize_ntpath(wdirname));
890
}
891
892
int mingw_chmod(const char *filename, int mode)