Skip to content

Commit 2a7953e

Browse files
committed
Merge pull request #443 from kblees/kb/nanosecond-file-times-v2.5.3
nanosecond file times for v2.5.3
2 parents 160840d + 3d04ebc commit 2a7953e

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
@@ -698,9 +698,9 @@ int mingw_lstat(const char *file_name, struct stat *buf)
698698
buf->st_size = S_ISLNK(buf->st_mode) ? MAX_LONG_PATH :
699699
fdata.nFileSizeLow | (((off_t) fdata.nFileSizeHigh) << 32);
700700
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
701-
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
702-
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
703-
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
701+
filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
702+
filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
703+
filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
704704
return 0;
705705
}
706706
error:
@@ -745,9 +745,9 @@ static int get_file_info_by_handle(HANDLE hnd, struct stat *buf)
745745
buf->st_nlink = 1;
746746
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes, 0);
747747
buf->st_size = fdata.nFileSizeLow | (((off_t) fdata.nFileSizeHigh) << 32);
748-
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
749-
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
750-
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
748+
filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
749+
filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
750+
filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
751751
return 0;
752752
}
753753

@@ -775,18 +775,31 @@ int mingw_stat(const char *file_name, struct stat *buf)
775775
int mingw_fstat(int fd, struct stat *buf)
776776
{
777777
HANDLE fh = (HANDLE)_get_osfhandle(fd);
778-
if (fh == INVALID_HANDLE_VALUE) {
778+
DWORD avail, type = GetFileType(fh) & ~FILE_TYPE_REMOTE;
779+
780+
switch (type) {
781+
case FILE_TYPE_DISK:
782+
return get_file_info_by_handle(fh, buf);
783+
784+
case FILE_TYPE_CHAR:
785+
case FILE_TYPE_PIPE:
786+
/* initialize stat fields */
787+
memset(buf, 0, sizeof(*buf));
788+
buf->st_nlink = 1;
789+
790+
if (type == FILE_TYPE_CHAR) {
791+
buf->st_mode = _S_IFCHR;
792+
} else {
793+
buf->st_mode = _S_IFIFO;
794+
if (PeekNamedPipe(fh, NULL, 0, NULL, &avail, NULL))
795+
buf->st_size = avail;
796+
}
797+
return 0;
798+
799+
default:
779800
errno = EBADF;
780801
return -1;
781802
}
782-
/* direct non-file handles to MS's fstat() */
783-
if (GetFileType(fh) != FILE_TYPE_DISK)
784-
return _fstati64(fd, buf);
785-
786-
if (!get_file_info_by_handle(fh, buf))
787-
return 0;
788-
errno = EBADF;
789-
return -1;
790803
}
791804

792805
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
@@ -325,24 +325,49 @@ static inline long long filetime_to_hnsec(const FILETIME *ft)
325325
return winTime - 116444736000000000LL;
326326
}
327327

328-
static inline time_t filetime_to_time_t(const FILETIME *ft)
329-
{
330-
return (time_t)(filetime_to_hnsec(ft) / 10000000);
331-
}
332-
333328
/*
334-
* Use mingw specific stat()/lstat()/fstat() implementations on Windows.
329+
* Use mingw specific stat()/lstat()/fstat() implementations on Windows,
330+
* including our own struct stat with 64 bit st_size and nanosecond-precision
331+
* file times.
335332
*/
336333
#ifndef __MINGW64_VERSION_MAJOR
337334
#define off_t off64_t
338335
#define lseek _lseeki64
336+
struct timespec {
337+
time_t tv_sec;
338+
long tv_nsec;
339+
};
339340
#endif
340341

341-
/* use struct stat with 64 bit st_size */
342+
static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
343+
{
344+
long long hnsec = filetime_to_hnsec(ft);
345+
ts->tv_sec = (time_t)(hnsec / 10000000);
346+
ts->tv_nsec = (hnsec % 10000000) * 100;
347+
}
348+
349+
struct mingw_stat {
350+
_dev_t st_dev;
351+
_ino_t st_ino;
352+
_mode_t st_mode;
353+
short st_nlink;
354+
short st_uid;
355+
short st_gid;
356+
_dev_t st_rdev;
357+
off64_t st_size;
358+
struct timespec st_atim;
359+
struct timespec st_mtim;
360+
struct timespec st_ctim;
361+
};
362+
363+
#define st_atime st_atim.tv_sec
364+
#define st_mtime st_mtim.tv_sec
365+
#define st_ctime st_ctim.tv_sec
366+
342367
#ifdef stat
343368
#undef stat
344369
#endif
345-
#define stat _stati64
370+
#define stat mingw_stat
346371
int mingw_lstat(const char *file_name, struct stat *buf);
347372
int mingw_stat(const char *file_name, struct stat *buf);
348373
int mingw_fstat(int fd, struct stat *buf);
@@ -355,13 +380,6 @@ int mingw_fstat(int fd, struct stat *buf);
355380
#endif
356381
extern int (*lstat)(const char *file_name, struct stat *buf);
357382

358-
#ifndef _stati64
359-
# define _stati64(x,y) mingw_stat(x,y)
360-
#elif defined (_USE_32BIT_TIME_T)
361-
# define _stat32i64(x,y) mingw_stat(x,y)
362-
#else
363-
# define _stat64(x,y) mingw_stat(x,y)
364-
#endif
365383

366384
int mingw_utime(const char *file_name, const struct utimbuf *times);
367385
#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
};
@@ -151,9 +151,9 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
151151
fdata->dwReserved0);
152152
fse->st_size = S_ISLNK(fse->st_mode) ? MAX_LONG_PATH :
153153
fdata->nFileSizeLow | (((off_t) fdata->nFileSizeHigh) << 32);
154-
fse->st_atime = filetime_to_time_t(&(fdata->ftLastAccessTime));
155-
fse->st_mtime = filetime_to_time_t(&(fdata->ftLastWriteTime));
156-
fse->st_ctime = filetime_to_time_t(&(fdata->ftCreationTime));
154+
filetime_to_timespec(&(fdata->ftLastAccessTime), &(fse->st_atim));
155+
filetime_to_timespec(&(fdata->ftLastWriteTime), &(fse->st_mtim));
156+
filetime_to_timespec(&(fdata->ftCreationTime), &(fse->st_ctim));
157157

158158
return fse;
159159
}
@@ -432,9 +432,9 @@ int fscache_lstat(const char *filename, struct stat *st)
432432
st->st_nlink = 1;
433433
st->st_mode = fse->st_mode;
434434
st->st_size = fse->st_size;
435-
st->st_atime = fse->st_atime;
436-
st->st_mtime = fse->st_mtime;
437-
st->st_ctime = fse->st_ctime;
435+
st->st_atim = fse->st_atim;
436+
st->st_mtim = fse->st_mtim;
437+
st->st_ctim = fse->st_ctim;
438438

439439
/* don't forget to release fsentry */
440440
fsentry_release(fse);

config.mak.uname

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,6 @@ ifeq ($(uname_S),Windows)
355355
NO_SVN_TESTS = YesPlease
356356
RUNTIME_PREFIX = YesPlease
357357
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
358-
NO_NSEC = YesPlease
359358
USE_WIN32_MMAP = YesPlease
360359
# USE_NED_ALLOCATOR = YesPlease
361360
UNRELIABLE_FSTAT = UnfortunatelyYes
@@ -505,7 +504,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))
505504
NO_SVN_TESTS = YesPlease
506505
RUNTIME_PREFIX = YesPlease
507506
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
508-
NO_NSEC = YesPlease
509507
USE_WIN32_MMAP = YesPlease
510508
USE_NED_ALLOCATOR = YesPlease
511509
UNRELIABLE_FSTAT = UnfortunatelyYes

0 commit comments

Comments
 (0)