Skip to content

Commit

Permalink
Win32: implement nanosecond-precision file times
Browse files Browse the repository at this point in the history
We no longer use any of MSVCRT's stat-functions, so there's no need to
stick to a CRT-compatible 'struct stat' either.

Define and use our own POSIX-2013-compatible 'struct stat' with nanosecond-
precision file times.

Note: Due to performance issues when using git variants with different file
time resolutions, this patch does *not* yet enable nanosecond precision in
the Makefile (use 'make USE_NSEC=1').

Signed-off-by: Karsten Blees <[email protected]>
  • Loading branch information
kblees authored and dscho committed Jun 9, 2016
1 parent 6b28f16 commit 804993e
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 32 deletions.
12 changes: 6 additions & 6 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -734,9 +734,9 @@ int mingw_lstat(const char *file_name, struct stat *buf)
buf->st_size = S_ISLNK(buf->st_mode) ? MAX_LONG_PATH :
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));
return 0;
}
error:
Expand Down Expand Up @@ -781,9 +781,9 @@ static int get_file_info_by_handle(HANDLE hnd, struct stat *buf)
buf->st_nlink = 1;
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes, 0);
buf->st_size = fdata.nFileSizeLow | (((off_t) fdata.nFileSizeHigh) << 32);
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));
return 0;
}

Expand Down
48 changes: 33 additions & 15 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,24 +332,49 @@ static inline long long filetime_to_hnsec(const FILETIME *ft)
return winTime - 116444736000000000LL;
}

static inline time_t filetime_to_time_t(const FILETIME *ft)
{
return (time_t)(filetime_to_hnsec(ft) / 10000000);
}

/*
* 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 */
static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
{
long long hnsec = filetime_to_hnsec(ft);
ts->tv_sec = (time_t)(hnsec / 10000000);
ts->tv_nsec = (hnsec % 10000000) * 100;
}

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 @@ -362,13 +387,6 @@ int mingw_fstat(int fd, struct stat *buf);
#endif
extern int (*lstat)(const char *file_name, struct stat *buf);

#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
18 changes: 9 additions & 9 deletions compat/win32/fscache.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ struct fsentry {
struct {
/* More stat members (only used for file entries). */
off64_t st_size;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
struct timespec st_atim;
struct timespec st_mtim;
struct timespec st_ctim;
};
};
};
Expand Down Expand Up @@ -151,9 +151,9 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
fdata->dwReserved0);
fse->st_size = S_ISLNK(fse->st_mode) ? MAX_LONG_PATH :
fdata->nFileSizeLow | (((off_t) fdata->nFileSizeHigh) << 32);
fse->st_atime = filetime_to_time_t(&(fdata->ftLastAccessTime));
fse->st_mtime = filetime_to_time_t(&(fdata->ftLastWriteTime));
fse->st_ctime = filetime_to_time_t(&(fdata->ftCreationTime));
filetime_to_timespec(&(fdata->ftLastAccessTime), &(fse->st_atim));
filetime_to_timespec(&(fdata->ftLastWriteTime), &(fse->st_mtim));
filetime_to_timespec(&(fdata->ftCreationTime), &(fse->st_ctim));

return fse;
}
Expand Down Expand Up @@ -432,9 +432,9 @@ int fscache_lstat(const char *filename, struct stat *st)
st->st_nlink = 1;
st->st_mode = fse->st_mode;
st->st_size = fse->st_size;
st->st_atime = fse->st_atime;
st->st_mtime = fse->st_mtime;
st->st_ctime = fse->st_ctime;
st->st_atim = fse->st_atim;
st->st_mtim = fse->st_mtim;
st->st_ctim = fse->st_ctim;

/* don't forget to release fsentry */
fsentry_release(fse);
Expand Down
2 changes: 0 additions & 2 deletions config.mak.uname
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,6 @@ ifeq ($(uname_S),Windows)
NO_SVN_TESTS = YesPlease
RUNTIME_PREFIX = YesPlease
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
NO_NSEC = YesPlease
USE_WIN32_MMAP = YesPlease
# USE_NED_ALLOCATOR = YesPlease
UNRELIABLE_FSTAT = UnfortunatelyYes
Expand Down Expand Up @@ -506,7 +505,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_SVN_TESTS = YesPlease
RUNTIME_PREFIX = YesPlease
NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
NO_NSEC = YesPlease
USE_WIN32_MMAP = YesPlease
USE_NED_ALLOCATOR = YesPlease
UNRELIABLE_FSTAT = UnfortunatelyYes
Expand Down

0 comments on commit 804993e

Please sign in to comment.