2015-07-25 Paul Eggert <eggert@cs.ucla.edu>
+ 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.
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)
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;
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
time_t
mktime_z (timezone_t tz, struct tm *tm)
{
+ restore_tzname ();
+
if (!tz)
return timegm (tm);
else