Skip to content

Commit 9f2d7e5

Browse files
kbleesdscho
authored andcommitted
Win32: teach fscache and dirent about symlinks
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 <[email protected]>
1 parent df3ae60 commit 9f2d7e5

File tree

4 files changed

+15
-15
lines changed

4 files changed

+15
-15
lines changed

compat/mingw.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -565,21 +565,14 @@ int mingw_lstat(const char *file_name, struct stat *buf)
565565
buf->st_gid = 0;
566566
buf->st_uid = 0;
567567
buf->st_nlink = 1;
568-
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
568+
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes,
569+
findbuf.dwReserved0);
569570
buf->st_size = fdata.nFileSizeLow |
570571
(((off_t)fdata.nFileSizeHigh)<<32);
571572
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
572573
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
573574
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
574575
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
575-
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
576-
if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
577-
(findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
578-
buf->st_mode = S_IFLNK | S_IREAD;
579-
if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
580-
buf->st_mode |= S_IWRITE;
581-
}
582-
}
583576
return 0;
584577
}
585578
error:
@@ -622,7 +615,7 @@ static int get_file_info_by_handle(HANDLE hnd, struct stat *buf)
622615
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
623616
buf->st_gid = buf->st_uid = 0;
624617
buf->st_nlink = 1;
625-
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
618+
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes, 0);
626619
buf->st_size = fdata.nFileSizeLow | (((off_t) fdata.nFileSizeHigh) << 32);
627620
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
628621
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));

compat/win32.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
#include <windows.h>
77
#endif
88

9-
static inline int file_attr_to_st_mode (DWORD attr)
9+
static inline int file_attr_to_st_mode (DWORD attr, DWORD tag)
1010
{
1111
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)
1315
fMode |= S_IFDIR;
1416
else
1517
fMode |= S_IFREG;

compat/win32/dirent.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ static inline void finddata2dirent(struct dirent *ent, WIN32_FIND_DATAW *fdata)
1616
xwcstoutf(ent->d_name, fdata->cFileName, MAX_PATH * 3);
1717

1818
/* Set file type, based on WIN32_FIND_DATA */
19-
if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
19+
if ((fdata->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
20+
&& fdata->dwReserved0 == IO_REPARSE_TAG_SYMLINK)
21+
ent->d_type = DT_LNK;
22+
else if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2023
ent->d_type = DT_DIR;
2124
else
2225
ent->d_type = DT_REG;

compat/win32/fscache.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
147147

148148
fse = fsentry_alloc(list, buf, len);
149149

150-
fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes);
150+
fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes,
151+
fdata->dwReserved0);
151152
fse->st_size = (((off64_t) (fdata->nFileSizeHigh)) << 32)
152153
| fdata->nFileSizeLow;
153154
fse->st_atime = filetime_to_time_t(&(fdata->ftLastAccessTime));
@@ -456,7 +457,8 @@ static struct dirent *fscache_readdir(DIR *base_dir)
456457
if (!next)
457458
return NULL;
458459
dir->pfsentry = next;
459-
dir->dirent.d_type = S_ISDIR(next->st_mode) ? DT_DIR : DT_REG;
460+
dir->dirent.d_type = S_ISREG(next->st_mode) ? DT_REG :
461+
S_ISDIR(next->st_mode) ? DT_DIR : DT_LNK;
460462
dir->dirent.d_name = (char*) next->name;
461463
return &(dir->dirent);
462464
}

0 commit comments

Comments
 (0)