Function _mktime64 is available since msvcr70.dll. For older msvcrt
versions provide mingw-w64 emulation via musl libc __tm_to_secs() function
with adjustment of _timezone and _dstbias variable variables, and
normalization via _localtime64() function which is now available in all
CRT import libraries (either as native symbols or as mingw-w64 emulation).
Adjustment of _dstbias needs to be done only when passed timestamp is
during the DST period which is detected by the _localtime64() function too.
---
mingw-w64-crt/Makefile.am | 2 +
mingw-w64-crt/lib-common/msvcrt.def.in | 2 +-
mingw-w64-crt/misc/_mktime64.c | 60 ++++++++++++++++++++++++++
3 files changed, 63 insertions(+), 1 deletion(-)
create mode 100644 mingw-w64-crt/misc/_mktime64.c
diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index 0f8bf5ca559d..220a0e210e5b 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -587,6 +587,7 @@ src_msvcrt32=\
misc/_localtime64.c \
misc/_mkgmtime32.c \
misc/_mkgmtime64.c \
+ misc/_mktime64.c \
misc/_set_doserrno.c \
misc/_set_fmode.c \
misc/_time64.c \
@@ -902,6 +903,7 @@ src_pre_msvcr70=\
misc/_futime64.c \
misc/_gmtime64.c \
misc/_localtime64.c \
+ misc/_mktime64.c \
misc/_time64.c \
misc/_utime64.c \
misc/_wctime64.c \
diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in
b/mingw-w64-crt/lib-common/msvcrt.def.in
index 1578e250f4a5..d90796a70e07 100644
--- a/mingw-w64-crt/lib-common/msvcrt.def.in
+++ b/mingw-w64-crt/lib-common/msvcrt.def.in
@@ -1158,7 +1158,7 @@ F_NON_I386(_ftime64) ; i386 _ftime64 replaced by emu
F_NON_I386(_futime64) ; i386 _futime64 replaced by emu
F_NON_I386(_gmtime64) ; i386 _gmtime64 replaced by emu
F_NON_I386(_localtime64) ; i386 _localtime64 replaced by emu
-_mktime64
+F_NON_I386(_mktime64) ; i386 _mktime64 replaced by emu
F_X86_ANY(_osplatform DATA)
F_NON_I386(_stat64) ; i386 _stat64 replaced by emu
F_NON_I386(_time64) ; i386 _time64 replaced by emu
diff --git a/mingw-w64-crt/misc/_mktime64.c b/mingw-w64-crt/misc/_mktime64.c
new file mode 100644
index 000000000000..924e6635446d
--- /dev/null
+++ b/mingw-w64-crt/misc/_mktime64.c
@@ -0,0 +1,60 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <windows.h>
+#include <time.h>
+
+#include "__tm_to_secs.h"
+
+static __time64_t __cdecl emu__mktime64(struct tm *tmptr)
+{
+ __time64_t time64;
+ struct tm *tmptr2;
+ int tm_isdst;
+ long local_dstbias;
+ long local_timezone;
+
+ /* _tzset() initialize _daylight, _dstbias and _timezone variables,
+ * so it needs to be called before accessing those variables.
+ * If those variables are already initialized then _tzset() does
+ * not need to be called again. As _tzset() is an expensive call,
+ * guard repeated calls by static variable. As the _tzset() is a
+ * thread-safe call, the race condition is not a problem.
+ */
+ {
+ static volatile long tzset_called = 0;
+ if (!tzset_called) {
+ _tzset();
+ (void)InterlockedExchange(&tzset_called, 1);
+ }
+ }
+ local_dstbias = *__dstbias();
+ local_timezone = *__timezone();
+
+ tm_isdst = tmptr->tm_isdst;
+ time64 = __tm_to_secs(tmptr);
+ time64 += local_timezone;
+
+ tmptr2 = _localtime64(&time64);
+ if (!tmptr2)
+ return -1;
+
+ if (tm_isdst > 0 || (tm_isdst < 0 && tmptr2->tm_isdst > 0)) {
+ time64 += local_dstbias;
+ tmptr2 = _localtime64(&time64);
+ if (!tmptr2)
+ return -1;
+ }
+
+ *tmptr = *tmptr2;
+ return time64;
+}
+
+#define RETT __time64_t
+#define FUNC _mktime64
+#define ARGS struct tm *tmptr
+#define CALL tmptr
+#include "msvcrt_or_emu_glue.h"
--
2.20.1
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public