Skip to content

Commit

Permalink
Merge pull request git-for-windows#443 from kblees/kb/nanosecond-file…
Browse files Browse the repository at this point in the history
…-times-v2.5.3

nanosecond file times for v2.5.3
  • Loading branch information
dscho committed Oct 30, 2018
2 parents 706b555 + a379b71 commit 6e35431
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 38 deletions.
76 changes: 50 additions & 26 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,9 +587,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;
}

/**
Expand Down Expand Up @@ -648,9 +650,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);
Expand Down Expand Up @@ -731,6 +733,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);
Expand All @@ -743,32 +768,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) {
errno = EBADF;
return -1;
}
/* direct non-file handles to MS's fstat() */
if (GetFileType(fh) != FILE_TYPE_DISK)
return _fstati64(fd, buf);
switch (type) {
case FILE_TYPE_DISK:
return get_file_info_by_handle(fh, buf);

if (GetFileInformationByHandle(fh, &fdata)) {
buf->st_ino = 0;
buf->st_gid = 0;
buf->st_uid = 0;
case FILE_TYPE_CHAR:
case FILE_TYPE_PIPE:
/* initialize stat fields */
memset(buf, 0, sizeof(*buf));
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));

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;
}
errno = EBADF;
return -1;
}

static inline void time_t_to_filetime(time_t t, FILETIME *ft)
Expand Down
36 changes: 26 additions & 10 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,18 +351,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);
Expand All @@ -375,13 +398,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
Expand Down
2 changes: 0 additions & 2 deletions config.mak.uname
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 6e35431

Please sign in to comment.