diff --git a/compat/mingw.c b/compat/mingw.c
index 1724518dd26168..aa5c54946cb860 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -698,9 +698,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:
@@ -745,9 +745,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;
 }
 
@@ -775,18 +775,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);
-	if (fh == INVALID_HANDLE_VALUE) {
+	DWORD avail, type = GetFileType(fh) & ~FILE_TYPE_REMOTE;
+
+	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 (!get_file_info_by_handle(fh, buf))
-		return 0;
-	errno = EBADF;
-	return -1;
 }
 
 static inline void time_t_to_filetime(time_t t, FILETIME *ft)
diff --git a/compat/mingw.h b/compat/mingw.h
index ecf6387cabb7ae..11637ab6259745 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -325,24 +325,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);
@@ -355,13 +380,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
diff --git a/compat/win32/fscache.c b/compat/win32/fscache.c
index b7caf2a02fcd33..846df4fcafff50 100644
--- a/compat/win32/fscache.c
+++ b/compat/win32/fscache.c
@@ -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;
 		};
 	};
 };
@@ -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;
 }
@@ -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);
diff --git a/config.mak.uname b/config.mak.uname
index fa8d3c6157418f..ebc3c802472e98 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -355,7 +355,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
@@ -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