mingw: teach dirent about symlinks
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 <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
8a4f4131aad8d2b176f83df628ee3a8d6e19ba6c
3 files changed
+11
-13
compat/mingw.c
+3
-10
@@ -946,21 +946,14 @@ int mingw_lstat(const char *file_name, struct stat *buf)
946
buf->st_gid = 0;
947
buf->st_uid = 0;
948
buf->st_nlink = 1;
949
- buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
949
+ buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes,
950
+ findbuf.dwReserved0);
951
buf->st_size = fdata.nFileSizeLow |
952
(((off_t)fdata.nFileSizeHigh)<<32);
953
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
954
filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
955
filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
956
filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
956
- if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
957
- if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
958
- (findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
959
- buf->st_mode = S_IFLNK | S_IREAD;
960
- if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
961
- buf->st_mode |= S_IWRITE;
962
- }
963
- }
957
return 0;
958
}
959
error:
@@ -1003,7 +996,7 @@ static int get_file_info_by_handle(HANDLE hnd, struct stat *buf)
996
buf->st_gid = 0;
997
buf->st_uid = 0;
998
buf->st_nlink = 1;
1006
- buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
999
+ buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes, 0);
1000
buf->st_size = fdata.nFileSizeLow |
1001
(((off_t)fdata.nFileSizeHigh)<<32);
1002
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
compat/win32.h
+4
-2
@@ -6,10 +6,12 @@
6
#include <windows.h>
7
#endif
8
9
-static inline int file_attr_to_st_mode (DWORD attr)
9
+static inline int file_attr_to_st_mode (DWORD attr, DWORD tag)
10
{
11
int fMode = S_IREAD;
12
- if (attr & FILE_ATTRIBUTE_DIRECTORY)
12
+ if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) && tag == IO_REPARSE_TAG_SYMLINK)
13
+ fMode |= S_IFLNK;
14
+ else if (attr & FILE_ATTRIBUTE_DIRECTORY)
15
fMode |= S_IFDIR;
16
else
17
fMode |= S_IFREG;
compat/win32/dirent.c
+4
-1
@@ -12,7 +12,10 @@ static inline void finddata2dirent(struct dirent *ent, WIN32_FIND_DATAW *fdata)
12
xwcstoutf(ent->d_name, fdata->cFileName, sizeof(ent->d_name));
13
14
/* Set file type, based on WIN32_FIND_DATA */
15
- if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
15
+ if ((fdata->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
16
+ && fdata->dwReserved0 == IO_REPARSE_TAG_SYMLINK)
17
+ ent->d_type = DT_LNK;
18
+ else if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
19
ent->d_type = DT_DIR;
20
else
21
ent->d_type = DT_REG;