]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add C11 localtime_r and gmtime_r shims for Windows
authorOndřej Surý <ondrej@isc.org>
Fri, 13 Mar 2020 07:38:37 +0000 (08:38 +0100)
committerEvan Hunt <each@isc.org>
Tue, 17 Mar 2020 20:28:15 +0000 (13:28 -0700)
On Windows, C11 localtime_r() and gmtime_r() functions are not
available.  While localtime() and gmtime() functions are already thread
safe because they use Thread Local Storage, it's quite ugly to #ifdef
around every localtime_r() and gmtime_r() usage to make the usage also
thread-safe on POSIX platforms.

The commit adds wrappers around Windows localtime_s() and gmtime_s()
functions.

NOTE: The implementation of localtime_s and gmtime_s in Microsoft CRT
are incompatible with the C standard since it has reversed parameter
order and errno_t return type.

bin/dig/dig.c
bin/dnssec/dnssec-settime.c
bin/dnssec/dnssec-signzone.c
lib/dns/gen-win32.h
lib/dns/gen.c
lib/dns/update.c
lib/isc/win32/include/isc/time.h

index 92c0f826c725775edb1f0f7bd842715da87720de..cd0127518123189c752dfddee24dcf5bb9e5d5c5 100644 (file)
@@ -337,11 +337,7 @@ received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) {
                }
                printf(";; SERVER: %s(%s)\n", fromtext, query->servname);
                time(&tnow);
-#if !defined(WIN32)
                (void)localtime_r(&tnow, &tmnow);
-#else  /* if !defined(WIN32) */
-               tmnow = *localtime(&tnow);
-#endif /* if !defined(WIN32) */
 
 #ifdef WIN32
                /*
index 041d1ca3025ee3eb523a4839ca7214a30d173fad..01d37186e1c46d08460413f19933a1a93dabf723 100644 (file)
@@ -127,15 +127,16 @@ printtime(dst_key_t *key, int type, const char *tag, bool epoch, FILE *stream) {
        } else if (epoch) {
                fprintf(stream, "%d\n", (int)when);
        } else {
-               time_t now = (time_t)when;
-#ifdef _MSC_VER
-               struct tm *tm = localtime(&now); /* Thread specific. */
-#else
+               time_t now = when;
                struct tm t, *tm = localtime_r(&now, &t);
-#endif
                unsigned int flen;
                char timebuf[80];
 
+               if (tm == NULL) {
+                       fprintf(stream, "INVALID\n");
+                       return;
+               }
+
                flen = strftime(timebuf, sizeof(timebuf),
                                "%a %b %e %H:%M:%S %Y", tm);
                INSIST(flen > 0U && flen < sizeof(timebuf));
index 325af98c1e7965139100ecd8015f8b2af6b77a12..4c5d28221d275cb9907512e90fe0f49854a6b756 100644 (file)
@@ -3106,15 +3106,11 @@ writeset(const char *prefix, dns_rdatatype_t type) {
 static void
 print_time(FILE *fp) {
        time_t currenttime = time(NULL);
-#ifdef _MSC_VER
-       struct tm *tm = localtime(&currenttime); /* Thread specific. */
-#else
        struct tm t, *tm = localtime_r(&currenttime, &t);
-#endif
        unsigned int flen;
        char timebuf[80];
 
-       if (outputformat != dns_masterformat_text) {
+       if (tm == NULL || outputformat != dns_masterformat_text) {
                return;
        }
 
index 6d3cdf2e3e0b0bd18a5919ed731f06be1627bd8b..31188558a86d70ae0043fa5b009cd58d81ead1be 100644 (file)
@@ -62,6 +62,7 @@
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
+#include <time.h>
 #include <windows.h>
 
 #include <isc/lang.h>
@@ -277,6 +278,16 @@ end_directory(isc_dir_t *dir) {
        }
 }
 
+inline struct tm *
+gmtime_r(const time_t *clock, struct tm *result) {
+       errno_t ret = gmtime_s(result, clock);
+       if (ret != 0) {
+               errno = ret;
+               return (NULL);
+       }
+       return (result);
+}
+
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_GEN_WIN32_H */
index 2e31c61177574a4db9238cfd640b082ac6777292..b922e0df9c4dd386618394240914c14a88941d74 100644 (file)
@@ -700,11 +700,7 @@ main(int argc, char **argv) {
        }
 
        if (now != -1) {
-#ifdef _MSC_VER
-               struct tm *tm = gmtime(&now); /* Thread specific. */
-#else
                struct tm t, *tm = gmtime_r(&now, &t);
-#endif
 
                if (tm != NULL && tm->tm_year > 104) {
                        n = snprintf(year, sizeof(year), "-%d",
index 6ba2fbd53a4edca329daea6b528fbb765e18adac..e2a062e0c3e6a586a8fd0ad71c8666627481976e 100644 (file)
@@ -2191,14 +2191,10 @@ failure:
 
 static isc_stdtime_t
 epoch_to_yyyymmdd(time_t when) {
-       struct tm *tm;
-
-#if !defined(WIN32)
-       struct tm tm0;
-       tm = localtime_r(&when, &tm0);
-#else  /* if !defined(WIN32) */
-       tm = localtime(&when);
-#endif /* if !defined(WIN32) */
+       struct tm t, *tm = localtime_r(&when, &t);
+       if (tm == NULL) {
+               return (0);
+       }
        return (((tm->tm_year + 1900) * 10000) + ((tm->tm_mon + 1) * 100) +
                tm->tm_mday);
 }
index 7745e548745853588f9adad210aeb3906eb2a1cf..f49c3a774ce94a3dc6df6000206344a537cb0d6d 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef ISC_TIME_H
 #define ISC_TIME_H 1
 
+#include <errno.h>
 #include <inttypes.h>
 #include <stdbool.h>
 #include <windows.h>
 #include <isc/lang.h>
 #include <isc/types.h>
 
+/***
+ *** POSIX Shims
+ ***/
+
+inline struct tm *
+gmtime_r(const time_t *clock, struct tm *result) {
+       errno_t ret = gmtime_s(result, clock);
+       if (ret != 0) {
+               errno = ret;
+               return (NULL);
+       }
+       return (result);
+}
+
+inline struct tm *
+localtime_r(const time_t *clock, struct tm *result) {
+       errno_t ret = localtime_s(result, clock);
+       if (ret != 0) {
+               errno = ret;
+               return (NULL);
+       }
+       return (result);
+}
+
 /***
  *** Intervals
  ***/