comparison lib/time_rz.c @ 18065:fd4663ad7454

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.
author Paul Eggert <eggert@cs.ucla.edu>
date Sat, 25 Jul 2015 15:20:10 -0700
parents 29e0bb74097d
children 1c6c8e9218c9
comparison
equal deleted inserted replaced
18064:e848c8248a0b 18065:fd4663ad7454
128 extend_abbrs (tz->abbrs, name, name_size); 128 extend_abbrs (tz->abbrs, name, name_size);
129 } 129 }
130 return tz; 130 return tz;
131 } 131 }
132 132
133 #if HAVE_TZNAME
134 /* If TZNAME_ADDRESS is nonnull, an assignment of a saved abbreviation.
135 TZNAME_ADDRESS should be either null, or &tzname[0], or &tzname[1].
136 *TZNAME_ADDRESS = TZNAME_VALUE should be done after revert_tz
137 (indirectly) calls tzset, so that revert_tz can overwrite tzset's
138 assignment to tzname. Also, it should be done at the start of
139 the next localtime_tz or mktime_z, to undo the overwrite. */
140 static char **tzname_address;
141 static char *tzname_value;
142 #endif
143
133 /* Save into TZ any nontrivial time zone abbreviation used by TM, 144 /* Save into TZ any nontrivial time zone abbreviation used by TM,
134 and update *TM or tzname if they point to the abbreviation. 145 and update *TM (or prepare to update tzname) if they use the abbreviation.
135 Return true if successful, false (setting errno) otherwise. */ 146 Return true if successful, false (setting errno) otherwise. */
136 static bool 147 static bool
137 save_abbr (timezone_t tz, struct tm *tm) 148 save_abbr (timezone_t tz, struct tm *tm)
138 { 149 {
139 #if HAVE_TM_ZONE || HAVE_TZNAME 150 #if HAVE_TM_ZONE || HAVE_TZNAME
187 # if HAVE_TM_ZONE 198 # if HAVE_TM_ZONE
188 if (!tzname_zone) 199 if (!tzname_zone)
189 tm->tm_zone = zone_copy; 200 tm->tm_zone = zone_copy;
190 # endif 201 # endif
191 # if HAVE_TZNAME 202 # if HAVE_TZNAME
192 if (tzname_zone) 203 tzname_address = tzname_zone;
193 *tzname_zone = zone_copy; 204 tzname_value = zone_copy;
194 # endif 205 # endif
195 #endif 206 #endif
196 return true; 207 return true;
197 } 208 }
198 209
279 { 290 {
280 int saved_errno = errno; 291 int saved_errno = errno;
281 bool ok = change_env (tz); 292 bool ok = change_env (tz);
282 if (!ok) 293 if (!ok)
283 saved_errno = errno; 294 saved_errno = errno;
295 #if HAVE_TZNAME
296 if (!ok)
297 tzname_address = NULL;
298 if (tzname_address)
299 {
300 char *old_value = *tzname_address;
301 *tzname_address = tzname_value;
302 tzname_value = old_value;
303 }
304 #endif
284 tzfree (tz); 305 tzfree (tz);
285 errno = saved_errno; 306 errno = saved_errno;
286 return ok; 307 return ok;
287 } 308 }
288 } 309 }
289 310
311 /* Restore an old tzname setting that was temporarily munged by revert_tz. */
312 static void
313 restore_tzname (void)
314 {
315 #if HAVE_TZNAME
316 if (tzname_address)
317 {
318 *tzname_address = tzname_value;
319 tzname_address = NULL;
320 }
321 #endif
322 }
323
290 /* Use time zone TZ to compute localtime_r (T, TM). */ 324 /* Use time zone TZ to compute localtime_r (T, TM). */
291 struct tm * 325 struct tm *
292 localtime_rz (timezone_t tz, time_t const *t, struct tm *tm) 326 localtime_rz (timezone_t tz, time_t const *t, struct tm *tm)
293 { 327 {
328 restore_tzname ();
329
294 if (!tz) 330 if (!tz)
295 return gmtime_r (t, tm); 331 return gmtime_r (t, tm);
296 else 332 else
297 { 333 {
298 timezone_t old_tz = set_tz (tz); 334 timezone_t old_tz = set_tz (tz);
310 346
311 /* Use time zone TZ to compute mktime (TM). */ 347 /* Use time zone TZ to compute mktime (TM). */
312 time_t 348 time_t
313 mktime_z (timezone_t tz, struct tm *tm) 349 mktime_z (timezone_t tz, struct tm *tm)
314 { 350 {
351 restore_tzname ();
352
315 if (!tz) 353 if (!tz)
316 return timegm (tm); 354 return timegm (tm);
317 else 355 else
318 { 356 {
319 timezone_t old_tz = set_tz (tz); 357 timezone_t old_tz = set_tz (tz);