bug-gnulib
[Top][All Lists]
Advanced

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

[PATCH 4/6] time_rz: port to Solaris etc.


From: Paul Eggert
Subject: [PATCH 4/6] time_rz: port to Solaris etc.
Date: Sat, 25 Jul 2015 18:21:56 -0700

Works around a tzname problem on platforms like Solaris that have
tzname but not tm_zone, by setting tzname at the appropriate time
and restoring it later.
* lib/time_rz.c (tzname_address, tzname_value) [HAVE_TZNAME]:
New static vars.
(save_abbr) [HAVE_TZNAME]: Set them.
(revert_tz) [HAVE_TZNAME]: Clear or use them.
(restore_tzname): New function.
(localtime_rz, mktime_z): Use it.
---
 ChangeLog     | 11 +++++++++++
 lib/time_rz.c | 44 +++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a803c15..5d8c1b1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2015-07-25  Paul Eggert  <address@hidden>
 
+       time_rz: port to Solaris etc.
+       Works around a tzname problem on platforms like Solaris that have
+       tzname but not tm_zone, by setting tzname at the appropriate time
+       and restoring it later.
+       * lib/time_rz.c (tzname_address, tzname_value) [HAVE_TZNAME]:
+       New static vars.
+       (save_abbr) [HAVE_TZNAME]: Set them.
+       (revert_tz) [HAVE_TZNAME]: Clear or use them.
+       (restore_tzname): New function.
+       (localtime_rz, mktime_z): Use it.
+
        time_rz: now LGPL
        * modules/time_rz (License): Now LGPL, because strftime depends on it.
 
diff --git a/lib/time_rz.c b/lib/time_rz.c
index 55b9122..142b2a1 100644
--- a/lib/time_rz.c
+++ b/lib/time_rz.c
@@ -130,8 +130,19 @@ tzalloc (char const *name)
   return tz;
 }
 
+#if HAVE_TZNAME
+/* If TZNAME_ADDRESS is nonnull, an assignment of a saved abbreviation.
+   TZNAME_ADDRESS should be either null, or &tzname[0], or &tzname[1].
+   *TZNAME_ADDRESS = TZNAME_VALUE should be done after revert_tz
+   (indirectly) calls tzset, so that revert_tz can overwrite tzset's
+   assignment to tzname.  Also, it should be done at the start of
+   the next localtime_tz or mktime_z, to undo the overwrite.  */
+static char **tzname_address;
+static char *tzname_value;
+#endif
+
 /* Save into TZ any nontrivial time zone abbreviation used by TM,
-   and update *TM or tzname if they point to the abbreviation.
+   and update *TM (or prepare to update tzname) if they use the abbreviation.
    Return true if successful, false (setting errno) otherwise.  */
 static bool
 save_abbr (timezone_t tz, struct tm *tm)
@@ -189,8 +200,8 @@ save_abbr (timezone_t tz, struct tm *tm)
     tm->tm_zone = zone_copy;
 # endif
 # if HAVE_TZNAME
-  if (tzname_zone)
-    *tzname_zone = zone_copy;
+  tzname_address = tzname_zone;
+  tzname_value = zone_copy;
 # endif
 #endif
   return true;
@@ -281,16 +292,41 @@ revert_tz (timezone_t tz)
       bool ok = change_env (tz);
       if (!ok)
         saved_errno = errno;
+#if HAVE_TZNAME
+      if (!ok)
+        tzname_address = NULL;
+      if (tzname_address)
+        {
+          char *old_value = *tzname_address;
+          *tzname_address = tzname_value;
+          tzname_value = old_value;
+        }
+#endif
       tzfree (tz);
       errno = saved_errno;
       return ok;
     }
 }
 
+/* Restore an old tzname setting that was temporarily munged by revert_tz.  */
+static void
+restore_tzname (void)
+{
+#if HAVE_TZNAME
+  if (tzname_address)
+    {
+      *tzname_address = tzname_value;
+      tzname_address = NULL;
+    }
+#endif
+}
+
 /* Use time zone TZ to compute localtime_r (T, TM).  */
 struct tm *
 localtime_rz (timezone_t tz, time_t const *t, struct tm *tm)
 {
+  restore_tzname ();
+
   if (!tz)
     return gmtime_r (t, tm);
   else
@@ -312,6 +348,8 @@ localtime_rz (timezone_t tz, time_t const *t, struct tm *tm)
 time_t
 mktime_z (timezone_t tz, struct tm *tm)
 {
+  restore_tzname ();
+
   if (!tz)
     return timegm (tm);
   else
-- 
2.1.0




reply via email to

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