aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarsten Blees <karsten.blees@gmail.com>2026-01-09 20:05:02 +0000
committerJunio C Hamano <gitster@pobox.com>2026-01-09 18:32:55 -0800
commit8a4f4131aad8d2b176f83df628ee3a8d6e19ba6c (patch)
treeba2629615da4aa9f90a5746c9ed8fb308c056a79
parent2c37842ff97c28876e980f1829bc732c98dcde14 (diff)
downloadgit-8a4f4131aad8d2b176f83df628ee3a8d6e19ba6c.tar.xz
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>
-rw-r--r--compat/mingw.c13
-rw-r--r--compat/win32.h6
-rw-r--r--compat/win32/dirent.c5
3 files changed, 11 insertions, 13 deletions
diff --git a/compat/mingw.c b/compat/mingw.c
index 23a926c7d1..a3a48db581 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -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 */
diff --git a/compat/win32.h b/compat/win32.h
index a97e880757..671bcc81f9 100644
--- a/compat/win32.h
+++ b/compat/win32.h
@@ -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;
diff --git a/compat/win32/dirent.c b/compat/win32/dirent.c
index 52420ec7d4..24ee9b814d 100644
--- a/compat/win32/dirent.c
+++ b/compat/win32/dirent.c
@@ -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;