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

Reply via email to