Merge branch 'js/mingw-ns-filetime'
Windows port learned to use nano-second resolution file timestamps. * js/mingw-ns-filetime: mingw: implement nanosecond-precision file times mingw: replace MSVCRT's fstat() with a Win32-based implementation mingw: factor out code to set stat() data
This commit is contained in:
commit
b9c3f062b6
@ -618,9 +618,11 @@ static inline long long filetime_to_hnsec(const FILETIME *ft)
|
||||
return winTime - 116444736000000000LL;
|
||||
}
|
||||
|
||||
static inline time_t filetime_to_time_t(const FILETIME *ft)
|
||||
static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
|
||||
{
|
||||
return (time_t)(filetime_to_hnsec(ft) / 10000000);
|
||||
long long hnsec = filetime_to_hnsec(ft);
|
||||
ts->tv_sec = (time_t)(hnsec / 10000000);
|
||||
ts->tv_nsec = (hnsec % 10000000) * 100;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -679,9 +681,9 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
|
||||
buf->st_size = fdata.nFileSizeLow |
|
||||
(((off_t)fdata.nFileSizeHigh)<<32);
|
||||
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
|
||||
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
|
||||
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
|
||||
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
|
||||
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) {
|
||||
WIN32_FIND_DATAW findbuf;
|
||||
HANDLE handle = FindFirstFileW(wfilename, &findbuf);
|
||||
@ -762,6 +764,29 @@ static int do_stat_internal(int follow, const char *file_name, struct stat *buf)
|
||||
return do_lstat(follow, alt_name, buf);
|
||||
}
|
||||
|
||||
static int get_file_info_by_handle(HANDLE hnd, struct stat *buf)
|
||||
{
|
||||
BY_HANDLE_FILE_INFORMATION fdata;
|
||||
|
||||
if (!GetFileInformationByHandle(hnd, &fdata)) {
|
||||
errno = err_win_to_posix(GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf->st_ino = 0;
|
||||
buf->st_gid = 0;
|
||||
buf->st_uid = 0;
|
||||
buf->st_nlink = 1;
|
||||
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
|
||||
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));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mingw_lstat(const char *file_name, struct stat *buf)
|
||||
{
|
||||
return do_stat_internal(0, file_name, buf);
|
||||
@ -774,32 +799,31 @@ int mingw_stat(const char *file_name, struct stat *buf)
|
||||
int mingw_fstat(int fd, struct stat *buf)
|
||||
{
|
||||
HANDLE fh = (HANDLE)_get_osfhandle(fd);
|
||||
BY_HANDLE_FILE_INFORMATION fdata;
|
||||
DWORD avail, type = GetFileType(fh) & ~FILE_TYPE_REMOTE;
|
||||
|
||||
if (fh == INVALID_HANDLE_VALUE) {
|
||||
switch (type) {
|
||||
case FILE_TYPE_DISK:
|
||||
return get_file_info_by_handle(fh, buf);
|
||||
|
||||
case FILE_TYPE_CHAR:
|
||||
case FILE_TYPE_PIPE:
|
||||
/* initialize stat fields */
|
||||
memset(buf, 0, sizeof(*buf));
|
||||
buf->st_nlink = 1;
|
||||
|
||||
if (type == FILE_TYPE_CHAR) {
|
||||
buf->st_mode = _S_IFCHR;
|
||||
} else {
|
||||
buf->st_mode = _S_IFIFO;
|
||||
if (PeekNamedPipe(fh, NULL, 0, NULL, &avail, NULL))
|
||||
buf->st_size = avail;
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
/* direct non-file handles to MS's fstat() */
|
||||
if (GetFileType(fh) != FILE_TYPE_DISK)
|
||||
return _fstati64(fd, buf);
|
||||
|
||||
if (GetFileInformationByHandle(fh, &fdata)) {
|
||||
buf->st_ino = 0;
|
||||
buf->st_gid = 0;
|
||||
buf->st_uid = 0;
|
||||
buf->st_nlink = 1;
|
||||
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
|
||||
buf->st_size = fdata.nFileSizeLow |
|
||||
(((off_t)fdata.nFileSizeHigh)<<32);
|
||||
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
|
||||
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
|
||||
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
|
||||
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
|
||||
return 0;
|
||||
}
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline void time_t_to_filetime(time_t t, FILETIME *ft)
|
||||
|
@ -327,18 +327,41 @@ static inline int getrlimit(int resource, struct rlimit *rlp)
|
||||
}
|
||||
|
||||
/*
|
||||
* Use mingw specific stat()/lstat()/fstat() implementations on Windows.
|
||||
* Use mingw specific stat()/lstat()/fstat() implementations on Windows,
|
||||
* including our own struct stat with 64 bit st_size and nanosecond-precision
|
||||
* file times.
|
||||
*/
|
||||
#ifndef __MINGW64_VERSION_MAJOR
|
||||
#define off_t off64_t
|
||||
#define lseek _lseeki64
|
||||
struct timespec {
|
||||
time_t tv_sec;
|
||||
long tv_nsec;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* use struct stat with 64 bit st_size */
|
||||
struct mingw_stat {
|
||||
_dev_t st_dev;
|
||||
_ino_t st_ino;
|
||||
_mode_t st_mode;
|
||||
short st_nlink;
|
||||
short st_uid;
|
||||
short st_gid;
|
||||
_dev_t st_rdev;
|
||||
off64_t st_size;
|
||||
struct timespec st_atim;
|
||||
struct timespec st_mtim;
|
||||
struct timespec st_ctim;
|
||||
};
|
||||
|
||||
#define st_atime st_atim.tv_sec
|
||||
#define st_mtime st_mtim.tv_sec
|
||||
#define st_ctime st_ctim.tv_sec
|
||||
|
||||
#ifdef stat
|
||||
#undef stat
|
||||
#endif
|
||||
#define stat _stati64
|
||||
#define stat mingw_stat
|
||||
int mingw_lstat(const char *file_name, struct stat *buf);
|
||||
int mingw_stat(const char *file_name, struct stat *buf);
|
||||
int mingw_fstat(int fd, struct stat *buf);
|
||||
@ -351,13 +374,6 @@ int mingw_fstat(int fd, struct stat *buf);
|
||||
#endif
|
||||
#define lstat mingw_lstat
|
||||
|
||||
#ifndef _stati64
|
||||
# define _stati64(x,y) mingw_stat(x,y)
|
||||
#elif defined (_USE_32BIT_TIME_T)
|
||||
# define _stat32i64(x,y) mingw_stat(x,y)
|
||||
#else
|
||||
# define _stat64(x,y) mingw_stat(x,y)
|
||||
#endif
|
||||
|
||||
int mingw_utime(const char *file_name, const struct utimbuf *times);
|
||||
#define utime mingw_utime
|
||||
|
@ -370,7 +370,6 @@ ifeq ($(uname_S),Windows)
|
||||
RUNTIME_PREFIX = YesPlease
|
||||
HAVE_WPGMPTR = YesWeDo
|
||||
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
|
||||
NO_NSEC = YesPlease
|
||||
USE_WIN32_MMAP = YesPlease
|
||||
MMAP_PREVENTS_DELETE = UnfortunatelyYes
|
||||
# USE_NED_ALLOCATOR = YesPlease
|
||||
@ -518,7 +517,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))
|
||||
RUNTIME_PREFIX = YesPlease
|
||||
HAVE_WPGMPTR = YesWeDo
|
||||
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
|
||||
NO_NSEC = YesPlease
|
||||
USE_WIN32_MMAP = YesPlease
|
||||
MMAP_PREVENTS_DELETE = UnfortunatelyYes
|
||||
USE_NED_ALLOCATOR = YesPlease
|
||||
|
Loading…
Reference in New Issue
Block a user