> * 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 <br...@clisp.org> 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. +@item 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 -@item -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