xref: /illumos-gate/usr/src/lib/libc/port/gen/localtime.c (revision d35c3d74c35b26ba5829798f51a44ce4d80d091b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
24  * Copyright 2025 Oxide Computer Company
25  */
26 
27 /*
28  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
29  * Use is subject to license terms.
30  */
31 
32 /*	Copyright (c) 1988 AT&T	*/
33 /*	  All Rights Reserved	*/
34 
35 /*
36  * A part of this file comes from public domain source, so
37  * clarified as of June 5, 1996 by Arthur David Olson
38  * (arthur_david_olson@nih.gov).
39  */
40 
41 /*
42  * localtime.c
43  *
44  * This file contains routines to convert struct tm to time_t and
45  * back as well as adjust time values based on their timezone, which
46  * is a local offset from GMT (Greenwich Mean Time).
47  *
48  * Many timezones actually consist of more than one offset from GMT.
49  * The GMT offset that is considered the normal offset is referred
50  * to as standard time.  The other offset is referred to as alternate
51  * time, but is better known as daylight savings time or summer time.
52  *
53  * The current timezone for an application is derived from the TZ
54  * environment variable either as defined in the environment or in
55  * /etc/default/init.  As defined by IEEE 1003.1-1990 (POSIX), the
56  * TZ variable can either be:
57  *    :<characters>
58  * or
59  *    <std><offset1>[<dst>[<offset2>]][,<start>[/<time>],<end>[/<time>]
60  *
61  * <characters> is an implementation-defined string that somehow describes
62  * a timezone.  The implementation-defined description of a timezone used
63  * in Solaris is based on the public domain zoneinfo code available from
64  * elsie.nci.nih.gov and a timezone that is specified in this way is
65  * referred to as a zoneinfo timezone.  An example of this is ":US/Pacific".
66  *
67  * The precise definition of the second format can be found in POSIX,
68  * but, basically, <std> is the abbreviation for the timezone in standard
69  * (not daylight savings time), <offset1> is the standard offset from GMT,
70  * <dst> is the abbreviation for the timezone in daylight savings time and
71  * <offset2> is the daylight savings time offset from GMT.  The remainder
72  * specifies when daylight savings time begins and ends.  A timezone
73  * specified in this way is referred to as a POSIX timezone.  An example
74  * of this is "PST7PDT".
75  *
76  * In Solaris, there is an extension to this.  If the timezone is not
77  * preceded by a ":" and it does not parse as a POSIX timezone, then it
78  * will be treated as a zoneinfo timezone.  Much usage of zoneinfo
79  * timezones in Solaris is done without the leading ":".
80  *
81  * A zoneinfo timezone is a reference to a file that contains a set of
82  * rules that describe the timezone.  In Solaris, the file is in
83  * /usr/share/lib/zoneinfo.  The file is generated by zic(8), based
84  * on zoneinfo rules "source" files.  This is all described on the zic(8)
85  * man page.
86  */
87 
88 /*
89  * Functions that are common to ctime(3C) and cftime(3C)
90  */
91 
92 #pragma weak _tzset = tzset
93 
94 #include "lint.h"
95 #include "libc.h"
96 #include "tsd.h"
97 #include <stdarg.h>
98 #include <mtlib.h>
99 #include <sys/types.h>
100 #include <ctype.h>
101 #include <stdio.h>
102 #include <limits.h>
103 #include <sys/param.h>
104 #include <time.h>
105 #include <unistd.h>
106 #include <stdlib.h>
107 #include <string.h>
108 #include <tzfile.h>
109 #include <thread.h>
110 #include <synch.h>
111 #include <fcntl.h>
112 #include <errno.h>
113 #include <deflt.h>
114 #include <sys/stat.h>
115 #include <sys/mman.h>
116 #include <stdbool.h>
117 
118 /* JAN_01_1902 cast to (int) - negative number of seconds from 1970 */
119 #define	JAN_01_1902		(int)0x8017E880
120 #define	LEN_TZDIR		(sizeof (TZDIR) - 1)
121 #define	TIMEZONE		"/etc/default/init"
122 #define	TZSTRING		"TZ="
123 #define	HASHTABLE		31
124 
125 #define	LEAPS_THRU_END_OF(y)	((y) / 4 - (y) / 100 + (y) / 400)
126 
127 /* Days since 1/1/70 to 12/31/(1900 + Y - 1) */
128 #define	DAYS_SINCE_70(Y) (YR((Y)-1L) - YR(70-1))
129 #define	YR(X) /* Calc # days since 0 A.D. X = curr. yr - 1900 */ \
130 	((1900L + (X)) * 365L + (1900L + (X)) / 4L - \
131 	(1900L + (X)) / 100L + ((1900L + (X)) - 1600L) / 400L)
132 
133 
134 /*
135  * The following macros are replacements for detzcode(), which has
136  * been in the public domain versions of the localtime.c code for
137  * a long time. The primatives supporting the CVTZCODE macro are
138  * implemented differently for different endianness (ie. little
139  * vs. big endian) out of necessity, to account for the different
140  * byte ordering of the quantities being fetched.  Both versions
141  * are substantially faster than the detzcode() macro.  The big
142  * endian version is approx. 6.8x faster than detzcode(), the
143  * little endian version is approximately 3x faster, due to the
144  * extra shifting requiring to change byte order.  The micro
145  * benchmarks used to compare were based on the SUNWSpro SC6.1
146  * (and later) compilers.
147  */
148 
149 #if defined(__sparc) || defined(__sparcv9)  /* big endian */
150 
151 #define	GET_LONG(p) \
152 	    *(uint_t *)(p)
153 
154 #define	GET_SHORTS(p) \
155 	    *(ushort_t *)(p) << 16 |\
156 	    *(ushort_t *)((p) + 2)
157 
158 #define	GET_CHARS(p) \
159 	    *(uchar_t *)(p) << 24 |\
160 	    *(uchar_t *)((p) + 1) << 16 |\
161 	    *(uchar_t *)((p) + 2) << 8  |\
162 	    *(uchar_t *)((p) + 3)
163 
164 #else /* little endian */
165 
166 #define	GET_BYTE(x) \
167 	    ((x) & 0xff)
168 
169 #define	SWAP_BYTES(x) ((\
170 	    GET_BYTE(x) << 8) |\
171 	    GET_BYTE((x) >> 8))
172 
173 #define	SWAP_WORDS(x) ((\
174 	    SWAP_BYTES(x) << 16) |\
175 	    SWAP_BYTES((x) >> 16))
176 
177 #define	GET_LONG(p) \
178 	    SWAP_WORDS(*(uint_t *)(p))
179 
180 #define	GET_SHORTS(p) \
181 	    SWAP_BYTES(*(ushort_t *)(p)) << 16 |\
182 	    SWAP_BYTES(*(ushort_t *)((p) + 2))
183 
184 #define	GET_CHARS(p) \
185 	    GET_BYTE(*(uchar_t *)(p)) << 24 |\
186 	    GET_BYTE(*(uchar_t *)((p) + 1)) << 16 |\
187 	    GET_BYTE(*(uchar_t *)((p) + 2)) << 8 |\
188 	    GET_BYTE(*(uchar_t *)((p) + 3))
189 
190 #endif
191 
192 
193 #define	IF_ALIGNED(ptr, byte_alignment) \
194 			!((uintptr_t)(ptr) & (byte_alignment - 1))
195 
196 #define	CVTZCODE(p) (int)(\
197 	    IF_ALIGNED(p, 4) ? GET_LONG(p) :\
198 	    IF_ALIGNED(p, 2) ? GET_SHORTS(p) : GET_CHARS(p));\
199 	    p += 4;
200 
201 #ifndef	FALSE
202 #define	FALSE	(0)
203 #endif
204 
205 #ifndef	TRUE
206 #define	TRUE	(1)
207 #endif
208 
209 extern	mutex_t		_time_lock;
210 
211 extern const int	__lyday_to_month[];
212 extern const int	__yday_to_month[];
213 extern const int	__mon_lengths[2][MONSPERYEAR];
214 extern const int	__year_lengths[2];
215 
216 const char	_tz_gmt[4] = "GMT";	/* "GMT"  */
217 const char	_tz_spaces[4] = "   ";	/* "   "  */
218 static const char	_posix_gmt0[5] = "GMT0";	/* "GMT0" */
219 
220 typedef struct ttinfo {			/* Time type information */
221 	long		tt_gmtoff;	/* GMT offset in seconds */
222 	int		tt_isdst;	/* used to set tm_isdst */
223 	int		tt_abbrind;	/* abbreviation list index */
224 	int		tt_ttisstd;	/* TRUE if trans is std time */
225 	int		tt_ttisgmt;	/* TRUE if transition is GMT */
226 } ttinfo_t;
227 
228 typedef struct lsinfo {			/* Leap second information */
229 	time_t		ls_trans;	/* transition time */
230 	long		ls_corr;	/* correction to apply */
231 } lsinfo_t;
232 
233 typedef struct previnfo {		/* Info about *prev* trans */
234 	ttinfo_t	*std;		/* Most recent std type */
235 	ttinfo_t	*alt;		/* Most recent alt type */
236 } prev_t;
237 
238 typedef enum {
239 	MON_WEEK_DOW,		/* Mm.n.d - month, week, day of week */
240 	JULIAN_DAY,		/* Jn - Julian day */
241 	DAY_OF_YEAR		/* n - day of year */
242 } posrule_type_t;
243 
244 typedef struct {
245 	posrule_type_t	r_type;		/* type of rule */
246 	int		r_day;		/* day number of rule */
247 	int		r_week;		/* week number of rule */
248 	int		r_mon;		/* month number of rule */
249 	long		r_time;		/* transition time of rule */
250 } rule_t;
251 
252 typedef struct {
253 	rule_t		*rules[2];
254 	long		offset[2];
255 	long long	rtime[2];
256 } posix_daylight_t;
257 
258 /*
259  * Note: ZONERULES_INVALID used for global curr_zonerules variable, but not
260  * for zonerules field of state_t.
261  */
262 typedef enum {
263 	ZONERULES_INVALID, POSIX, POSIX_USA, ZONEINFO
264 } zone_rules_t;
265 
266 /*
267  * The following members are allocated from the libc-internal malloc:
268  *
269  *	zonename
270  *	chars
271  */
272 typedef struct state {
273 	const char	*zonename;		/* Timezone */
274 	struct state	*next;			/* next state */
275 	zone_rules_t	zonerules;		/* Type of zone */
276 	int		daylight;		/* daylight global */
277 	long		default_timezone;	/* Def. timezone val */
278 	long		default_altzone;	/* Def. altzone val */
279 	const char	*default_tzname0;	/* Def tz..[0] val */
280 	const char	*default_tzname1;	/* Def tz..[1] val  */
281 	int		leapcnt;		/* # leap sec trans */
282 	int		timecnt;		/* # transitions */
283 	int		typecnt;		/* # zone types */
284 	int		charcnt;		/* # zone abbv. chars */
285 	char		*chars;			/* Zone abbv. chars */
286 	size_t		charsbuf_size;		/* malloc'ed buflen */
287 	prev_t		prev[TZ_MAX_TIMES];	/* Pv. trans info */
288 	time_t		ats[TZ_MAX_TIMES];	/* Trans.  times */
289 	uchar_t		types[TZ_MAX_TIMES];	/* Type indices */
290 	ttinfo_t	ttis[TZ_MAX_TYPES];	/* Zone types */
291 	lsinfo_t	lsis[TZ_MAX_LEAPS];	/* Leap sec trans */
292 	int		last_ats_idx;		/* last ats index */
293 	rule_t		start_rule;		/* For POSIX w/rules */
294 	rule_t		end_rule;		/* For POSIX w/rules */
295 } state_t;
296 
297 typedef struct tznmlist {
298 	struct tznmlist *link;
299 	char	name[1];
300 } tznmlist_t;
301 
302 static const char	*systemTZ;
303 static tznmlist_t	*systemTZrec;
304 
305 static const char	*namecache;
306 
307 static state_t		*tzcache[HASHTABLE];
308 
309 #define	TZNMC_SZ	43
310 static tznmlist_t	*tznmhash[TZNMC_SZ];
311 static const char	*last_tzname[2];
312 
313 static state_t		*lclzonep;
314 
315 static struct tm	tm;		/* For non-reentrant use */
316 static int		is_in_dst;	/* Set if t is in DST */
317 static zone_rules_t	curr_zonerules = ZONERULES_INVALID;
318 static int		cached_year;	/* mktime() perf. enhancement */
319 static long long	cached_secs_since_1970;	/* mktime() perf. */
320 static int		year_is_cached = FALSE;	/* mktime() perf. */
321 
322 #define	TZSYNC_FILE	"/var/run/tzsync"
323 static uint32_t		zoneinfo_seqno;
324 static uint32_t		zoneinfo_seqno_init = 1;
325 static uint32_t		*zoneinfo_seqadr = &zoneinfo_seqno_init;
326 #define	RELOAD_INFO()	(zoneinfo_seqno != *zoneinfo_seqadr)
327 
328 #define	_2AM		(2 * SECSPERHOUR)
329 #define	FIRSTWEEK	1
330 #define	LASTWEEK	5
331 
332 enum wks {
333 	_1st_week = 1,
334 	_2nd_week,
335 	_3rd_week,
336 	_4th_week,
337 	_Last_week
338 };
339 
340 enum dwk {
341 	Sun,
342 	Mon,
343 	Tue,
344 	Wed,
345 	Thu,
346 	Fri,
347 	Sat
348 };
349 
350 enum mth {
351 	Jan = 1,
352 	Feb,
353 	Mar,
354 	Apr,
355 	May,
356 	Jun,
357 	Jul,
358 	Aug,
359 	Sep,
360 	Oct,
361 	Nov,
362 	Dec
363 };
364 
365 /*
366  * The following table defines standard USA DST transitions
367  * as they have been declared throughout history, disregarding
368  * the legally sanctioned local variants.
369  *
370  * Note:  At some point, this table may be supplanted by
371  * more popular 'posixrules' logic.
372  */
373 typedef struct {
374 	int	s_year;
375 	int	e_year;
376 	rule_t	start;
377 	rule_t	end;
378 } __usa_rules_t;
379 
380 static const __usa_rules_t	__usa_rules[] = {
381 	{
382 		2007, 2037,
383 		{ MON_WEEK_DOW, Sun, _2nd_week, Mar, _2AM },
384 		{ MON_WEEK_DOW, Sun, _1st_week, Nov, _2AM },
385 	},
386 	{
387 		1987, 2006,
388 		{ MON_WEEK_DOW, Sun, _1st_week,  Apr, _2AM },
389 		{ MON_WEEK_DOW, Sun, _Last_week, Oct, _2AM },
390 	},
391 	{
392 		1976, 1986,
393 		{ MON_WEEK_DOW, Sun, _Last_week, Apr, _2AM },
394 		{ MON_WEEK_DOW, Sun, _Last_week, Oct, _2AM },
395 	},
396 	{
397 		1975, 1975,
398 		{ MON_WEEK_DOW, Sun, _Last_week, Feb, _2AM },
399 		{ MON_WEEK_DOW, Sun, _Last_week, Oct, _2AM },
400 	},
401 
402 	{
403 		1974, 1974,
404 		{ MON_WEEK_DOW, Sun, _1st_week,  Jan, _2AM },
405 		{ MON_WEEK_DOW, Sun, _Last_week, Nov, _2AM },
406 	},
407 	/*
408 	 * The entry below combines two previously separate entries for
409 	 * 1969-1973 and 1902-1968
410 	 */
411 	{
412 		1902, 1973,
413 		{ MON_WEEK_DOW, Sun, _Last_week, Apr, _2AM },
414 		{ MON_WEEK_DOW, Sun, _Last_week, Oct, _2AM },
415 	}
416 };
417 #define	MAX_RULE_TABLE	(sizeof (__usa_rules) / sizeof (__usa_rules_t) - 1)
418 
419 /*
420  * Prototypes for static functions.
421  */
422 static const char *getsystemTZ(void);
423 static const char *getzname(const char *, int);
424 static const char *getnum(const char *, int *, int, int);
425 static const char *getsecs(const char *, long *);
426 static const char *getoffset(const char *, long *);
427 static const char *getrule(const char *, rule_t *, int);
428 static int	load_posixinfo(const char *, state_t *);
429 static int	load_zoneinfo(const char *, state_t *);
430 static void	load_posix_transitions(state_t *, long, long, zone_rules_t);
431 static void	adjust_posix_default(state_t *, long, long);
432 static void	*ltzset_u(time_t);
433 static struct tm *offtime_u(time_t, long, struct tm *);
434 static int	posix_check_dst(long long, state_t *);
435 static int	posix_daylight(long long *, int, posix_daylight_t *);
436 static void	set_zone_context(time_t);
437 static void	reload_counter(void);
438 static void	purge_zone_cache(void);
439 static void	set_tzname(const char **);
440 
441 /*
442  * definition of difftime
443  *
444  * This code assumes time_t is type long.  Note the difference of two
445  * longs in absolute value is representable as an unsigned long.  So,
446  * compute the absolute value of the difference, cast the result to
447  * double and attach the sign back on.
448  *
449  * Note this code assumes 2's complement arithmetic.  The subtraction
450  * operation may overflow when using signed operands, but when the
451  * result is cast to unsigned long, it yields the desired value
452  * (ie, the absolute value of the difference).  The cast to unsigned
453  * long is done using pointers to avoid undefined behavior if casting
454  * a negative value to unsigned.
455  */
456 double
difftime(time_t time1,time_t time0)457 difftime(time_t time1, time_t time0)
458 {
459 	if (time1 < time0) {
460 		time0 -= time1;
461 		return (-(double)*(unsigned long *) &time0);
462 	} else {
463 		time1 -= time0;
464 		return ((double)*(unsigned long *) &time1);
465 	}
466 }
467 
468 /*
469  * Accepts a time_t, returns a tm struct based on it, with
470  * no local timezone adjustment.
471  *
472  * This routine is the thread-safe variant of gmtime(), and
473  * requires that the call provide the address of their own tm
474  * struct.
475  *
476  * Locking is not done here because set_zone_context()
477  * is not called, thus timezone, altzone, and tzname[] are not
478  * accessed, no memory is allocated, and no common dynamic
479  * data is accessed.
480  *
481  * See ctime(3C)
482  */
483 struct tm *
gmtime_r(const time_t * timep,struct tm * p_tm)484 gmtime_r(const time_t *timep, struct tm *p_tm)
485 {
486 	return (offtime_u((time_t)*timep, 0L, p_tm));
487 }
488 
489 /*
490  * Accepts a time_t, returns a tm struct based on it, with
491  * no local timezone adjustment.
492  *
493  * This function is explicitly NOT THREAD-SAFE.  The standards
494  * indicate it should provide its results in its own statically
495  * allocated tm struct that gets overwritten. The thread-safe
496  * variant is gmtime_r().  We make it mostly thread-safe by
497  * allocating its buffer in thread-specific data.
498  *
499  * See ctime(3C)
500  */
501 struct tm *
gmtime(const time_t * timep)502 gmtime(const time_t *timep)
503 {
504 	struct tm *p_tm = tsdalloc(_T_STRUCT_TM, sizeof (struct tm), NULL);
505 
506 	if (p_tm == NULL)	/* memory allocation failure */
507 		p_tm = &tm;	/* use static buffer and hope for the best */
508 	return (gmtime_r(timep, p_tm));
509 }
510 
511 /*
512  * This is the hashing function, based on the input timezone name.
513  */
514 static int
get_hashid(const char * id)515 get_hashid(const char *id)
516 {
517 	unsigned char	c;
518 	unsigned int	h;
519 
520 	h = *id++;
521 	while ((c = *id++) != '\0')
522 		h += c;
523 	return ((int)(h % HASHTABLE));
524 }
525 
526 /*
527  * find_zone() gets the hashid for zonename, then uses the hashid
528  * to search the hash table for the appropriate timezone entry.  If
529  * the entry for zonename is found in the hash table, return a pointer
530  * to the entry.
531  */
532 static state_t *
find_zone(const char * zonename)533 find_zone(const char *zonename)
534 {
535 	int	hashid;
536 	state_t	*cur;
537 
538 	hashid = get_hashid(zonename);
539 	cur = tzcache[hashid];
540 	while (cur) {
541 		int	res;
542 		res = strcmp(cur->zonename, zonename);
543 		if (res == 0) {
544 			return (cur);
545 		} else if (res > 0) {
546 			break;
547 		}
548 		cur = cur->next;
549 	}
550 	return (NULL);
551 }
552 
553 /*
554  * Register new state in the cache.
555  */
556 static void
reg_zone(state_t * new)557 reg_zone(state_t *new)
558 {
559 	int	hashid, res;
560 	state_t	*cur, *prv;
561 
562 	hashid = get_hashid(new->zonename);
563 	cur = tzcache[hashid];
564 	prv = NULL;
565 	while (cur != NULL) {
566 		res = strcmp(cur->zonename, new->zonename);
567 		if (res == 0) {
568 			/* impossible, but just in case */
569 			return;
570 		} else if (res > 0) {
571 			break;
572 		}
573 		prv = cur;
574 		cur = cur->next;
575 	}
576 	if (prv != NULL) {
577 		new->next = prv->next;
578 		prv->next = new;
579 	} else {
580 		new->next = tzcache[hashid];
581 		tzcache[hashid] = new;
582 	}
583 }
584 
585 /*
586  * Returns tm struct based on input time_t argument, correcting
587  * for the local timezone, producing documented side-effects
588  * to extern global state, timezone, altzone, daylight and tzname[].
589  *
590  * localtime_r() is the thread-safe variant of localtime().
591  *
592  * IMPLEMENTATION NOTE:
593  *
594  *	Locking slows multithreaded access and is probably ultimately
595  *	unnecessary here. The POSIX specification is a bit vague
596  *	as to whether the extern variables set by tzset() need to
597  *	set as a result of a call to localtime_r()
598  *
599  *	Currently, the spec only mentions that tzname[] doesn't
600  *	need to be set.  As soon as it becomes unequivocal
601  *	that the external zone state doesn't need to be asserted
602  *	for this call, and it really doesn't make much sense
603  *	to set common state from multi-threaded calls made to this
604  *	function, locking can be dispensed with here.
605  *
606  *	local zone state would still need to be aquired for the
607  *	time in question in order for calculations elicited here
608  *	to be correct, but that state wouldn't need to be shared,
609  *	thus no multi-threaded synchronization would be required.
610  *
611  *	It would be nice if POSIX would approve an ltzset_r()
612  *	function, but if not, it wouldn't stop us from making one
613  *	privately.
614  *
615  *	localtime_r() can now return NULL if overflow is detected.
616  *	offtime_u() is the function that detects overflow, and sets
617  *	errno appropriately.  We unlock before the call to offtime_u(),
618  *	so that lmutex_unlock() does not reassign errno.  The function
619  *	offtime_u() is MT-safe and does not have to be locked.  Use
620  *	my_is_in_dst to reference local copy of is_in_dst outside locks.
621  *
622  * See ctime(3C)
623  */
624 struct tm *
localtime_r(const time_t * timep,struct tm * p_tm)625 localtime_r(const time_t *timep, struct tm *p_tm)
626 {
627 	long	offset;
628 	struct tm *rt;
629 	void	*unused;
630 	int	my_is_in_dst;
631 
632 	lmutex_lock(&_time_lock);
633 	unused = ltzset_u(*timep);
634 	if (lclzonep == NULL) {
635 		lmutex_unlock(&_time_lock);
636 		if (unused != NULL)
637 			free(unused);
638 		return (offtime_u(*timep, 0L, p_tm));
639 	}
640 	my_is_in_dst = is_in_dst;
641 	offset = (my_is_in_dst) ? -altzone : -timezone;
642 	lmutex_unlock(&_time_lock);
643 	if (unused != NULL)
644 		free(unused);
645 	rt = offtime_u(*timep, offset, p_tm);
646 	p_tm->tm_isdst = my_is_in_dst;
647 	return (rt);
648 }
649 
650 /*
651  * Accepts a time_t, returns a tm struct based on it, correcting
652  * for the local timezone.  Produces documented side-effects to
653  * extern global timezone state data.
654  *
655  * This function is explicitly NOT THREAD-SAFE.  The standards
656  * indicate it should provide its results in its own statically
657  * allocated tm struct that gets overwritten. The thread-safe
658  * variant is localtime_r().  We make it mostly thread-safe by
659  * allocating its buffer in thread-specific data.
660  *
661  * localtime() can now return NULL if overflow is detected.
662  * offtime_u() is the function that detects overflow, and sets
663  * errno appropriately.
664  *
665  * See ctime(3C)
666  */
667 struct tm *
localtime(const time_t * timep)668 localtime(const time_t *timep)
669 {
670 	struct tm *p_tm = tsdalloc(_T_STRUCT_TM, sizeof (struct tm), NULL);
671 
672 	if (p_tm == NULL)	/* memory allocation failure */
673 		p_tm = &tm;	/* use static buffer and hope for the best */
674 	return (localtime_r(timep, p_tm));
675 }
676 
677 /*
678  * This function takes a pointer to a tm struct and returns a
679  * normalized time_t, also inducing documented side-effects in
680  * extern global zone state variables.  (See mktime(3C)).
681  */
682 static time_t
mktime1(struct tm * tmptr,int usetz)683 mktime1(struct tm *tmptr, int usetz)
684 {
685 	struct tm _tm;
686 	long long t;		/* must hold more than 32-bit time_t */
687 	int	temp;
688 	int	mketimerrno;
689 	int	overflow;
690 	void	*unused = NULL;
691 
692 	mketimerrno = errno;
693 
694 	/* mktime leaves errno unchanged if no error is encountered */
695 
696 	/* Calculate time_t from tm arg.  tm may need to be normalized. */
697 	t = tmptr->tm_sec + SECSPERMIN * tmptr->tm_min +
698 	    SECSPERHOUR * tmptr->tm_hour +
699 	    SECSPERDAY * (tmptr->tm_mday - 1);
700 
701 	if (tmptr->tm_mon >= 12) {
702 		tmptr->tm_year += tmptr->tm_mon / 12;
703 		tmptr->tm_mon %= 12;
704 	} else if (tmptr->tm_mon < 0) {
705 		temp = -tmptr->tm_mon;
706 		tmptr->tm_mon = 0;	/* If tm_mon divides by 12. */
707 		tmptr->tm_year -= (temp / 12);
708 		if (temp %= 12) {	/* Remainder... */
709 			tmptr->tm_year--;
710 			tmptr->tm_mon = 12 - temp;
711 		}
712 	}
713 
714 	lmutex_lock(&_time_lock);
715 
716 	/* Avoid numerous calculations embedded in macro if possible */
717 	if (!year_is_cached || (cached_year != tmptr->tm_year))	 {
718 		cached_year = tmptr->tm_year;
719 		year_is_cached = TRUE;
720 		/* For boundry values of tm_year, typecasting required */
721 		cached_secs_since_1970 =
722 		    (long long)SECSPERDAY * DAYS_SINCE_70(cached_year);
723 	}
724 	t += cached_secs_since_1970;
725 
726 	if (isleap(tmptr->tm_year + TM_YEAR_BASE))
727 		t += SECSPERDAY * __lyday_to_month[tmptr->tm_mon];
728 	else
729 		t += SECSPERDAY * __yday_to_month[tmptr->tm_mon];
730 
731 
732 	if (usetz) {
733 		/*
734 		 * If called from mktime(), then we need to do the TZ
735 		 * related transformations.
736 		 */
737 
738 		unused = ltzset_u((time_t)t);
739 
740 		/* Attempt to convert time to GMT based on tm_isdst setting */
741 		t += (tmptr->tm_isdst > 0) ? altzone : timezone;
742 
743 #ifdef _ILP32
744 		overflow = t > LONG_MAX || t < LONG_MIN ||
745 		    tmptr->tm_year < 1 || tmptr->tm_year > 138;
746 #else
747 		overflow = t > LONG_MAX || t < LONG_MIN;
748 #endif
749 		set_zone_context((time_t)t);
750 		if (tmptr->tm_isdst < 0) {
751 			long dst_delta = timezone - altzone;
752 			switch (curr_zonerules) {
753 			case ZONEINFO:
754 				if (is_in_dst) {
755 					t -= dst_delta;
756 					set_zone_context((time_t)t);
757 					if (is_in_dst) {
758 						(void) offtime_u((time_t)t,
759 						    -altzone, &_tm);
760 						_tm.tm_isdst = 1;
761 					} else {
762 						(void) offtime_u((time_t)t,
763 						    -timezone, &_tm);
764 					}
765 				} else {
766 					(void) offtime_u((time_t)t, -timezone,
767 					    &_tm);
768 				}
769 				break;
770 			case POSIX_USA:
771 			case POSIX:
772 				if (is_in_dst) {
773 					t -= dst_delta;
774 					set_zone_context((time_t)t);
775 					if (is_in_dst) {
776 						(void) offtime_u((time_t)t,
777 						    -altzone, &_tm);
778 						_tm.tm_isdst = 1;
779 					} else {
780 						(void) offtime_u((time_t)t,
781 						    -timezone, &_tm);
782 					}
783 				} else {
784 					/*
785 					 * check for ambiguous
786 					 * 'fallback' transition
787 					 */
788 					set_zone_context((time_t)t - dst_delta);
789 					if (is_in_dst) {
790 						/* In fallback, force DST */
791 						t -= dst_delta;
792 						(void) offtime_u((time_t)t,
793 						    -altzone, &_tm);
794 						_tm.tm_isdst = 1;
795 					} else {
796 						(void) offtime_u((time_t)t,
797 						    -timezone, &_tm);
798 					}
799 				}
800 				break;
801 
802 			case ZONERULES_INVALID:
803 				(void) offtime_u((time_t)t, 0L, &_tm);
804 				break;
805 
806 			}
807 		} else if (is_in_dst) {
808 			(void) offtime_u((time_t)t, -altzone, &_tm);
809 			_tm.tm_isdst = 1;
810 		} else {
811 			(void) offtime_u((time_t)t, -timezone, &_tm);
812 		}
813 
814 	} else {	/* !usetz, i.e. using UTC */
815 		overflow = 0;
816 		/* Normalize the TM structure */
817 		(void) offtime_u((time_t)t, 0, &_tm);
818 	}
819 
820 	if (overflow || t > LONG_MAX || t < LONG_MIN) {
821 		mketimerrno = EOVERFLOW;
822 		t = -1;
823 	} else {
824 		*tmptr = _tm;
825 	}
826 
827 	lmutex_unlock(&_time_lock);
828 	if (unused != NULL)
829 		free(unused);
830 
831 	errno = mketimerrno;
832 	return ((time_t)t);
833 }
834 
835 time_t
mktime(struct tm * tmptr)836 mktime(struct tm *tmptr)
837 {
838 	return (mktime1(tmptr, TRUE));
839 }
840 
841 time_t
timegm(struct tm * tmptr)842 timegm(struct tm *tmptr)
843 {
844 	return (mktime1(tmptr, FALSE));
845 }
846 
847 
848 /*
849  * Sets extern global zone state variables based on the current
850  * time.  Specifically, tzname[], timezone, altzone, and daylight
851  * are updated.  See ctime(3C) manpage.
852  */
853 void
tzset(void)854 tzset(void)
855 {
856 	void	*unused;
857 
858 	lmutex_lock(&_time_lock);
859 	unused = ltzset_u(time(NULL));
860 	lmutex_unlock(&_time_lock);
861 	if (unused != NULL)
862 		free(unused);
863 }
864 
865 void
_ltzset(time_t tim)866 _ltzset(time_t tim)
867 {
868 	void	*unused;
869 
870 	lmutex_lock(&_time_lock);
871 	unused = ltzset_u(tim);
872 	lmutex_unlock(&_time_lock);
873 	if (unused != NULL)
874 		free(unused);
875 }
876 
877 /*
878  * Loads local zone information if TZ changed since last time zone
879  * information was loaded, or if this is the first time thru.
880  * We already hold _time_lock; no further locking is required.
881  * Return a memory block which can be free'd at safe place.
882  */
883 static void *
ltzset_u(time_t t)884 ltzset_u(time_t t)
885 {
886 	const char	*zonename;
887 	state_t		*entry, *new_entry;
888 	const char	*newtzname[2];
889 
890 	if (RELOAD_INFO()) {
891 		reload_counter();
892 		purge_zone_cache();
893 	}
894 
895 	if ((zonename = getsystemTZ()) == NULL || *zonename == '\0')
896 		zonename = _posix_gmt0;
897 
898 	if (namecache != NULL && strcmp(namecache, zonename) == 0) {
899 		set_zone_context(t);
900 		return (NULL);
901 	}
902 
903 	entry = find_zone(zonename);
904 	if (entry == NULL) {
905 		/*
906 		 * We need to release _time_lock to call out malloc().
907 		 * We can release _time_lock as far as global variables
908 		 * can remain consistent. Here, we haven't touch any
909 		 * variables, so it's okay to release lock.
910 		 */
911 		lmutex_unlock(&_time_lock);
912 		new_entry = malloc(sizeof (state_t));
913 		lmutex_lock(&_time_lock);
914 
915 		/*
916 		 * check it again, since zone may have been loaded while
917 		 * time_lock was unlocked.
918 		 */
919 		entry = find_zone(zonename);
920 	} else {
921 		new_entry = NULL;
922 		goto out;
923 	}
924 
925 	/*
926 	 * We are here because the 1st attemp failed.
927 	 * new_entry points newly allocated entry. If it was NULL, it
928 	 * indicates that the memory allocation also failed.
929 	 */
930 	if (entry == NULL) {
931 		/*
932 		 * 2nd attemp also failed.
933 		 * No timezone entry found in hash table, so load it,
934 		 * and create a new timezone entry.
935 		 */
936 		char	*newzonename, *charsbuf;
937 
938 		newzonename = libc_strdup(zonename);
939 		daylight = 0;
940 		entry = new_entry;
941 
942 		if (entry == NULL || newzonename == NULL) {
943 			/* something wrong happened. */
944 failed:
945 			if (newzonename != NULL)
946 				libc_free(newzonename);
947 
948 			/* Invalidate the current timezone */
949 			curr_zonerules = ZONERULES_INVALID;
950 			namecache = NULL;
951 
952 			timezone = altzone = 0;
953 			is_in_dst = 0;
954 			newtzname[0] = (char *)_tz_gmt;
955 			newtzname[1] = (char *)_tz_spaces;
956 			set_tzname(newtzname);
957 			return (entry);
958 		}
959 
960 		/*
961 		 * Builds transition cache and sets up zone state data for zone
962 		 * specified in TZ, which can be specified as a POSIX zone or an
963 		 * Olson zoneinfo file reference.
964 		 *
965 		 * If local data cannot be parsed or loaded, the local zone
966 		 * tables are set up for GMT.
967 		 *
968 		 * Unless a leading ':' is prepended to TZ, TZ is initially
969 		 * parsed as a POSIX zone;  failing that, it reverts to
970 		 * a zoneinfo check.
971 		 * However, if a ':' is prepended, the zone will *only* be
972 		 * parsed as zoneinfo.  If any failure occurs parsing or
973 		 * loading a zoneinfo TZ, GMT data is loaded for the local zone.
974 		 *
975 		 * Example:  There is a zoneinfo file in the standard
976 		 * distribution called 'PST8PDT'.  The only way the user can
977 		 * specify that file under Solaris is to set TZ to ":PST8PDT".
978 		 * Otherwise the initial parse of PST8PDT as a POSIX zone will
979 		 * succeed and be used.
980 		 */
981 		if ((charsbuf = libc_malloc(TZ_MAX_CHARS)) == NULL)
982 			goto failed;
983 
984 		entry->zonerules = ZONERULES_INVALID;
985 		entry->charsbuf_size = TZ_MAX_CHARS;
986 		entry->chars = charsbuf;
987 		entry->default_tzname0 = _tz_gmt;
988 		entry->default_tzname1 = _tz_spaces;
989 		entry->zonename = newzonename;
990 
991 		if (*zonename == ':') {
992 			if (load_zoneinfo(zonename + 1, entry) != 0) {
993 				(void) load_posixinfo(_posix_gmt0, entry);
994 			}
995 		} else if (load_posixinfo(zonename, entry) != 0) {
996 			if (load_zoneinfo(zonename, entry) != 0) {
997 				(void) load_posixinfo(_posix_gmt0, entry);
998 			}
999 		}
1000 		entry->last_ats_idx = -1;
1001 
1002 		/*
1003 		 * The pre-allocated buffer is used; reset the free flag
1004 		 * so the buffer won't be freed.
1005 		 */
1006 		reg_zone(entry);
1007 		new_entry = NULL;
1008 	}
1009 
1010 out:
1011 	curr_zonerules = entry->zonerules;
1012 	namecache = entry->zonename;
1013 	daylight = entry->daylight;
1014 	lclzonep = entry;
1015 
1016 	set_zone_context(t);
1017 
1018 	/*
1019 	 * We shouldn't release lock beyond this point since lclzonep
1020 	 * can refer to invalid address if cache is invalidated.
1021 	 * We defer the call to free till it can be done safely.
1022 	 */
1023 	return (new_entry);
1024 }
1025 
1026 /*
1027  * Sets timezone, altzone, tzname[], extern globals, to represent
1028  * disposition of t with respect to TZ; See ctime(3C). is_in_dst,
1029  * internal global is also set.  daylight is set at zone load time.
1030  *
1031  * Issues:
1032  *
1033  *	In this function, any time_t not located in the cache is handled
1034  *	as a miss.  To build/update transition cache, load_zoneinfo()
1035  *	must be called prior to this routine.
1036  *
1037  *	If POSIX zone, cache miss penalty is slightly degraded
1038  *	performance.  For zoneinfo, penalty is decreased is_in_dst
1039  *	accuracy.
1040  *
1041  *	POSIX, despite its chicken/egg problem, ie. not knowing DST
1042  *	until time known, and not knowing time until DST known, at
1043  *	least uses the same algorithm for 64-bit time as 32-bit.
1044  *
1045  *	The fact that zoneinfo files only contain transistions for 32-bit
1046  *	time space is a well known problem, as yet unresolved.
1047  *	Without an official standard for coping with out-of-range
1048  *	zoneinfo times,  assumptions must be made.  For now
1049  *	the assumption is:   If t exceeds 32-bit boundries and local zone
1050  *	is zoneinfo type, is_in_dst is set to to 0 for negative values
1051  *	of t, and set to the same DST state as the highest ordered
1052  *	transition in cache for positive values of t.
1053  */
1054 static void
set_zone_default_context(void)1055 set_zone_default_context(void)
1056 {
1057 	const char	*newtzname[2];
1058 
1059 	/* Retrieve suitable defaults for this zone */
1060 	altzone = lclzonep->default_altzone;
1061 	timezone = lclzonep->default_timezone;
1062 	newtzname[0] = (char *)lclzonep->default_tzname0;
1063 	newtzname[1] = (char *)lclzonep->default_tzname1;
1064 	is_in_dst = 0;
1065 
1066 	set_tzname(newtzname);
1067 }
1068 
1069 static bool
state_is_posix(const state_t * state)1070 state_is_posix(const state_t *state)
1071 {
1072 	return (state->zonerules == POSIX || state->zonerules == POSIX_USA);
1073 }
1074 
1075 static void
set_zone_context(time_t t)1076 set_zone_context(time_t t)
1077 {
1078 	prev_t		*prevp;
1079 	int		lo, hi, tidx, lidx;
1080 	ttinfo_t	*ttisp, *std, *alt;
1081 	const char	*newtzname[2];
1082 
1083 	/* If state data not loaded or TZ busted, just use GMT */
1084 	if (lclzonep == NULL || curr_zonerules == ZONERULES_INVALID) {
1085 		timezone = altzone = 0;
1086 		daylight = is_in_dst = 0;
1087 		newtzname[0] = (char *)_tz_gmt;
1088 		newtzname[1] = (char *)_tz_spaces;
1089 		set_tzname(newtzname);
1090 		return;
1091 	}
1092 
1093 	if (lclzonep->timecnt <= 0 || lclzonep->typecnt < 2) {
1094 		/* Loaded zone incapable of transitioning. */
1095 		set_zone_default_context();
1096 		return;
1097 	}
1098 
1099 	/*
1100 	 * At least one alt. zone and one transistion exist. Locate
1101 	 * state for 't' quickly as possible.  Use defaults as necessary.
1102 	 */
1103 	lo = 0;
1104 	hi = lclzonep->timecnt - 1;
1105 
1106 	if (t < lclzonep->ats[0] || t >= lclzonep->ats[hi]) {
1107 		/*
1108 		 * Date which is out of definition.
1109 		 * Calculate DST as best as possible
1110 		 */
1111 		if (lclzonep->zonerules == POSIX_USA ||
1112 		    lclzonep->zonerules == POSIX) {
1113 			/* Must invoke calculations to determine DST */
1114 			set_zone_default_context();
1115 			is_in_dst = (daylight) ?
1116 			    posix_check_dst(t, lclzonep) : 0;
1117 			return;
1118 		} else if (t < lclzonep->ats[0]) {   /* zoneinfo... */
1119 			/* t precedes 1st transition.  Use defaults */
1120 			set_zone_default_context();
1121 			return;
1122 		} else	{    /* zoneinfo */
1123 			/* t follows final transistion.  Use final */
1124 			tidx = hi;
1125 		}
1126 	} else {
1127 		if ((lidx = lclzonep->last_ats_idx) != -1 &&
1128 		    lidx != hi &&
1129 		    t >= lclzonep->ats[lidx] &&
1130 		    t < lclzonep->ats[lidx + 1]) {
1131 			/* CACHE HIT. Nothing needs to be done */
1132 			tidx = lidx;
1133 		} else {
1134 			/*
1135 			 * CACHE MISS.  Locate transition using binary search.
1136 			 */
1137 			while (lo <= hi) {
1138 				tidx = (lo + hi) / 2;
1139 				if (t == lclzonep->ats[tidx])
1140 					break;
1141 				else if (t < lclzonep->ats[tidx])
1142 					hi = tidx - 1;
1143 				else
1144 					lo = tidx + 1;
1145 			}
1146 			if (lo > hi)
1147 				tidx = hi;
1148 		}
1149 	}
1150 
1151 	/*
1152 	 * Set extern globals based on located transition and summary of
1153 	 * its previous state, which were cached when zone was loaded
1154 	 */
1155 	ttisp = &lclzonep->ttis[lclzonep->types[tidx]];
1156 	prevp = &lclzonep->prev[tidx];
1157 	bool posix = state_is_posix(lclzonep);
1158 
1159 	if ((is_in_dst = ttisp->tt_isdst) == 0) { /* std. time */
1160 		timezone = -ttisp->tt_gmtoff;
1161 		newtzname[0] = &lclzonep->chars[ttisp->tt_abbrind];
1162 		if (!posix && (alt = prevp->alt) != NULL) {
1163 			altzone = -alt->tt_gmtoff;
1164 			newtzname[1] = &lclzonep->chars[alt->tt_abbrind];
1165 		} else {
1166 			altzone = lclzonep->default_altzone;
1167 			newtzname[1] = (char *)lclzonep->default_tzname1;
1168 		}
1169 	} else { /* alt. time */
1170 		altzone = -ttisp->tt_gmtoff;
1171 		newtzname[1] = &lclzonep->chars[ttisp->tt_abbrind];
1172 		if (!posix && (std = prevp->std) != NULL) {
1173 			timezone = -std->tt_gmtoff;
1174 			newtzname[0] = &lclzonep->chars[std->tt_abbrind];
1175 		} else {
1176 			timezone = lclzonep->default_timezone;
1177 			newtzname[0] = (char *)lclzonep->default_tzname0;
1178 		}
1179 	}
1180 
1181 	lclzonep->last_ats_idx = tidx;
1182 	set_tzname(newtzname);
1183 }
1184 
1185 /*
1186  * This function takes a time_t and gmt offset and produces a
1187  * tm struct based on specified time.
1188  *
1189  * The the following fields are calculated, based entirely
1190  * on the offset-adjusted value of t:
1191  *
1192  * tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec
1193  * tm_yday. tm_wday.  (tm_isdst is ALWAYS set to 0).
1194  */
1195 
1196 static struct tm *
offtime_u(time_t t,long offset,struct tm * tmptr)1197 offtime_u(time_t t, long offset, struct tm *tmptr)
1198 {
1199 	long		days;
1200 	long		rem;
1201 	long		y;
1202 	int		yleap;
1203 	const int	*ip;
1204 
1205 	days = t / SECSPERDAY;
1206 	rem = t % SECSPERDAY;
1207 	rem += offset;
1208 	while (rem < 0) {
1209 		rem += SECSPERDAY;
1210 		--days;
1211 	}
1212 	while (rem >= SECSPERDAY) {
1213 		rem -= SECSPERDAY;
1214 		++days;
1215 	}
1216 	tmptr->tm_hour = (int)(rem / SECSPERHOUR);
1217 	rem = rem % SECSPERHOUR;
1218 	tmptr->tm_min = (int)(rem / SECSPERMIN);
1219 	tmptr->tm_sec = (int)(rem % SECSPERMIN);
1220 
1221 	tmptr->tm_wday = (int)((EPOCH_WDAY + days) % DAYSPERWEEK);
1222 	if (tmptr->tm_wday < 0)
1223 		tmptr->tm_wday += DAYSPERWEEK;
1224 	y = EPOCH_YEAR;
1225 	while (days < 0 || days >= (long)__year_lengths[yleap = isleap(y)]) {
1226 		long newy;
1227 
1228 		newy = y + days / DAYSPERNYEAR;
1229 		if (days < 0)
1230 			--newy;
1231 		days -= ((long)newy - (long)y) * DAYSPERNYEAR +
1232 		    LEAPS_THRU_END_OF(newy > 0 ? newy - 1L : newy) -
1233 		    LEAPS_THRU_END_OF(y > 0 ? y - 1L : y);
1234 		y = newy;
1235 	}
1236 	tmptr->tm_year = (int)(y - TM_YEAR_BASE);
1237 	tmptr->tm_yday = (int)days;
1238 	ip = __mon_lengths[yleap];
1239 	for (tmptr->tm_mon = 0; days >=
1240 	    (long)ip[tmptr->tm_mon]; ++(tmptr->tm_mon)) {
1241 		days = days - (long)ip[tmptr->tm_mon];
1242 	}
1243 	tmptr->tm_mday = (int)(days + 1);
1244 	tmptr->tm_isdst = 0;
1245 
1246 #ifdef _LP64
1247 	/* do as much as possible before checking for error. */
1248 	if ((y > (long)INT_MAX + TM_YEAR_BASE) ||
1249 	    (y < (long)INT_MIN + TM_YEAR_BASE)) {
1250 		errno = EOVERFLOW;
1251 		return (NULL);
1252 	}
1253 #endif
1254 	return (tmptr);
1255 }
1256 
1257 /*
1258  * Check whether DST is set for time in question.  Only applies to
1259  * POSIX timezones.  If explicit POSIX transition rules were provided
1260  * for the current zone, use those, otherwise use default USA POSIX
1261  * transitions.
1262  */
1263 static int
posix_check_dst(long long t,state_t * sp)1264 posix_check_dst(long long t, state_t *sp)
1265 {
1266 	struct tm	gmttm;
1267 	long long	jan01;
1268 	int		year, i, idx, ridx;
1269 	posix_daylight_t	pdaylight;
1270 
1271 	(void) offtime_u(t, 0L, &gmttm);
1272 
1273 	year = gmttm.tm_year + 1900;
1274 	jan01 = t - ((gmttm.tm_yday * SECSPERDAY) +
1275 	    (gmttm.tm_hour * SECSPERHOUR) +
1276 	    (gmttm.tm_min * SECSPERMIN) + gmttm.tm_sec);
1277 	/*
1278 	 * If transition rules were provided for this zone,
1279 	 * use them, otherwise, default to USA daylight rules,
1280 	 * which are historically correct for the continental USA,
1281 	 * excluding local provisions.  (This logic may be replaced
1282 	 * at some point in the future with "posixrules" to offer
1283 	 * more flexibility to the system administrator).
1284 	 */
1285 	if (sp->zonerules == POSIX)	 {	/* POSIX rules */
1286 		pdaylight.rules[0] = &sp->start_rule;
1287 		pdaylight.rules[1] = &sp->end_rule;
1288 	} else {			/* POSIX_USA: USA */
1289 		i = 0;
1290 		while (year < __usa_rules[i].s_year && i < MAX_RULE_TABLE) {
1291 			i++;
1292 		}
1293 		pdaylight.rules[0] = (rule_t *)&__usa_rules[i].start;
1294 		pdaylight.rules[1] = (rule_t *)&__usa_rules[i].end;
1295 	}
1296 	pdaylight.offset[0] = timezone;
1297 	pdaylight.offset[1] = altzone;
1298 
1299 	idx = posix_daylight(&jan01, year, &pdaylight);
1300 	ridx = !idx;
1301 
1302 	/*
1303 	 * Note:  t, rtime[0], and rtime[1] are all bounded within 'year'
1304 	 * beginning on 'jan01'
1305 	 */
1306 	if (t >= pdaylight.rtime[idx] && t < pdaylight.rtime[ridx]) {
1307 		return (ridx);
1308 	} else {
1309 		return (idx);
1310 	}
1311 }
1312 
1313 /*
1314  * Given January 1, 00:00:00 GMT for a year as an Epoch-relative time,
1315  * along with the integer year #, a posix_daylight_t that is composed
1316  * of two rules, and two GMT offsets (timezone and altzone), calculate
1317  * the two Epoch-relative times the two rules take effect, and return
1318  * them in the two rtime fields of the posix_daylight_t structure.
1319  * Also update janfirst by a year, by adding the appropriate number of
1320  * seconds depending on whether the year is a leap year or not.  (We take
1321  * advantage that this routine knows the leap year status.)
1322  */
1323 static int
posix_daylight(long long * janfirst,int year,posix_daylight_t * pdaylightp)1324 posix_daylight(long long *janfirst, int year, posix_daylight_t *pdaylightp)
1325 {
1326 	rule_t	*rulep;
1327 	long	offset;
1328 	int	idx;
1329 	int	i, d, m1, yy0, yy1, yy2, dow;
1330 	long	leapyear;
1331 	long long	value;
1332 
1333 	static const int	__secs_year_lengths[2] = {
1334 		DAYSPERNYEAR * SECSPERDAY,
1335 		DAYSPERLYEAR * SECSPERDAY
1336 	};
1337 
1338 	leapyear = isleap(year);
1339 
1340 	for (idx = 0; idx < 2; idx++) {
1341 		rulep = pdaylightp->rules[idx];
1342 		offset = pdaylightp->offset[idx];
1343 
1344 		switch (rulep->r_type) {
1345 
1346 		case MON_WEEK_DOW:
1347 			/*
1348 			 * Mm.n.d - nth "dth day" of month m.
1349 			 */
1350 			value = *janfirst;
1351 			for (i = 0; i < rulep->r_mon - 1; ++i)
1352 				value += __mon_lengths[leapyear][i] *
1353 				    SECSPERDAY;
1354 
1355 			/*
1356 			 * Use Zeller's Congruence to get day-of-week of first
1357 			 * day of month.
1358 			 */
1359 			m1 = (rulep->r_mon + 9) % 12 + 1;
1360 			yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
1361 			yy1 = yy0 / 100;
1362 			yy2 = yy0 % 100;
1363 			dow = ((26 * m1 - 2) / 10 +
1364 			    1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1365 
1366 			if (dow < 0)
1367 				dow += DAYSPERWEEK;
1368 
1369 			/*
1370 			 * Following heuristic increases accuracy of USA rules
1371 			 * for negative years.
1372 			 */
1373 			if (year < 1 && leapyear)
1374 				++dow;
1375 			/*
1376 			 * "dow" is the day-of-week of the first day of the
1377 			 * month.  Get the day-of-month, zero-origin, of the
1378 			 * first "dow" day of the month.
1379 			 */
1380 			d = rulep->r_day - dow;
1381 			if (d < 0)
1382 				d += DAYSPERWEEK;
1383 			for (i = 1; i < rulep->r_week; ++i) {
1384 				if (d + DAYSPERWEEK >=
1385 				    __mon_lengths[leapyear][rulep->r_mon - 1])
1386 					break;
1387 				d += DAYSPERWEEK;
1388 			}
1389 			/*
1390 			 * "d" is the day-of-month, zero-origin, of the day
1391 			 * we want.
1392 			 */
1393 			value += d * SECSPERDAY;
1394 			break;
1395 
1396 		case JULIAN_DAY:
1397 			/*
1398 			 * Jn - Julian day, 1 == Jan 1, 60 == March 1 even
1399 			 * in leap yrs.
1400 			 */
1401 			value = *janfirst + (rulep->r_day - 1) * SECSPERDAY;
1402 			if (leapyear && rulep->r_day >= 60)
1403 				value += SECSPERDAY;
1404 			break;
1405 
1406 		case DAY_OF_YEAR:
1407 			/*
1408 			 * n - day of year.
1409 			 */
1410 			value = *janfirst + rulep->r_day * SECSPERDAY;
1411 			break;
1412 		}
1413 		pdaylightp->rtime[idx] = value + rulep->r_time + offset;
1414 	}
1415 	*janfirst += __secs_year_lengths[leapyear];
1416 
1417 	return ((pdaylightp->rtime[0] > pdaylightp->rtime[1]) ? 1 : 0);
1418 }
1419 
1420 /*
1421  * Try to load zoneinfo file into internal transition tables using name
1422  * indicated in TZ, and do validity checks.  The format of zic(8)
1423  * compiled zoneinfo files isdescribed in tzfile.h
1424  */
1425 static int
load_zoneinfo(const char * name,state_t * sp)1426 load_zoneinfo(const char *name, state_t *sp)
1427 {
1428 	char	*cp;
1429 	char	*cp2;
1430 	int	i;
1431 	long	cnt;
1432 	int	fid;
1433 	int	ttisstdcnt;
1434 	int	ttisgmtcnt;
1435 	char	*fullname;
1436 	size_t	namelen;
1437 	char	*bufp;
1438 	size_t	flen;
1439 	prev_t	*prevp;
1440 	struct	tzhead *tzhp;
1441 	struct	stat64	stbuf;
1442 	ttinfo_t	*most_recent_alt = NULL;
1443 	ttinfo_t	*most_recent_std = NULL;
1444 	ttinfo_t	*ttisp;
1445 
1446 
1447 	if (name == NULL) {
1448 		/* May TZDEFAULT be function call? */
1449 		name = TZDEFAULT;
1450 		if (name == NULL)
1451 			return (-1);
1452 	}
1453 
1454 	if ((name[0] == '/') || strstr(name, "../"))
1455 		return (-1);
1456 
1457 	/*
1458 	 * We allocate fullname this way to avoid having
1459 	 * a PATH_MAX size buffer in our stack frame.
1460 	 */
1461 	namelen = LEN_TZDIR + 1 + strlen(name) + 1;
1462 	if ((fullname = lmalloc(namelen)) == NULL)
1463 		return (-1);
1464 	(void) strcpy(fullname, TZDIR "/");
1465 	(void) strcpy(fullname + LEN_TZDIR + 1, name);
1466 	if ((fid = open(fullname, O_RDONLY)) == -1) {
1467 		lfree(fullname, namelen);
1468 		return (-1);
1469 	}
1470 	lfree(fullname, namelen);
1471 
1472 	if (fstat64(fid, &stbuf) == -1) {
1473 		(void) close(fid);
1474 		return (-1);
1475 	}
1476 
1477 	flen = (size_t)stbuf.st_size;
1478 	if (flen < sizeof (struct tzhead)) {
1479 		(void) close(fid);
1480 		return (-1);
1481 	}
1482 
1483 	/*
1484 	 * It would be nice to use alloca() to allocate bufp but,
1485 	 * as above, we wish to avoid allocating a big buffer in
1486 	 * our stack frame, and also because alloca() gives us no
1487 	 * opportunity to fail gracefully on allocation failure.
1488 	 */
1489 	cp = bufp = lmalloc(flen);
1490 	if (bufp == NULL) {
1491 		(void) close(fid);
1492 		return (-1);
1493 	}
1494 
1495 	if ((cnt = read(fid, bufp, flen)) != flen) {
1496 		lfree(bufp, flen);
1497 		(void) close(fid);
1498 		return (-1);
1499 	}
1500 
1501 	if (close(fid) != 0) {
1502 		lfree(bufp, flen);
1503 		return (-1);
1504 	}
1505 
1506 	cp += offsetof(struct tzhead, tzh_ttisutcnt);
1507 
1508 /* LINTED: alignment */
1509 	ttisstdcnt = CVTZCODE(cp);
1510 /* LINTED: alignment */
1511 	ttisgmtcnt = CVTZCODE(cp);
1512 /* LINTED: alignment */
1513 	sp->leapcnt = CVTZCODE(cp);
1514 /* LINTED: alignment */
1515 	sp->timecnt = CVTZCODE(cp);
1516 /* LINTED: alignment */
1517 	sp->typecnt = CVTZCODE(cp);
1518 /* LINTED: alignment */
1519 	sp->charcnt = CVTZCODE(cp);
1520 
1521 	if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
1522 	    sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
1523 	    sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
1524 	    sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
1525 	    (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
1526 	    (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) {
1527 		lfree(bufp, flen);
1528 		return (-1);
1529 	}
1530 
1531 	if (cnt - (cp - bufp) < (long)(sp->timecnt * 4 +	/* ats */
1532 	    sp->timecnt +			/* types */
1533 	    sp->typecnt * (4 + 2) +		/* ttinfos */
1534 	    sp->charcnt +			/* chars */
1535 	    sp->leapcnt * (4 + 4) +		/* lsinfos */
1536 	    ttisstdcnt +			/* ttisstds */
1537 	    ttisgmtcnt)) {			/* ttisgmts */
1538 		lfree(bufp, flen);
1539 		return (-1);
1540 	}
1541 
1542 
1543 	for (i = 0; i < sp->timecnt; ++i) {
1544 /* LINTED: alignment */
1545 		sp->ats[i] = CVTZCODE(cp);
1546 	}
1547 
1548 	/*
1549 	 * Skip over types[] for now and load ttis[] so that when
1550 	 * types[] are loaded we can check for transitions to STD & DST.
1551 	 * This allows us to shave cycles in ltzset_u(), including
1552 	 * eliminating the need to check set 'daylight' later.
1553 	 */
1554 
1555 	cp2 = (char *)((uintptr_t)cp + sp->timecnt);
1556 
1557 	for (i = 0; i < sp->typecnt; ++i) {
1558 		ttisp = &sp->ttis[i];
1559 /* LINTED: alignment */
1560 		ttisp->tt_gmtoff = CVTZCODE(cp2);
1561 		ttisp->tt_isdst = (uchar_t)*cp2++;
1562 
1563 		if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) {
1564 			lfree(bufp, flen);
1565 			return (-1);
1566 		}
1567 
1568 		ttisp->tt_abbrind = (uchar_t)*cp2++;
1569 		if (ttisp->tt_abbrind < 0 ||
1570 		    ttisp->tt_abbrind > sp->charcnt) {
1571 			lfree(bufp, flen);
1572 			return (-1);
1573 		}
1574 	}
1575 
1576 	/*
1577 	 * Since ttis were loaded ahead of types, it is possible to
1578 	 * detect whether daylight is ever set for this zone now, and
1579 	 * also preload other information to avoid repeated lookups later.
1580 	 * This logic facilitates keeping a running tab on the state of
1581 	 * std zone and alternate zone transitions such that timezone,
1582 	 * altzone and tzname[] can be determined quickly via an
1583 	 * index to any transition.
1584 	 *
1585 	 * For transition #0 there are no previous transitions,
1586 	 * so prev->std and prev->alt will be null, but that's OK,
1587 	 * because null prev->std/prev->alt effectively
1588 	 * indicates none existed prior.
1589 	 */
1590 
1591 	prevp = &sp->prev[0];
1592 
1593 	for (i = 0; i < sp->timecnt; ++i) {
1594 
1595 		sp->types[i] = (uchar_t)*cp++;
1596 		ttisp = &sp->ttis[sp->types[i]];
1597 
1598 		prevp->std = most_recent_std;
1599 		prevp->alt = most_recent_alt;
1600 
1601 		if (ttisp->tt_isdst == 1) {
1602 			most_recent_alt = ttisp;
1603 		} else {
1604 			most_recent_std = ttisp;
1605 		}
1606 
1607 		if ((int)sp->types[i] >= sp->typecnt) {
1608 			lfree(bufp, flen);
1609 			return (-1);
1610 		}
1611 
1612 		++prevp;
1613 	}
1614 	if (most_recent_alt == NULL)
1615 		sp->daylight = 0;
1616 	else
1617 		sp->daylight = 1;
1618 
1619 	/*
1620 	 * Set pointer ahead to where it would have been if we
1621 	 * had read types[] and ttis[] in the same order they
1622 	 * occurred in the file.
1623 	 */
1624 	cp = cp2;
1625 	for (i = 0; i < sp->charcnt; ++i)
1626 		sp->chars[i] = *cp++;
1627 
1628 	sp->chars[i] = '\0';	/* ensure '\0' at end */
1629 
1630 	for (i = 0; i < sp->leapcnt; ++i) {
1631 		struct lsinfo *lsisp;
1632 
1633 		lsisp = &sp->lsis[i];
1634 /* LINTED: alignment */
1635 		lsisp->ls_trans = CVTZCODE(cp);
1636 /* LINTED: alignment */
1637 		lsisp->ls_corr = CVTZCODE(cp);
1638 	}
1639 
1640 	for (i = 0; i < sp->typecnt; ++i) {
1641 		ttisp = &sp->ttis[i];
1642 		if (ttisstdcnt == 0) {
1643 			ttisp->tt_ttisstd = FALSE;
1644 		} else {
1645 			ttisp->tt_ttisstd = *cp++;
1646 			if (ttisp->tt_ttisstd != TRUE &&
1647 			    ttisp->tt_ttisstd != FALSE) {
1648 				lfree(bufp, flen);
1649 				return (-1);
1650 			}
1651 		}
1652 	}
1653 
1654 	for (i = 0; i < sp->typecnt; ++i) {
1655 		ttisp = &sp->ttis[i];
1656 		if (ttisgmtcnt == 0) {
1657 			ttisp->tt_ttisgmt = FALSE;
1658 		} else {
1659 			ttisp->tt_ttisgmt = *cp++;
1660 			if (ttisp->tt_ttisgmt != TRUE &&
1661 			    ttisp->tt_ttisgmt != FALSE) {
1662 				lfree(bufp, flen);
1663 				return (-1);
1664 			}
1665 		}
1666 	}
1667 
1668 	/*
1669 	 * Other defaults set at beginning of this routine
1670 	 * to cover case where zoneinfo file cannot be loaded
1671 	 */
1672 	sp->default_timezone = -sp->ttis[0].tt_gmtoff;
1673 	sp->default_altzone  = 0;
1674 	sp->default_tzname0  = &sp->chars[0];
1675 	sp->default_tzname1  = _tz_spaces;
1676 
1677 	lfree(bufp, flen);
1678 
1679 	sp->zonerules = ZONEINFO;
1680 
1681 	return (0);
1682 }
1683 
1684 #ifdef	_TZ_DEBUG
1685 static void
print_state(state_t * sp)1686 print_state(state_t *sp)
1687 {
1688 	struct tm	tmp;
1689 	int	i, c;
1690 
1691 	(void) fprintf(stderr, "=========================================\n");
1692 	(void) fprintf(stderr, "zonename: \"%s\"\n", sp->zonename);
1693 	(void) fprintf(stderr, "next: 0x%p\n", (void *)sp->next);
1694 	(void) fprintf(stderr, "zonerules: %s\n",
1695 	    sp->zonerules == ZONERULES_INVALID ? "ZONERULES_INVALID" :
1696 	    sp->zonerules == POSIX ? "POSIX" :
1697 	    sp->zonerules == POSIX_USA ? "POSIX_USA" :
1698 	    sp->zonerules == ZONEINFO ? "ZONEINFO" : "UNKNOWN");
1699 	(void) fprintf(stderr, "daylight: %d\n", sp->daylight);
1700 	(void) fprintf(stderr, "default_timezone: %ld\n", sp->default_timezone);
1701 	(void) fprintf(stderr, "default_altzone: %ld\n", sp->default_altzone);
1702 	(void) fprintf(stderr, "default_tzname0: \"%s\"\n",
1703 	    sp->default_tzname0);
1704 	(void) fprintf(stderr, "default_tzname1: \"%s\"\n",
1705 	    sp->default_tzname1);
1706 	(void) fprintf(stderr, "leapcnt: %d\n", sp->leapcnt);
1707 	(void) fprintf(stderr, "timecnt: %d\n", sp->timecnt);
1708 	(void) fprintf(stderr, "typecnt: %d\n", sp->typecnt);
1709 	(void) fprintf(stderr, "charcnt: %d\n", sp->charcnt);
1710 	(void) fprintf(stderr, "chars: \"%s\"\n", sp->chars);
1711 	(void) fprintf(stderr, "charsbuf_size: %u\n", sp->charsbuf_size);
1712 	(void) fprintf(stderr, "prev: skipping...\n");
1713 	(void) fprintf(stderr, "ats = {\n");
1714 	for (c = 0, i = 0; i < sp->timecnt; i++) {
1715 		char	buf[64];
1716 		size_t	len;
1717 		if (c != 0) {
1718 			(void) fprintf(stderr, ", ");
1719 		}
1720 		(void) asctime_r(gmtime_r(&sp->ats[i], &tmp),
1721 		    buf, sizeof (buf));
1722 		len = strlen(buf);
1723 		buf[len-1] = '\0';
1724 		(void) fprintf(stderr, "%s", buf);
1725 		if (c == 1) {
1726 			(void) fprintf(stderr, "\n");
1727 			c = 0;
1728 		} else {
1729 			c++;
1730 		}
1731 	}
1732 	(void) fprintf(stderr, "}\n");
1733 	(void) fprintf(stderr, "types = {\n");
1734 	for (c = 0, i = 0; i < sp->timecnt; i++) {
1735 		if (c == 0) {
1736 			(void) fprintf(stderr, "\t");
1737 		} else {
1738 			(void) fprintf(stderr, ", ");
1739 		}
1740 		(void) fprintf(stderr, "%d", sp->types[i]);
1741 		if (c == 7) {
1742 			(void) fprintf(stderr, "\n");
1743 			c = 0;
1744 		} else {
1745 			c++;
1746 		}
1747 	}
1748 	(void) fprintf(stderr, "}\n");
1749 	(void) fprintf(stderr, "ttis = {\n");
1750 	for (i = 0; i < sp->typecnt; i++) {
1751 		(void) fprintf(stderr, "\t{\n");
1752 		(void) fprintf(stderr, "\t\ttt_gmtoff: %ld\n",
1753 		    sp->ttis[i].tt_gmtoff);
1754 		(void) fprintf(stderr, "\t\ttt_ttisdst: %d\n",
1755 		    sp->ttis[i].tt_isdst);
1756 		(void) fprintf(stderr, "\t\ttt_abbrind: %d\n",
1757 		    sp->ttis[i].tt_abbrind);
1758 		(void) fprintf(stderr, "\t\ttt_tt_isstd: %d\n",
1759 		    sp->ttis[i].tt_ttisstd);
1760 		(void) fprintf(stderr, "\t\ttt_ttisgmt: %d\n",
1761 		    sp->ttis[i].tt_ttisgmt);
1762 		(void) fprintf(stderr, "\t}\n");
1763 	}
1764 	(void) fprintf(stderr, "}\n");
1765 }
1766 #endif
1767 
1768 /*
1769  * Given a POSIX section 8-style TZ string, fill in transition tables.
1770  *
1771  * Examples:
1772  *
1773  * TZ = PST8 or GMT0
1774  *	Timecnt set to 0 and typecnt set to 1, reflecting std time only.
1775  *
1776  * TZ = PST8PDT or PST8PDT7
1777  *	Create transition times by applying USA transitions from
1778  *	Jan 1 of each year covering 1902-2038.  POSIX offsets
1779  *	as specified in the TZ are used to calculate the tt_gmtoff
1780  *	for each of the two zones.  If ommitted, DST defaults to
1781  *	std. time minus one hour.
1782  *
1783  * TZ = <PST8>8PDT  or <PST8>8<PDT9>
1784  *      Quoted transition.  The values in angled brackets are treated
1785  *      as zone name text, not parsed as offsets.  The offsets
1786  *      occuring following the zonename section.  In this way,
1787  *      instead of PST being displayed for standard time, it could
1788  *      be displayed as PST8 to give an indication of the offset
1789  *      of that zone to GMT.
1790  *
1791  * TZ = GMT0BST, M3.5.0/1, M10.5.0/2   or  GMT0BST, J23953, J23989
1792  *	Create transition times based on the application new-year
1793  *	relative POSIX transitions, parsed from TZ, from Jan 1
1794  *	for each year covering 1902-2038.  POSIX offsets specified
1795  *	in TZ are used to calculate tt_gmtoff for each of the two
1796  *	zones.
1797  *
1798  */
1799 static int
load_posixinfo(const char * name,state_t * sp)1800 load_posixinfo(const char *name, state_t *sp)
1801 {
1802 	const char	*stdname;
1803 	const char	*dstname = 0;
1804 	size_t		stdlen;
1805 	size_t		dstlen;
1806 	long		stdoff = 0;
1807 	long		dstoff = 0;
1808 	char		*cp;
1809 	int		i;
1810 	ttinfo_t	*dst;
1811 	ttinfo_t	*std;
1812 	int		quoted;
1813 	zone_rules_t	zonetype;
1814 
1815 
1816 	zonetype = POSIX_USA;
1817 	stdname = name;
1818 
1819 	if ((quoted = (*stdname == '<')) != 0)
1820 		++stdname;
1821 
1822 	/* Parse/extract STD zone name, len and GMT offset */
1823 	if (*name != '\0') {
1824 		if ((name = getzname(name, quoted)) == NULL)
1825 			return (-1);
1826 		stdlen = name - stdname;
1827 		if (*name == '>')
1828 			++name;
1829 		if (*name == '\0' || stdlen < 1) {
1830 			return (-1);
1831 		} else {
1832 			if ((name = getoffset(name, &stdoff)) == NULL)
1833 				return (-1);
1834 		}
1835 	}
1836 
1837 	/* If DST specified in TZ, extract DST zone details */
1838 	if (*name != '\0') {
1839 
1840 		dstname = name;
1841 		if ((quoted = (*dstname == '<')) != 0)
1842 			++dstname;
1843 		if ((name = getzname(name, quoted)) == NULL)
1844 			return (-1);
1845 		dstlen = name - dstname;
1846 		if (dstlen < 1)
1847 			return (-1);
1848 		if (*name == '>')
1849 			++name;
1850 		if (*name != '\0' && *name != ',' && *name != ';') {
1851 			if ((name = getoffset(name, &dstoff)) == NULL)
1852 				return (-1);
1853 		} else {
1854 			dstoff = stdoff - SECSPERHOUR;
1855 		}
1856 
1857 		if (*name != ',' && *name != ';') {
1858 			/* no transtition specified; using default rule */
1859 			if (load_zoneinfo(TZDEFRULES, sp) == 0 &&
1860 			    sp->daylight == 1) {
1861 				/* loading TZDEFRULES zoneinfo succeeded */
1862 				adjust_posix_default(sp, stdoff, dstoff);
1863 			} else {
1864 				/* loading TZDEFRULES zoneinfo failed */
1865 				load_posix_transitions(sp, stdoff, dstoff,
1866 				    zonetype);
1867 			}
1868 		} else {
1869 			/* extract POSIX transitions from TZ */
1870 			/* Backward compatibility using ';' separator */
1871 			int	compat_flag = (*name == ';');
1872 			++name;
1873 			if ((name = getrule(name, &sp->start_rule, compat_flag))
1874 			    == NULL)
1875 				return (-1);
1876 			if (*name++ != ',')
1877 				return (-1);
1878 			if ((name = getrule(name, &sp->end_rule, compat_flag))
1879 			    == NULL)
1880 				return (-1);
1881 			if (*name != '\0')
1882 				return (-1);
1883 			zonetype = POSIX;
1884 			load_posix_transitions(sp, stdoff, dstoff, zonetype);
1885 		}
1886 		dst = &sp->ttis[0];
1887 		std = &sp->ttis[1];
1888 	} else {  /* DST wasn't specified in POSIX TZ */
1889 
1890 		/*  Since we only have STD time, there are no transitions */
1891 		dstlen = 0;
1892 		sp->daylight = 0;
1893 		sp->typecnt = 1;
1894 		sp->timecnt = 0;
1895 		std = &sp->ttis[0];
1896 		std->tt_gmtoff = -stdoff;
1897 		std->tt_isdst = 0;
1898 	}
1899 
1900 	/* Setup zone name character data for state table */
1901 	sp->charcnt = (int)(stdlen + 1);
1902 	if (dstlen != 0)
1903 		sp->charcnt += dstlen + 1;
1904 
1905 	/* If bigger than zone name abbv. buffer, grow it */
1906 	if ((size_t)sp->charcnt > sp->charsbuf_size) {
1907 		if ((cp = libc_realloc(sp->chars, sp->charcnt)) == NULL)
1908 			return (-1);
1909 		sp->chars = cp;
1910 		sp->charsbuf_size = sp->charcnt;
1911 	}
1912 
1913 	/*
1914 	 * Copy zone name text null-terminatedly into state table.
1915 	 * By doing the copy once during zone loading, setting
1916 	 * tzname[] subsequently merely involves setting pointer
1917 	 *
1918 	 * If either or both std. or alt. zone name < 3 chars,
1919 	 * space pad the deficient name(s) to right.
1920 	 */
1921 
1922 	std->tt_abbrind = 0;
1923 	cp = sp->chars;
1924 	(void) strncpy(cp, stdname, stdlen);
1925 	while (stdlen < 3)
1926 		cp[stdlen++] = ' ';
1927 	cp[stdlen] = '\0';
1928 
1929 	i = (int)(stdlen + 1);
1930 	if (dstlen != 0) {
1931 		dst->tt_abbrind = i;
1932 		cp += i;
1933 		(void) strncpy(cp, dstname, dstlen);
1934 		while (dstlen < 3)
1935 			cp[dstlen++] = ' ';
1936 		cp[dstlen] = '\0';
1937 	}
1938 
1939 	/* Save default values */
1940 	if (sp->typecnt == 1) {
1941 		sp->default_timezone = stdoff;
1942 		sp->default_altzone = stdoff;
1943 		sp->default_tzname0 = &sp->chars[0];
1944 		sp->default_tzname1 = _tz_spaces;
1945 	} else {
1946 		sp->default_timezone = -std->tt_gmtoff;
1947 		sp->default_altzone = -dst->tt_gmtoff;
1948 		sp->default_tzname0 = &sp->chars[std->tt_abbrind];
1949 		sp->default_tzname1 = &sp->chars[dst->tt_abbrind];
1950 	}
1951 
1952 	sp->zonerules = zonetype;
1953 
1954 	return (0);
1955 }
1956 
1957 /*
1958  * We loaded the TZDEFAULT which usually the one in US zones. We
1959  * adjust the GMT offset for the zone which has stdoff/dstoff
1960  * offset.
1961  */
1962 static void
adjust_posix_default(state_t * sp,long stdoff,long dstoff)1963 adjust_posix_default(state_t *sp, long stdoff, long dstoff)
1964 {
1965 	long	zone_stdoff = 0;
1966 	long	zone_dstoff = 0;
1967 	int	zone_stdoff_flag = 0;
1968 	int	zone_dstoff_flag = 0;
1969 	int	isdst;
1970 	int	i;
1971 
1972 	/*
1973 	 * Initial values of zone_stdoff and zone_dstoff
1974 	 */
1975 	for (i = 0; (zone_stdoff_flag == 0 || zone_dstoff_flag == 0) &&
1976 	    i < sp->timecnt; i++) {
1977 		ttinfo_t	*zone;
1978 
1979 		zone = &sp->ttis[sp->types[i]];
1980 
1981 		if (zone_stdoff_flag == 0 && zone->tt_isdst == 0) {
1982 			zone_stdoff = -zone->tt_gmtoff;
1983 			zone_stdoff_flag = 1;
1984 		} else if (zone_dstoff_flag == 0 && zone->tt_isdst != 0) {
1985 			zone_dstoff = -zone->tt_gmtoff;
1986 			zone_dstoff_flag = 1;
1987 		}
1988 	}
1989 	if (zone_dstoff_flag == 0)
1990 		zone_dstoff = zone_stdoff;
1991 
1992 	/*
1993 	 * Initially we're assumed to be in standard time.
1994 	 */
1995 	isdst = 0;
1996 
1997 	for (i = 0; i < sp->timecnt; i++) {
1998 		ttinfo_t	*zone;
1999 		int	next_isdst;
2000 
2001 		zone = &sp->ttis[sp->types[i]];
2002 		next_isdst = zone->tt_isdst;
2003 
2004 		sp->types[i] = next_isdst ? 0 : 1;
2005 
2006 		if (zone->tt_ttisgmt == 0) {
2007 			/*
2008 			 * If summer time is in effect, and the transition time
2009 			 * was not specified as standard time, add the summer
2010 			 * time offset to the transition time;
2011 			 * otherwise, add the standard time offset to the
2012 			 * transition time.
2013 			 */
2014 			/*
2015 			 * Transitions from DST to DDST will effectively
2016 			 * disappear since POSIX provides for only one DST
2017 			 * offset.
2018 			 */
2019 			if (isdst != 0 && zone->tt_ttisstd == 0)
2020 				sp->ats[i] += dstoff - zone_dstoff;
2021 			else
2022 				sp->ats[i] += stdoff - zone_stdoff;
2023 		}
2024 		if (next_isdst != 0)
2025 			zone_dstoff = -zone->tt_gmtoff;
2026 		else
2027 			zone_stdoff = -zone->tt_gmtoff;
2028 		isdst = next_isdst;
2029 	}
2030 	/*
2031 	 * Finally, fill in ttis.
2032 	 * ttisstd and ttisgmt need not be handled.
2033 	 */
2034 	sp->ttis[0].tt_gmtoff = -dstoff;
2035 	sp->ttis[0].tt_isdst = 1;
2036 	sp->ttis[1].tt_gmtoff = -stdoff;
2037 	sp->ttis[1].tt_isdst = 0;
2038 	sp->typecnt = 2;
2039 	sp->daylight = 1;
2040 }
2041 
2042 /*
2043  *
2044  */
2045 static void
load_posix_transitions(state_t * sp,long stdoff,long dstoff,zone_rules_t zonetype)2046 load_posix_transitions(state_t *sp, long stdoff, long dstoff,
2047     zone_rules_t zonetype)
2048 {
2049 	ttinfo_t	*std, *dst;
2050 	time_t	*tranp;
2051 	uchar_t	*typep;
2052 	prev_t	*prevp;
2053 	int	year;
2054 	int	i;
2055 	long long	janfirst;
2056 	posix_daylight_t	pdaylight;
2057 
2058 	/*
2059 	 * We know STD and DST zones are specified with this timezone
2060 	 * therefore the cache will be set up with 2 transitions per
2061 	 * year transitioning to their respective std and dst zones.
2062 	 */
2063 	sp->daylight = 1;
2064 	sp->typecnt = 2;
2065 	sp->timecnt = 272;
2066 
2067 	/*
2068 	 * Insert zone data from POSIX TZ into state table
2069 	 * The Olson public domain POSIX code sets up ttis[0] to be DST,
2070 	 * as we are doing here.  It seems to be the correct behavior.
2071 	 * The US/Pacific zoneinfo file also lists DST as first type.
2072 	 */
2073 
2074 	dst = &sp->ttis[0];
2075 	dst->tt_gmtoff = -dstoff;
2076 	dst->tt_isdst = 1;
2077 
2078 	std = &sp->ttis[1];
2079 	std->tt_gmtoff = -stdoff;
2080 	std->tt_isdst = 0;
2081 
2082 	sp->prev[0].std = NULL;
2083 	sp->prev[0].alt = NULL;
2084 
2085 	/* Create transition data based on POSIX TZ */
2086 	tranp = sp->ats;
2087 	prevp  = &sp->prev[1];
2088 	typep  = sp->types;
2089 
2090 	/*
2091 	 * We only cache from 1902 to 2037 to avoid transistions
2092 	 * that wrap at the 32-bit boundries, since 1901 and 2038
2093 	 * are not full years in 32-bit time.  The rough edges
2094 	 * will be handled as transition cache misses.
2095 	 */
2096 
2097 	janfirst = JAN_01_1902;
2098 
2099 	pdaylight.rules[0] = &sp->start_rule;
2100 	pdaylight.rules[1] = &sp->end_rule;
2101 	pdaylight.offset[0] = stdoff;
2102 	pdaylight.offset[1] = dstoff;
2103 
2104 	for (i = MAX_RULE_TABLE; i >= 0; i--) {
2105 		if (zonetype == POSIX_USA) {
2106 			pdaylight.rules[0] = (rule_t *)&__usa_rules[i].start;
2107 			pdaylight.rules[1] = (rule_t *)&__usa_rules[i].end;
2108 		}
2109 		for (year = __usa_rules[i].s_year;
2110 		    year <= __usa_rules[i].e_year; year++) {
2111 			int	idx, ridx;
2112 			idx = posix_daylight(&janfirst, year, &pdaylight);
2113 			ridx = !idx;
2114 
2115 			/*
2116 			 * Two transitions per year. Since there are
2117 			 * only two zone types for this POSIX zone,
2118 			 * previous std and alt are always set to
2119 			 * &ttis[0] and &ttis[1].
2120 			 */
2121 			*tranp++ = (time_t)pdaylight.rtime[idx];
2122 			*typep++ = idx;
2123 			prevp->std = std;
2124 			prevp->alt = dst;
2125 			++prevp;
2126 
2127 			*tranp++ = (time_t)pdaylight.rtime[ridx];
2128 			*typep++ = ridx;
2129 			prevp->std = std;
2130 			prevp->alt = dst;
2131 			++prevp;
2132 		}
2133 	}
2134 }
2135 
2136 /*
2137  * Given a pointer into a time zone string, scan until a character that is not
2138  * a valid character in a zone name is found.  Return ptr to that character.
2139  * Return NULL if error (ie. non-printable character located in name)
2140  */
2141 static const char *
getzname(const char * strp,int quoted)2142 getzname(const char *strp, int quoted)
2143 {
2144 	char	c;
2145 
2146 	if (quoted) {
2147 		while ((c = *strp) != '\0' && c != '>' &&
2148 		    isgraph((unsigned char)c)) {
2149 			++strp;
2150 		}
2151 	} else {
2152 		while ((c = *strp) != '\0' && isgraph((unsigned char)c) &&
2153 		    !isdigit((unsigned char)c) && c != ',' && c != '-' &&
2154 		    c != '+') {
2155 			++strp;
2156 		}
2157 	}
2158 
2159 	/* Found an excessively invalid character.  Discredit whole name */
2160 	if (c != '\0' && !isgraph((unsigned char)c))
2161 		return (NULL);
2162 
2163 	return (strp);
2164 }
2165 
2166 /*
2167  * Given pointer into time zone string, extract first
2168  * number pointed to.  Validate number within range specified,
2169  * Return ptr to first char following valid numeric sequence.
2170  */
2171 static const char *
getnum(const char * strp,int * nump,int min,int max)2172 getnum(const char *strp, int *nump, int min, int max)
2173 {
2174 	char	c;
2175 	int	num;
2176 
2177 	if (strp == NULL || !isdigit((unsigned char)(c = *strp)))
2178 		return (NULL);
2179 	num = 0;
2180 	do {
2181 		num = num * 10 + (c - '0');
2182 		if (num > max)
2183 			return (NULL);	/* illegal value */
2184 		c = *++strp;
2185 	} while (isdigit((unsigned char)c));
2186 	if (num < min)
2187 		return (NULL);		/* illegal value */
2188 	*nump = num;
2189 	return (strp);
2190 }
2191 
2192 /*
2193  * Given a pointer into a time zone string, extract a number of seconds,
2194  * in hh[:mm[:ss]] form, from the string.  If an error occurs, return NULL,
2195  * otherwise, return a pointer to the first character not part of the number
2196  * of seconds.
2197  */
2198 static const char *
getsecs(const char * strp,long * secsp)2199 getsecs(const char *strp, long *secsp)
2200 {
2201 	int	num;
2202 
2203 	/*
2204 	 * `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
2205 	 * "M10.4.6/26", which does not conform to Posix,
2206 	 * but which specifies the equivalent of
2207 	 * ``02:00 on the first Sunday on or after 23 Oct''.
2208 	 */
2209 	strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
2210 	if (strp == NULL)
2211 		return (NULL);
2212 	*secsp = num * (long)SECSPERHOUR;
2213 	if (*strp == ':') {
2214 		++strp;
2215 		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
2216 		if (strp == NULL)
2217 			return (NULL);
2218 		*secsp += num * SECSPERMIN;
2219 		if (*strp == ':') {
2220 			++strp;
2221 			/* `SECSPERMIN' allows for leap seconds.  */
2222 			strp = getnum(strp, &num, 0, SECSPERMIN);
2223 			if (strp == NULL)
2224 				return (NULL);
2225 			*secsp += num;
2226 		}
2227 	}
2228 	return (strp);
2229 }
2230 
2231 /*
2232  * Given a pointer into a time zone string, extract an offset, in
2233  * [+-]hh[:mm[:ss]] form, from the string.
2234  * If any error occurs, return NULL.
2235  * Otherwise, return a pointer to the first character not part of the time.
2236  */
2237 static const char *
getoffset(const char * strp,long * offsetp)2238 getoffset(const char *strp, long *offsetp)
2239 {
2240 	int	neg = 0;
2241 
2242 	if (*strp == '-') {
2243 		neg = 1;
2244 		++strp;
2245 	} else if (*strp == '+') {
2246 		++strp;
2247 	}
2248 	strp = getsecs(strp, offsetp);
2249 	if (strp == NULL)
2250 		return (NULL);		/* illegal time */
2251 	if (neg)
2252 		*offsetp = -*offsetp;
2253 	return (strp);
2254 }
2255 
2256 /*
2257  * Given a pointer into a time zone string, extract a rule in the form
2258  * date[/time].  See POSIX section 8 for the format of "date" and "time".
2259  * If a valid rule is not found, return NULL.
2260  * Otherwise, return a pointer to the first character not part of the rule.
2261  *
2262  * If compat_flag is set, support old 1-based day of year values.
2263  */
2264 static const char *
getrule(const char * strp,rule_t * rulep,int compat_flag)2265 getrule(const char *strp, rule_t *rulep, int compat_flag)
2266 {
2267 	if (compat_flag == 0 && *strp == 'M') {
2268 		/*
2269 		 * Month, week, day.
2270 		 */
2271 		rulep->r_type = MON_WEEK_DOW;
2272 		++strp;
2273 		strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
2274 		if (strp == NULL)
2275 			return (NULL);
2276 		if (*strp++ != '.')
2277 			return (NULL);
2278 		strp = getnum(strp, &rulep->r_week, 1, 5);
2279 		if (strp == NULL)
2280 			return (NULL);
2281 		if (*strp++ != '.')
2282 			return (NULL);
2283 		strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
2284 	} else if (compat_flag == 0 && *strp == 'J') {
2285 		/*
2286 		 * Julian day.
2287 		 */
2288 		rulep->r_type = JULIAN_DAY;
2289 		++strp;
2290 		strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
2291 
2292 	} else if (isdigit((unsigned char)*strp)) {
2293 		/*
2294 		 * Day of year.
2295 		 */
2296 		rulep->r_type = DAY_OF_YEAR;
2297 		if (compat_flag == 0) {
2298 			/* zero-based day of year */
2299 			strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
2300 		} else {
2301 			/* one-based day of year */
2302 			strp = getnum(strp, &rulep->r_day, 1, DAYSPERLYEAR);
2303 			rulep->r_day--;
2304 		}
2305 	} else {
2306 		return (NULL);		/* ZONERULES_INVALID format */
2307 	}
2308 	if (strp == NULL)
2309 		return (NULL);
2310 	if (*strp == '/') {
2311 		/*
2312 		 * Time specified.
2313 		 */
2314 		++strp;
2315 		strp = getsecs(strp, &rulep->r_time);
2316 	} else	{
2317 		rulep->r_time = 2 * SECSPERHOUR;	/* default = 2:00:00 */
2318 	}
2319 	return (strp);
2320 }
2321 
2322 /*
2323  * Returns default value for TZ as specified in /etc/default/init file, if
2324  * a default value for TZ is provided there.
2325  */
2326 static char *
get_default_tz(void)2327 get_default_tz(void)
2328 {
2329 	char	*tz = NULL;
2330 	uchar_t	*tzp, *tzq;
2331 	int	flags;
2332 	void	*defp;
2333 
2334 	assert_no_libc_locks_held();
2335 
2336 	if ((defp = defopen_r(TIMEZONE)) != NULL) {
2337 		flags = defcntl_r(DC_GETFLAGS, 0, defp);
2338 		TURNON(flags, DC_STRIP_QUOTES);
2339 		(void) defcntl_r(DC_SETFLAGS, flags, defp);
2340 
2341 		if ((tzp = (uchar_t *)defread_r(TZSTRING, defp)) != NULL) {
2342 			while (isspace(*tzp))
2343 				tzp++;
2344 			tzq = tzp;
2345 			while (!isspace(*tzq) &&
2346 			    *tzq != ';' &&
2347 			    *tzq != '#' &&
2348 			    *tzq != '\0')
2349 				tzq++;
2350 			*tzq = '\0';
2351 			if (*tzp != '\0')
2352 				tz = libc_strdup((char *)tzp);
2353 		}
2354 
2355 		defclose_r(defp);
2356 	}
2357 	return (tz);
2358 }
2359 
2360 /*
2361  * Purge all cache'd state_t
2362  */
2363 static void
purge_zone_cache(void)2364 purge_zone_cache(void)
2365 {
2366 	int	hashid;
2367 	state_t	*p, *n, *r;
2368 
2369 	/*
2370 	 * Create a single list of caches which are detached
2371 	 * from hash table.
2372 	 */
2373 	r = NULL;
2374 	for (hashid = 0; hashid < HASHTABLE; hashid++) {
2375 		for (p = tzcache[hashid]; p != NULL; p = n) {
2376 			n = p->next;
2377 			p->next = r;
2378 			r = p;
2379 		}
2380 		tzcache[hashid] = NULL;
2381 	}
2382 	namecache = NULL;
2383 
2384 	/* last_tzname[] may point cache being freed */
2385 	last_tzname[0] = NULL;
2386 	last_tzname[1] = NULL;
2387 
2388 	/* We'll reload system TZ as well */
2389 	systemTZ = NULL;
2390 
2391 	/*
2392 	 * Hash table has been cleared, and all elements are detached from
2393 	 * the hash table. Now we are safe to release _time_lock.
2394 	 * We need to unlock _time_lock because we need to call out to
2395 	 * free().
2396 	 */
2397 	lmutex_unlock(&_time_lock);
2398 
2399 	assert_no_libc_locks_held();
2400 
2401 	while (r != NULL) {
2402 		n = r->next;
2403 		libc_free((char *)r->zonename);
2404 		libc_free((char *)r->chars);
2405 		free(r);
2406 		r = n;
2407 	}
2408 
2409 	lmutex_lock(&_time_lock);
2410 }
2411 
2412 /*
2413  * When called first time, open the counter device and load
2414  * the initial value. If counter is updated, copy value to
2415  * private memory.
2416  */
2417 static void
reload_counter(void)2418 reload_counter(void)
2419 {
2420 	int	fd;
2421 	caddr_t	addr;
2422 
2423 	if (zoneinfo_seqadr != &zoneinfo_seqno_init) {
2424 		zoneinfo_seqno = *zoneinfo_seqadr;
2425 		return;
2426 	}
2427 
2428 	if ((fd = open(TZSYNC_FILE, O_RDONLY)) < 0)
2429 		return;
2430 
2431 	addr = mmap(0, sizeof (uint32_t), PROT_READ, MAP_SHARED, fd, 0);
2432 	(void) close(fd);
2433 
2434 	if (addr == MAP_FAILED)
2435 		return;
2436 	/*LINTED*/
2437 	zoneinfo_seqadr = (uint32_t *)addr;
2438 	zoneinfo_seqno = *zoneinfo_seqadr;
2439 }
2440 
2441 /*
2442  * getsystemTZ() returns the TZ value if it is set in the environment, or
2443  * it returns the system TZ;  if the systemTZ has not yet been set, or
2444  * cleared by tzreload, get_default_tz() is called to read the
2445  * /etc/default/init file to get the value.
2446  */
2447 static const char *
getsystemTZ()2448 getsystemTZ()
2449 {
2450 	tznmlist_t *tzn;
2451 	char	*tz;
2452 
2453 	tz = getenv("TZ");
2454 	if (tz != NULL && *tz != '\0')
2455 		return ((const char *)tz);
2456 
2457 	if (systemTZ != NULL)
2458 		return (systemTZ);
2459 
2460 	/*
2461 	 * get_default_tz calls out stdio functions via defread.
2462 	 */
2463 	lmutex_unlock(&_time_lock);
2464 	tz = get_default_tz();
2465 	lmutex_lock(&_time_lock);
2466 
2467 	if (tz == NULL) {
2468 		/* no TZ entry in the file */
2469 		systemTZ = _posix_gmt0;
2470 		return (systemTZ);
2471 	}
2472 
2473 	/*
2474 	 * look up timezone used previously. We will not free the
2475 	 * old timezone name, because ltzset_u() can release _time_lock
2476 	 * while it has references to systemTZ (via zonename). If we
2477 	 * free the systemTZ, the reference via zonename can access
2478 	 * invalid memory when systemTZ is reset.
2479 	 */
2480 	for (tzn = systemTZrec; tzn != NULL; tzn = tzn->link) {
2481 		if (strcmp(tz, tzn->name) == 0)
2482 			break;
2483 	}
2484 	if (tzn == NULL) {
2485 		/* This is new timezone name */
2486 		tzn = lmalloc(sizeof (tznmlist_t *) + strlen(tz) + 1);
2487 		(void) strcpy(tzn->name, tz);
2488 		tzn->link = systemTZrec;
2489 		systemTZrec = tzn;
2490 	}
2491 
2492 	libc_free(tz);
2493 
2494 	return (systemTZ = tzn->name);
2495 }
2496 
2497 /*
2498  * tzname[] is the user visible string which applications may have
2499  * references. Even though TZ was changed, references to the old tzname
2500  * may continue to remain in the application, and those references need
2501  * to be valid. They were valid by our implementation because strings being
2502  * pointed by tzname were never be freed nor altered by the change of TZ.
2503  * However, this will no longer be the case.
2504  *
2505  * state_t is now freed when cache is purged. Therefore, reading string
2506  * from old tzname[] addr may end up with accessing a stale data(freed area).
2507  * To avoid this, we maintain a copy of all timezone name strings which will
2508  * never be freed, and tzname[] will point those copies.
2509  *
2510  */
2511 static int
set_one_tzname(const char * name,int idx)2512 set_one_tzname(const char *name, int idx)
2513 {
2514 	const unsigned char *nm;
2515 	int	hashid, i;
2516 	char	*s;
2517 	tznmlist_t *tzn;
2518 
2519 	if (name == _tz_gmt || name == _tz_spaces) {
2520 		tzname[idx] = (char *)name;
2521 		return (0);
2522 	}
2523 
2524 	nm = (const unsigned char *)name;
2525 	hashid = (nm[0] * 29 + nm[1] * 3) % TZNMC_SZ;
2526 	for (tzn = tznmhash[hashid]; tzn != NULL; tzn = tzn->link) {
2527 		s = tzn->name;
2528 		/* do the strcmp() */
2529 		for (i = 0; s[i] == name[i]; i++) {
2530 			if (s[i] == '\0') {
2531 				tzname[idx] = tzn->name;
2532 				return (0);
2533 			}
2534 		}
2535 	}
2536 	/*
2537 	 * allocate new entry. This entry is never freed, so use lmalloc
2538 	 */
2539 	tzn = lmalloc(sizeof (tznmlist_t *) + strlen(name) + 1);
2540 	if (tzn == NULL)
2541 		return (1);
2542 
2543 	(void) strcpy(tzn->name, name);
2544 
2545 	/* link it */
2546 	tzn->link = tznmhash[hashid];
2547 	tznmhash[hashid] = tzn;
2548 
2549 	tzname[idx] = tzn->name;
2550 	return (0);
2551 }
2552 
2553 /*
2554  * Set tzname[] after testing parameter to see if we are setting
2555  * same zone name. If we got same address, it should be same zone
2556  * name as tzname[], unless cache have been purged.
2557  * Note, purge_zone_cache() resets last_tzname[].
2558  */
2559 static void
set_tzname(const char ** namep)2560 set_tzname(const char **namep)
2561 {
2562 	if (namep[0] != last_tzname[0]) {
2563 		if (set_one_tzname(namep[0], 0)) {
2564 			tzname[0] = (char *)_tz_gmt;
2565 			last_tzname[0] = NULL;
2566 		} else {
2567 			last_tzname[0] = namep[0];
2568 		}
2569 	}
2570 
2571 	if (namep[1] != last_tzname[1]) {
2572 		if (set_one_tzname(namep[1], 1)) {
2573 			tzname[1] = (char *)_tz_spaces;
2574 			last_tzname[1] = NULL;
2575 		} else {
2576 			last_tzname[1] = namep[1];
2577 		}
2578 	}
2579 }
2580