bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

tzset: add native Windows workaround


From: Bruno Haible
Subject: tzset: add native Windows workaround
Date: Mon, 01 May 2017 18:40:53 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-75-generic; KDE/5.18.0; x86_64; ; )

> * Some which should obey TZ, just that they should ignore the values set by
>   Cygwin (instead of exhibiting garbage behaviour):
> 
>   _tzset
>   https://msdn.microsoft.com/en-us/library/aa273389.aspx
>   https://msdn.microsoft.com/en-us/library/90s5c885.aspx
>   http://pubs.opengroup.org/onlinepubs/9699919799/functions/tzset.html

Here's the workaround for 'tzset'.


2017-05-01  Bruno Haible  <address@hidden>

        tzset: Work around TZ problem on native Windows.
        * m4/tzset.m4 (gl_FUNC_TZSET): Require AC_CANONICAL_HOST. On native
        Windows, set REPLACE_TZSET to 1.
        * lib/tzset.c (tzset): On native Windows, fix TZ if necessary, and
        invoke '_tzset' instead of 'tzset'.
        * doc/posix-functions/tzset.texi: Mention the native Windows workaround.

        * modules/time_rz (Depends-on): Add tzset.
        * lib/time_rz.c (tzset): Remove fallback definition.
        * m4/time_rz.m4 (gl_TIME_RZ): Don't test for tzset.

diff --git a/doc/posix-functions/tzset.texi b/doc/posix-functions/tzset.texi
index 30b147c..a457409 100644
--- a/doc/posix-functions/tzset.texi
+++ b/doc/posix-functions/tzset.texi
@@ -9,6 +9,9 @@ Gnulib module: tzset
 Portability problems fixed by Gnulib:
 @itemize
 @item
+On native Windows platforms (mingw, MSVC), this function works incorrectly
+when the environment variable @code{TZ} has been set by Cygwin.
address@hidden
 This function clobbers the buffer used by the localtime function on some
 platforms:
 Solaris 2.6.
@@ -16,7 +19,4 @@ Solaris 2.6.
 
 Portability problems not fixed by Gnulib:
 @itemize
address@hidden
-On native Windows platforms (mingw, MSVC), this function works incorrectly
-when the environment variable @code{TZ} has been set by Cygwin.
 @end itemize
diff --git a/lib/tzset.c b/lib/tzset.c
index 1cb9822..ce854b9 100644
--- a/lib/tzset.c
+++ b/lib/tzset.c
@@ -40,7 +40,23 @@ tzset (void)
   struct tm save = *localtime_buffer_addr;
 #endif
 
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+  /* If the environment variable TZ has been set by Cygwin, neutralize it.
+     The Microsoft CRT interprets TZ differently than Cygwin and produces
+     incorrect results if TZ has the syntax used by Cygwin.  */
+  const char *tz = getenv ("TZ");
+  if (tz != NULL && strchr (tz, '/') != NULL)
+    _putenv ("TZ=");
+
+  /* On native Windows, tzset() is deprecated.  Use _tzset() instead.  See
+     https://msdn.microsoft.com/en-us/library/ms235451.aspx
+     https://msdn.microsoft.com/en-us/library/90s5c885.aspx  */
+  _tzset ();
+#elif HAVE_TZSET
   tzset ();
+#else
+  /* Do nothing.  Avoid infinite recursion.  */
+#endif
 
 #if TZSET_CLOBBERS_LOCALTIME
   *localtime_buffer_addr = save;
diff --git a/m4/tzset.m4 b/m4/tzset.m4
index 20939e9..08362fe 100644
--- a/m4/tzset.m4
+++ b/m4/tzset.m4
@@ -17,11 +17,13 @@ AC_DEFUN([gl_FUNC_TZSET],
 [
   AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS])
   AC_REQUIRE([gl_LOCALTIME_BUFFER_DEFAULTS])
+  AC_REQUIRE([AC_CANONICAL_HOST])
   AC_CHECK_FUNCS_ONCE([tzset])
   if test $ac_cv_func_tzset = no; then
     HAVE_TZSET=0
   fi
   gl_FUNC_TZSET_CLOBBER
+  REPLACE_TZSET=0
   case "$gl_cv_func_tzset_clobber" in
     *yes)
       REPLACE_TZSET=1
@@ -29,9 +31,9 @@ AC_DEFUN([gl_FUNC_TZSET],
         [Define if tzset clobbers localtime's static buffer.])
       gl_LOCALTIME_BUFFER_NEEDED
       ;;
-    *)
-      REPLACE_TZSET=0
-      ;;
+  esac
+  case "$host_os" in
+    mingw*) REPLACE_TZSET=1 ;;
   esac
 ])
 
diff --git a/modules/time_rz b/modules/time_rz
index e934d55..1bc29f4 100644
--- a/modules/time_rz
+++ b/modules/time_rz
@@ -24,6 +24,7 @@ setenv         [test "$HAVE_TIMEZONE_T" = 0]
 stdbool        [test "$HAVE_TIMEZONE_T" = 0]
 time_r         [test "$HAVE_TIMEZONE_T" = 0]
 timegm         [test "$HAVE_TIMEZONE_T" = 0]
+tzset          [test "$HAVE_TIMEZONE_T" = 0]
 unsetenv       [test "$HAVE_TIMEZONE_T" = 0]
 
 configure.ac:
diff --git a/lib/time_rz.c b/lib/time_rz.c
index 82f3f3f..95c7293 100644
--- a/lib/time_rz.c
+++ b/lib/time_rz.c
@@ -40,10 +40,6 @@
 # define SIZE_MAX ((size_t) -1)
 #endif
 
-#if !HAVE_TZSET
-static void tzset (void) { }
-#endif
-
 /* The approximate size to use for small allocation requests.  This is
    the largest "small" request for the GNU C library malloc.  */
 enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
diff --git a/m4/time_rz.m4 b/m4/time_rz.m4
index 79060e0..079e933 100644
--- a/m4/time_rz.m4
+++ b/m4/time_rz.m4
@@ -12,7 +12,6 @@ AC_DEFUN([gl_TIME_RZ],
   AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
   AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS])
   AC_REQUIRE([AC_STRUCT_TIMEZONE])
-  AC_CHECK_FUNCS_ONCE([tzset])
 
   AC_CHECK_TYPES([timezone_t], [], [], [[#include <time.h>]])
   if test "$ac_cv_type_timezone_t" = yes; then




reply via email to

[Prev in Thread] Current Thread [Next in Thread]