]> git.ipfire.org Git - thirdparty/git.git/commitdiff
mingw: implement `stat()` with symlink support
authorKarsten Blees <karsten.blees@gmail.com>
Fri, 9 Jan 2026 20:04:59 +0000 (20:04 +0000)
committerJunio C Hamano <gitster@pobox.com>
Sat, 10 Jan 2026 02:32:54 +0000 (18:32 -0800)
With respect to symlinks, the current `mingw_stat()` implementation is
almost identical to `mingw_lstat()`: except for the file type (`st_mode
& S_IFMT`), it returns information about the link rather than the target.

Implement `mingw_stat()` by opening the file handle requesting minimal
permissions, and then calling `GetFileInformationByHandle()` on it. This
way, all links are resolved by the Windows file system layer.

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>
compat/mingw.c

index ae6826948e718ddb4f95532e9350fe68838598ac..13970ae729872e2c80994246849293c42de9d42d 100644 (file)
@@ -1027,9 +1027,26 @@ int mingw_lstat(const char *file_name, struct stat *buf)
 {
        return do_lstat(0, file_name, buf);
 }
+
 int mingw_stat(const char *file_name, struct stat *buf)
 {
-       return do_lstat(1, file_name, buf);
+       wchar_t wfile_name[MAX_PATH];
+       HANDLE hnd;
+       int result;
+
+       /* open the file and let Windows resolve the links */
+       if (xutftowcs_path(wfile_name, file_name) < 0)
+               return -1;
+       hnd = CreateFileW(wfile_name, 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;
+       }
+       result = get_file_info_by_handle(hnd, buf);
+       CloseHandle(hnd);
+       return result;
 }
 
 int mingw_fstat(int fd, struct stat *buf)