Skip to content

Commit

Permalink
mingw: teach fscache and dirent about symlinks
Browse files Browse the repository at this point in the history
Move S_IFLNK detection to file_attr_to_st_mode() and reuse it in fscache.

Implement DT_LNK detection in dirent.c and the fscache readdir version.

Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
  • Loading branch information
kblees authored and dscho committed Sep 22, 2022
1 parent aa33f26 commit 0a17234
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 17 deletions.
13 changes: 3 additions & 10 deletions compat/mingw.c
Expand Up @@ -846,21 +846,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:
Expand Down Expand Up @@ -905,7 +898,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 */
Expand Down
6 changes: 4 additions & 2 deletions compat/win32.h
Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion compat/win32/dirent.c
Expand Up @@ -18,7 +18,10 @@ static inline void finddata2dirent(struct dirent *ent, WIN32_FIND_DATAW *fdata)
xwcstoutf(ent->d_name, fdata->cFileName, MAX_PATH * 3);

/* 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;
Expand Down
11 changes: 7 additions & 4 deletions compat/win32/fscache.c
Expand Up @@ -200,10 +200,13 @@ static struct fsentry *fseentry_create_entry(struct fscache *cache,
fdata->FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ?
fdata->EaSize : 0;

fse->st_mode = file_attr_to_st_mode(fdata->FileAttributes);
fse->dirent.d_type = S_ISDIR(fse->st_mode) ? DT_DIR : DT_REG;
fse->u.s.st_size = fdata->EndOfFile.LowPart |
(((off_t)fdata->EndOfFile.HighPart) << 32);
fse->st_mode = file_attr_to_st_mode(fdata->FileAttributes,
fdata->EaSize);
fse->dirent.d_type = S_ISREG(fse->st_mode) ? DT_REG :
S_ISDIR(fse->st_mode) ? DT_DIR : DT_LNK;
fse->u.s.st_size = S_ISLNK(fse->st_mode) ? MAX_LONG_PATH :
fdata->EndOfFile.LowPart |
(((off_t)fdata->EndOfFile.HighPart) << 32);
filetime_to_timespec((FILETIME *)&(fdata->LastAccessTime),
&(fse->u.s.st_atim));
filetime_to_timespec((FILETIME *)&(fdata->LastWriteTime),
Expand Down

0 comments on commit 0a17234

Please sign in to comment.