]> git.ipfire.org Git - thirdparty/git.git/commitdiff
mingw: allow `mingw_chdir()` to change to symlink-resolved directories
authorKarsten Blees <blees@dcon.de>
Wed, 17 Dec 2025 14:08:49 +0000 (14:08 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 17 Dec 2025 23:22:19 +0000 (08:22 +0900)
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>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
compat/mingw.c

index 55f0bb478e61271ee994dcfc233e600c23a754a7..5d2a8c247ce622b923a6d60479a144dcbf2aa4ed 100644 (file)
@@ -866,9 +866,27 @@ int mingw_access(const char *filename, int mode)
 int mingw_chdir(const char *dirname)
 {
        wchar_t wdirname[MAX_PATH];
+
        if (xutftowcs_path(wdirname, dirname) < 0)
                return -1;
-       return _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);
+       }
+
+       return _wchdir(normalize_ntpath(wdirname));
 }
 
 int mingw_chmod(const char *filename, int mode)