]> git.ipfire.org Git - thirdparty/git.git/commitdiff
mingw: teach dirent about symlinks
authorKarsten Blees <blees@dcon.de>
Wed, 17 Dec 2025 14:08:42 +0000 (14:08 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 17 Dec 2025 23:22:18 +0000 (08:22 +0900)
Move the `S_IFLNK` detection to `file_attr_to_st_mode()`.

Implement `DT_LNK` detection in dirent.c's `readdir()` function.

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
compat/win32.h
compat/win32/dirent.c

index 23a926c7d149945de89d718b8ca96bc59fdb6d84..a3a48db581df87962369ca1a8ee7186a91814589 100644 (file)
@@ -946,21 +946,14 @@ int mingw_lstat(const char *file_name, struct stat *buf)
                buf->st_gid = 0;
                buf->st_uid = 0;
                buf->st_nlink = 1;
-               buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
+               buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes,
+                               findbuf.dwReserved0);
                buf->st_size = fdata.nFileSizeLow |
                        (((off_t)fdata.nFileSizeHigh)<<32);
                buf->st_dev = buf->st_rdev = 0; /* not used by Git */
                filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
                filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
                filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
-               if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
-                       if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
-                                       (findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
-                               buf->st_mode = S_IFLNK | S_IREAD;
-                               if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
-                                       buf->st_mode |= S_IWRITE;
-                       }
-               }
                return 0;
        }
 error:
@@ -1003,7 +996,7 @@ static int get_file_info_by_handle(HANDLE hnd, struct stat *buf)
        buf->st_gid = 0;
        buf->st_uid = 0;
        buf->st_nlink = 1;
-       buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
+       buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes, 0);
        buf->st_size = fdata.nFileSizeLow |
                (((off_t)fdata.nFileSizeHigh)<<32);
        buf->st_dev = buf->st_rdev = 0; /* not used by Git */
index a97e880757b6f1328fea90371da8f857648e6923..671bcc81f93351909e01b82278e7e5195b788f84 100644 (file)
@@ -6,10 +6,12 @@
 #include <windows.h>
 #endif
 
-static inline int file_attr_to_st_mode (DWORD attr)
+static inline int file_attr_to_st_mode (DWORD attr, DWORD tag)
 {
        int fMode = S_IREAD;
-       if (attr & FILE_ATTRIBUTE_DIRECTORY)
+       if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) && tag == IO_REPARSE_TAG_SYMLINK)
+               fMode |= S_IFLNK;
+       else if (attr & FILE_ATTRIBUTE_DIRECTORY)
                fMode |= S_IFDIR;
        else
                fMode |= S_IFREG;
index 52420ec7d4dad7b8e984bd7f5a36330f1fa88e24..24ee9b814d6adf870a9e61dcd744d165593131cf 100644 (file)
@@ -12,7 +12,10 @@ static inline void finddata2dirent(struct dirent *ent, WIN32_FIND_DATAW *fdata)
        xwcstoutf(ent->d_name, fdata->cFileName, sizeof(ent->d_name));
 
        /* Set file type, based on WIN32_FIND_DATA */
-       if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+       if ((fdata->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+                       && fdata->dwReserved0 == IO_REPARSE_TAG_SYMLINK)
+               ent->d_type = DT_LNK;
+       else if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                ent->d_type = DT_DIR;
        else
                ent->d_type = DT_REG;