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