Skip to content

Commit 9c238b4

Browse files
dschoGit for Windows Build Agent
authored and
Git for Windows Build Agent
committed
Merge pull request #443 from kblees/kb/nanosecond-file-times-v2.5.3
nanosecond file times for v2.5.3
2 parents be68202 + d12f838 commit 9c238b4

File tree

4 files changed

+70
-41
lines changed

4 files changed

+70
-41
lines changed

compat/mingw.c

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -855,9 +855,9 @@ int mingw_lstat(const char *file_name, struct stat *buf)
855855
buf->st_size = S_ISLNK(buf->st_mode) ? MAX_LONG_PATH :
856856
fdata.nFileSizeLow | (((off_t) fdata.nFileSizeHigh) << 32);
857857
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
858-
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
859-
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
860-
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
858+
filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
859+
filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
860+
filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
861861
return 0;
862862
}
863863
error:
@@ -902,9 +902,9 @@ static int get_file_info_by_handle(HANDLE hnd, struct stat *buf)
902902
buf->st_nlink = 1;
903903
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes, 0);
904904
buf->st_size = fdata.nFileSizeLow | (((off_t) fdata.nFileSizeHigh) << 32);
905-
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
906-
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
907-
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
905+
filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
906+
filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
907+
filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
908908
return 0;
909909
}
910910

@@ -932,18 +932,31 @@ int mingw_stat(const char *file_name, struct stat *buf)
932932
int mingw_fstat(int fd, struct stat *buf)
933933
{
934934
HANDLE fh = (HANDLE)_get_osfhandle(fd);
935-
if (fh == INVALID_HANDLE_VALUE) {
935+
DWORD avail, type = GetFileType(fh) & ~FILE_TYPE_REMOTE;
936+
937+
switch (type) {
938+
case FILE_TYPE_DISK:
939+
return get_file_info_by_handle(fh, buf);
940+
941+
case FILE_TYPE_CHAR:
942+
case FILE_TYPE_PIPE:
943+
/* initialize stat fields */
944+
memset(buf, 0, sizeof(*buf));
945+
buf->st_nlink = 1;
946+
947+
if (type == FILE_TYPE_CHAR) {
948+
buf->st_mode = _S_IFCHR;
949+
} else {
950+
buf->st_mode = _S_IFIFO;
951+
if (PeekNamedPipe(fh, NULL, 0, NULL, &avail, NULL))
952+
buf->st_size = avail;
953+
}
954+
return 0;
955+
956+
default:
936957
errno = EBADF;
937958
return -1;
938959
}
939-
/* direct non-file handles to MS's fstat() */
940-
if (GetFileType(fh) != FILE_TYPE_DISK)
941-
return _fstati64(fd, buf);
942-
943-
if (!get_file_info_by_handle(fh, buf))
944-
return 0;
945-
errno = EBADF;
946-
return -1;
947960
}
948961

949962
static inline void time_t_to_filetime(time_t t, FILETIME *ft)

compat/mingw.h

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -345,24 +345,49 @@ static inline long long filetime_to_hnsec(const FILETIME *ft)
345345
return winTime - 116444736000000000LL;
346346
}
347347

348-
static inline time_t filetime_to_time_t(const FILETIME *ft)
349-
{
350-
return (time_t)(filetime_to_hnsec(ft) / 10000000);
351-
}
352-
353348
/*
354-
* Use mingw specific stat()/lstat()/fstat() implementations on Windows.
349+
* Use mingw specific stat()/lstat()/fstat() implementations on Windows,
350+
* including our own struct stat with 64 bit st_size and nanosecond-precision
351+
* file times.
355352
*/
356353
#ifndef __MINGW64_VERSION_MAJOR
357354
#define off_t off64_t
358355
#define lseek _lseeki64
356+
struct timespec {
357+
time_t tv_sec;
358+
long tv_nsec;
359+
};
359360
#endif
360361

361-
/* use struct stat with 64 bit st_size */
362+
static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
363+
{
364+
long long hnsec = filetime_to_hnsec(ft);
365+
ts->tv_sec = (time_t)(hnsec / 10000000);
366+
ts->tv_nsec = (hnsec % 10000000) * 100;
367+
}
368+
369+
struct mingw_stat {
370+
_dev_t st_dev;
371+
_ino_t st_ino;
372+
_mode_t st_mode;
373+
short st_nlink;
374+
short st_uid;
375+
short st_gid;
376+
_dev_t st_rdev;
377+
off64_t st_size;
378+
struct timespec st_atim;
379+
struct timespec st_mtim;
380+
struct timespec st_ctim;
381+
};
382+
383+
#define st_atime st_atim.tv_sec
384+
#define st_mtime st_mtim.tv_sec
385+
#define st_ctime st_ctim.tv_sec
386+
362387
#ifdef stat
363388
#undef stat
364389
#endif
365-
#define stat _stati64
390+
#define stat mingw_stat
366391
int mingw_lstat(const char *file_name, struct stat *buf);
367392
int mingw_stat(const char *file_name, struct stat *buf);
368393
int mingw_fstat(int fd, struct stat *buf);
@@ -375,13 +400,6 @@ int mingw_fstat(int fd, struct stat *buf);
375400
#endif
376401
extern int (*lstat)(const char *file_name, struct stat *buf);
377402

378-
#ifndef _stati64
379-
# define _stati64(x,y) mingw_stat(x,y)
380-
#elif defined (_USE_32BIT_TIME_T)
381-
# define _stat32i64(x,y) mingw_stat(x,y)
382-
#else
383-
# define _stat64(x,y) mingw_stat(x,y)
384-
#endif
385403

386404
int mingw_utime(const char *file_name, const struct utimbuf *times);
387405
#define utime mingw_utime

compat/win32/fscache.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ struct fsentry {
3838
struct {
3939
/* More stat members (only used for file entries). */
4040
off64_t st_size;
41-
time_t st_atime;
42-
time_t st_mtime;
43-
time_t st_ctime;
41+
struct timespec st_atim;
42+
struct timespec st_mtim;
43+
struct timespec st_ctim;
4444
};
4545
};
4646
};
@@ -153,9 +153,9 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
153153
fdata->dwReserved0);
154154
fse->st_size = S_ISLNK(fse->st_mode) ? MAX_LONG_PATH :
155155
fdata->nFileSizeLow | (((off_t) fdata->nFileSizeHigh) << 32);
156-
fse->st_atime = filetime_to_time_t(&(fdata->ftLastAccessTime));
157-
fse->st_mtime = filetime_to_time_t(&(fdata->ftLastWriteTime));
158-
fse->st_ctime = filetime_to_time_t(&(fdata->ftCreationTime));
156+
filetime_to_timespec(&(fdata->ftLastAccessTime), &(fse->st_atim));
157+
filetime_to_timespec(&(fdata->ftLastWriteTime), &(fse->st_mtim));
158+
filetime_to_timespec(&(fdata->ftCreationTime), &(fse->st_ctim));
159159

160160
return fse;
161161
}
@@ -418,9 +418,9 @@ int fscache_lstat(const char *filename, struct stat *st)
418418
st->st_nlink = 1;
419419
st->st_mode = fse->st_mode;
420420
st->st_size = fse->st_size;
421-
st->st_atime = fse->st_atime;
422-
st->st_mtime = fse->st_mtime;
423-
st->st_ctime = fse->st_ctime;
421+
st->st_atim = fse->st_atim;
422+
st->st_mtim = fse->st_mtim;
423+
st->st_ctim = fse->st_ctim;
424424

425425
/* don't forget to release fsentry */
426426
fsentry_release(fse);

config.mak.uname

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,6 @@ ifeq ($(uname_S),Windows)
370370
RUNTIME_PREFIX = YesPlease
371371
HAVE_WPGMPTR = YesWeDo
372372
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
373-
NO_NSEC = YesPlease
374373
USE_WIN32_MMAP = YesPlease
375374
MMAP_PREVENTS_DELETE = UnfortunatelyYes
376375
# USE_NED_ALLOCATOR = YesPlease
@@ -519,7 +518,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))
519518
RUNTIME_PREFIX = YesPlease
520519
HAVE_WPGMPTR = YesWeDo
521520
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
522-
NO_NSEC = YesPlease
523521
USE_WIN32_MMAP = YesPlease
524522
MMAP_PREVENTS_DELETE = UnfortunatelyYes
525523
USE_NED_ALLOCATOR = YesPlease

0 commit comments

Comments
 (0)