win32: define our own POSIX struct stat, and support USE_NSEC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a72659d..0c9c356 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -87,7 +87,7 @@ ENDIF()
CHECK_STRUCT_HAS_MEMBER("struct stat" st_mtim.tv_nsec sys/stat.h
HAVE_STRUCT_STAT_NSEC LANGUAGE C)
-IF(HAVE_STRUCT_STAT_NSEC)
+IF(HAVE_STRUCT_STAT_NSEC OR WIN32)
OPTION( USE_NSEC "Care about sub-second file mtimes and ctimes" OFF )
ENDIF()
diff --git a/src/common.h b/src/common.h
index 6dca36f..c87343d 100644
--- a/src/common.h
+++ b/src/common.h
@@ -41,6 +41,7 @@
# include <ws2tcpip.h>
# include "win32/msvc-compat.h"
# include "win32/mingw-compat.h"
+# include "win32/win32-compat.h"
# include "win32/error.h"
# include "win32/version.h"
# ifdef GIT_THREADS
diff --git a/src/win32/mingw-compat.h b/src/win32/mingw-compat.h
index a4a5a31..698ebed 100644
--- a/src/win32/mingw-compat.h
+++ b/src/win32/mingw-compat.h
@@ -11,12 +11,6 @@
#undef stat
-#if _WIN32_WINNT >= 0x0601
-#define stat __stat64
-#else
-#define stat _stati64
-#endif
-
#if _WIN32_WINNT < 0x0600 && !defined(__MINGW64_VERSION_MAJOR)
#undef MemoryBarrier
void __mingworg_MemoryBarrier(void);
diff --git a/src/win32/msvc-compat.h b/src/win32/msvc-compat.h
index 8004bc1..12b50d9 100644
--- a/src/win32/msvc-compat.h
+++ b/src/win32/msvc-compat.h
@@ -9,9 +9,6 @@
#if defined(_MSC_VER)
-/* 64-bit stat information, regardless of USE_32BIT_TIME_T define */
-#define stat __stat64
-
typedef unsigned short mode_t;
typedef SSIZE_T ssize_t;
diff --git a/src/win32/w32_util.h b/src/win32/w32_util.h
index 8db3afb..727ed1c 100644
--- a/src/win32/w32_util.h
+++ b/src/win32/w32_util.h
@@ -76,17 +76,23 @@ size_t git_win32__path_trim_end(wchar_t *str, size_t len);
size_t git_win32__canonicalize_path(wchar_t *str, size_t len);
/**
- * Converts a FILETIME structure to a time_t.
+ * Converts a FILETIME structure to a struct timespec.
*
* @param FILETIME A pointer to a FILETIME
- * @return A time_t containing the same time
+ * @param ts A pointer to the timespec structure to fill in
*/
-GIT_INLINE(time_t) git_win32__filetime_to_time_t(const FILETIME *ft)
+GIT_INLINE(void) git_win32__filetime_to_timespec(
+ const FILETIME *ft,
+ struct timespec *ts)
{
long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
- winTime /= 10000000; /* Nano to seconds resolution */
- return (time_t)winTime;
+ ts->tv_sec = (time_t)(winTime / 10000000);
+#ifdef GIT_USE_NSEC
+ ts->tv_nsec = (winTime % 10000000) * 100;
+#else
+ ts->tv_nsec = 0;
+#endif
}
GIT_INLINE(void) git_win32__timeval_to_filetime(
@@ -122,9 +128,9 @@ GIT_INLINE(int) git_win32__file_attribute_to_stat(
st->st_size = ((git_off_t)attrdata->nFileSizeHigh << 32) + attrdata->nFileSizeLow;
st->st_dev = _getdrive() - 1;
st->st_rdev = st->st_dev;
- st->st_atime = git_win32__filetime_to_time_t(&(attrdata->ftLastAccessTime));
- st->st_mtime = git_win32__filetime_to_time_t(&(attrdata->ftLastWriteTime));
- st->st_ctime = git_win32__filetime_to_time_t(&(attrdata->ftCreationTime));
+ git_win32__filetime_to_timespec(&(attrdata->ftLastAccessTime), &(st->st_atim));
+ git_win32__filetime_to_timespec(&(attrdata->ftLastWriteTime), &(st->st_mtim));
+ git_win32__filetime_to_timespec(&(attrdata->ftCreationTime), &(st->st_ctim));
if (attrdata->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && path) {
git_win32_path target;
diff --git a/src/win32/win32-compat.h b/src/win32/win32-compat.h
new file mode 100644
index 0000000..8b4070d
--- /dev/null
+++ b/src/win32/win32-compat.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_win32_compat__
+#define INCLUDE_win32_compat__
+
+#include <stdint.h>
+#include <time.h>
+#include <wchar.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+struct p_timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+
+#define timespec p_timespec
+
+struct p_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;
+ uint64_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
+};
+
+#define stat p_stat
+
+#endif /* INCLUDE_win32_compat__ */