localtime.c revision 1.50
1/*	$NetBSD: localtime.c,v 1.50 2010/12/17 23:11:57 christos Exp $	*/
2
3/*
4** This file is in the public domain, so clarified as of
5** 1996-06-05 by Arthur David Olson.
6*/
7
8#include <sys/cdefs.h>
9#if defined(LIBC_SCCS) && !defined(lint)
10#if 0
11static char	elsieid[] = "@(#)localtime.c	8.9";
12#else
13__RCSID("$NetBSD: localtime.c,v 1.50 2010/12/17 23:11:57 christos Exp $");
14#endif
15#endif /* LIBC_SCCS and not lint */
16
17/*
18** Leap second handling from Bradley White.
19** POSIX-style TZ environment variable handling from Guy Harris.
20*/
21
22/*LINTLIBRARY*/
23
24#include "namespace.h"
25#include "private.h"
26#include "tzfile.h"
27#include "fcntl.h"
28#include "reentrant.h"
29
30#if defined(__weak_alias)
31__weak_alias(ctime_r,_ctime_r)
32__weak_alias(ctime_rz,_ctime_rz)
33__weak_alias(daylight,_daylight)
34__weak_alias(mktime_z,_mktime_z)
35__weak_alias(localtime_r,_localtime_r)
36__weak_alias(localtime_rz,_localtime_rz)
37__weak_alias(posix2time,_posix2time)
38__weak_alias(posix2time_z,_posix2time_z)
39__weak_alias(tzname,_tzname)
40#endif
41
42#include "float.h"	/* for FLT_MAX and DBL_MAX */
43
44#ifndef TZ_ABBR_MAX_LEN
45#define TZ_ABBR_MAX_LEN	16
46#endif /* !defined TZ_ABBR_MAX_LEN */
47
48#ifndef TZ_ABBR_CHAR_SET
49#define TZ_ABBR_CHAR_SET \
50	"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
51#endif /* !defined TZ_ABBR_CHAR_SET */
52
53#ifndef TZ_ABBR_ERR_CHAR
54#define TZ_ABBR_ERR_CHAR	'_'
55#endif /* !defined TZ_ABBR_ERR_CHAR */
56
57/*
58** SunOS 4.1.1 headers lack O_BINARY.
59*/
60
61#ifdef O_BINARY
62#define OPEN_MODE	(O_RDONLY | O_BINARY)
63#endif /* defined O_BINARY */
64#ifndef O_BINARY
65#define OPEN_MODE	O_RDONLY
66#endif /* !defined O_BINARY */
67
68#ifndef WILDABBR
69/*
70** Someone might make incorrect use of a time zone abbreviation:
71**	1.	They might reference tzname[0] before calling tzset (explicitly
72**		or implicitly).
73**	2.	They might reference tzname[1] before calling tzset (explicitly
74**		or implicitly).
75**	3.	They might reference tzname[1] after setting to a time zone
76**		in which Daylight Saving Time is never observed.
77**	4.	They might reference tzname[0] after setting to a time zone
78**		in which Standard Time is never observed.
79**	5.	They might reference tm.TM_ZONE after calling offtime.
80** What's best to do in the above cases is open to debate;
81** for now, we just set things up so that in any of the five cases
82** WILDABBR is used. Another possibility: initialize tzname[0] to the
83** string "tzname[0] used before set", and similarly for the other cases.
84** And another: initialize tzname[0] to "ERA", with an explanation in the
85** manual page of what this "time zone abbreviation" means (doing this so
86** that tzname[0] has the "normal" length of three characters).
87*/
88#define WILDABBR	"   "
89#endif /* !defined WILDABBR */
90
91static const char	wildabbr[] = WILDABBR;
92
93static char		gmt[] = "GMT";
94
95/*
96** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
97** We default to US rules as of 1999-08-17.
98** POSIX 1003.1 section 8.1.1 says that the default DST rules are
99** implementation dependent; for historical reasons, US rules are a
100** common default.
101*/
102#ifndef TZDEFRULESTRING
103#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
104#endif /* !defined TZDEFDST */
105
106struct ttinfo {				/* time type information */
107	long		tt_gmtoff;	/* UTC offset in seconds */
108	int		tt_isdst;	/* used to set tm_isdst */
109	int		tt_abbrind;	/* abbreviation list index */
110	int		tt_ttisstd;	/* TRUE if transition is std time */
111	int		tt_ttisgmt;	/* TRUE if transition is UTC */
112};
113
114struct lsinfo {				/* leap second information */
115	time_t		ls_trans;	/* transition time */
116	long		ls_corr;	/* correction to apply */
117};
118
119#define BIGGEST(a, b)	(((a) > (b)) ? (a) : (b))
120
121#ifdef TZNAME_MAX
122#define MY_TZNAME_MAX	TZNAME_MAX
123#endif /* defined TZNAME_MAX */
124#ifndef TZNAME_MAX
125#define MY_TZNAME_MAX	255
126#endif /* !defined TZNAME_MAX */
127
128struct __state {
129	int		leapcnt;
130	int		timecnt;
131	int		typecnt;
132	int		charcnt;
133	int		goback;
134	int		goahead;
135	time_t		ats[TZ_MAX_TIMES];
136	unsigned char	types[TZ_MAX_TIMES];
137	struct ttinfo	ttis[TZ_MAX_TYPES];
138	char		chars[/*CONSTCOND*/BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
139				(2 * (MY_TZNAME_MAX + 1)))];
140	struct lsinfo	lsis[TZ_MAX_LEAPS];
141};
142
143struct rule {
144	int		r_type;		/* type of rule--see below */
145	int		r_day;		/* day number of rule */
146	int		r_week;		/* week number of rule */
147	int		r_mon;		/* month number of rule */
148	long		r_time;		/* transition time of rule */
149};
150
151#define JULIAN_DAY		0	/* Jn - Julian day */
152#define DAY_OF_YEAR		1	/* n - day of year */
153#define MONTH_NTH_DAY_OF_WEEK	2	/* Mm.n.d - month, week, day of week */
154
155typedef struct tm *(*subfun_t)(const timezone_t sp, const time_t *timep,
156			       long offset, struct tm *tmp);
157
158/*
159** Prototypes for static functions.
160*/
161
162static long		detzcode(const char * codep);
163static time_t		detzcode64(const char * codep);
164static int		differ_by_repeat(time_t t1, time_t t0);
165static const char *	getzname(const char * strp);
166static const char *	getqzname(const char * strp, const int delim);
167static const char *	getnum(const char * strp, int * nump, int min,
168				int max);
169static const char *	getsecs(const char * strp, long * secsp);
170static const char *	getoffset(const char * strp, long * offsetp);
171static const char *	getrule(const char * strp, struct rule * rulep);
172static void		gmtload(timezone_t sp);
173static struct tm *	gmtsub(const timezone_t sp, const time_t *timep,
174				long offset, struct tm * tmp);
175static struct tm *	localsub(const timezone_t sp, const time_t *timep,
176				long offset, struct tm *tmp);
177static int		increment_overflow(int * number, int delta);
178static int		leaps_thru_end_of(int y);
179static int		long_increment_overflow(long * number, int delta);
180static int		long_normalize_overflow(long * tensptr,
181				int * unitsptr, int base);
182static int		normalize_overflow(int * tensptr, int * unitsptr,
183				int base);
184static void		settzname(void);
185static time_t		time1(const timezone_t sp, struct tm * const tmp,
186				subfun_t funcp, long offset);
187static time_t		time2(const timezone_t sp, struct tm * const tmp,
188				subfun_t funcp,
189				const long offset, int *const okayp);
190static time_t		time2sub(const timezone_t sp, struct tm * consttmp,
191				subfun_t funcp, const long offset,
192				int *const okayp, const int do_norm_secs);
193static struct tm *	timesub(const timezone_t sp, const time_t * timep,
194				long offset, struct tm * tmp);
195static int		tmcomp(const struct tm * atmp,
196				const struct tm * btmp);
197static time_t		transtime(time_t janfirst, int year,
198				const struct rule * rulep, long offset);
199static int		typesequiv(const timezone_t sp, int a, int b);
200static int		tzload(timezone_t sp, const char * name,
201				int doextend);
202static int		tzparse(timezone_t sp, const char * name,
203				int lastditch);
204static void		tzset_unlocked(void);
205static void		tzsetwall_unlocked(void);
206static long		leapcorr(const timezone_t sp, time_t * timep);
207
208static timezone_t lclptr;
209static timezone_t gmtptr;
210
211#ifndef TZ_STRLEN_MAX
212#define TZ_STRLEN_MAX 255
213#endif /* !defined TZ_STRLEN_MAX */
214
215static char		lcl_TZname[TZ_STRLEN_MAX + 1];
216static int		lcl_is_set;
217static int		gmt_is_set;
218
219#if !defined(__LIBC12_SOURCE__)
220
221__aconst char *		tzname[2] = {
222	(__aconst char *)__UNCONST(wildabbr),
223	(__aconst char *)__UNCONST(wildabbr)
224};
225
226#else
227
228extern __aconst char *	tzname[2];
229
230#endif
231
232#ifdef _REENTRANT
233static rwlock_t lcl_lock = RWLOCK_INITIALIZER;
234#endif
235
236/*
237** Section 4.12.3 of X3.159-1989 requires that
238**	Except for the strftime function, these functions [asctime,
239**	ctime, gmtime, localtime] return values in one of two static
240**	objects: a broken-down time structure and an array of char.
241** Thanks to Paul Eggert for noting this.
242*/
243
244static struct tm	tm;
245
246#ifdef USG_COMPAT
247#if !defined(__LIBC12_SOURCE__)
248long 			timezone = 0;
249int			daylight = 0;
250#else
251extern int		daylight;
252extern long		timezone __RENAME(__timezone13);
253#endif
254#endif /* defined USG_COMPAT */
255
256#ifdef ALTZONE
257time_t			altzone = 0;
258#endif /* defined ALTZONE */
259
260static long
261detzcode(const char *const codep)
262{
263	long	result;
264	int	i;
265
266	result = (codep[0] & 0x80) ? ~0L : 0;
267	for (i = 0; i < 4; ++i)
268		result = (result << 8) | (codep[i] & 0xff);
269	return result;
270}
271
272static time_t
273detzcode64(const char *const codep)
274{
275	time_t	result;
276	int	i;
277
278	result = (codep[0] & 0x80) ? -1 : 0;
279	for (i = 0; i < 8; ++i)
280		result = result * 256 + (codep[i] & 0xff);
281	return result;
282}
283
284const char *
285tzgetname(const timezone_t sp, int isdst)
286{
287	int i;
288	for (i = 0; i < sp->timecnt; ++i) {
289		const struct ttinfo *const ttisp = &sp->ttis[sp->types[i]];
290
291		if (ttisp->tt_isdst == isdst)
292			return &sp->chars[ttisp->tt_abbrind];
293	}
294	return NULL;
295}
296
297static void
298settzname_z(timezone_t sp)
299{
300	int			i;
301
302	/*
303	** Scrub the abbreviations.
304	** First, replace bogus characters.
305	*/
306	for (i = 0; i < sp->charcnt; ++i)
307		if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
308			sp->chars[i] = TZ_ABBR_ERR_CHAR;
309	/*
310	** Second, truncate long abbreviations.
311	*/
312	for (i = 0; i < sp->typecnt; ++i) {
313		const struct ttinfo * const	ttisp = &sp->ttis[i];
314		char *				cp = &sp->chars[ttisp->tt_abbrind];
315
316		if (strlen(cp) > TZ_ABBR_MAX_LEN &&
317			strcmp(cp, GRANDPARENTED) != 0)
318				*(cp + TZ_ABBR_MAX_LEN) = '\0';
319	}
320}
321
322static void
323settzname(void)
324{
325	timezone_t const	sp = lclptr;
326	int			i;
327
328	tzname[0] = (__aconst char *)__UNCONST(wildabbr);
329	tzname[1] = (__aconst char *)__UNCONST(wildabbr);
330#ifdef USG_COMPAT
331	daylight = 0;
332	timezone = 0;
333#endif /* defined USG_COMPAT */
334#ifdef ALTZONE
335	altzone = 0;
336#endif /* defined ALTZONE */
337	if (sp == NULL) {
338		tzname[0] = tzname[1] = (__aconst char *)__UNCONST(gmt);
339		return;
340	}
341	for (i = 0; i < sp->typecnt; ++i) {
342		const struct ttinfo * const	ttisp = &sp->ttis[i];
343
344		tzname[ttisp->tt_isdst] =
345			&sp->chars[ttisp->tt_abbrind];
346#ifdef USG_COMPAT
347		if (ttisp->tt_isdst)
348			daylight = 1;
349		if (i == 0 || !ttisp->tt_isdst)
350			timezone = -(ttisp->tt_gmtoff);
351#endif /* defined USG_COMPAT */
352#ifdef ALTZONE
353		if (i == 0 || ttisp->tt_isdst)
354			altzone = -(ttisp->tt_gmtoff);
355#endif /* defined ALTZONE */
356	}
357	/*
358	** And to get the latest zone names into tzname. . .
359	*/
360	for (i = 0; i < sp->timecnt; ++i) {
361		register const struct ttinfo * const	ttisp =
362							&sp->ttis[
363								sp->types[i]];
364
365		tzname[ttisp->tt_isdst] =
366			&sp->chars[ttisp->tt_abbrind];
367	}
368	settzname_z(sp);
369}
370
371static int
372differ_by_repeat(const time_t t1, const time_t t0)
373{
374/* CONSTCOND */
375	if (TYPE_INTEGRAL(time_t) &&
376		TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
377			return 0;
378	return (int_fast64_t)t1 - (int_fast64_t)t0 == SECSPERREPEAT;
379}
380
381static int
382tzload(timezone_t sp, const char *name, const int doextend)
383{
384	const char *		p;
385	int			i;
386	int			fid;
387	int			stored;
388	int			nread;
389	union {
390		struct tzhead	tzhead;
391		char		buf[2 * sizeof(struct tzhead) +
392					2 * sizeof *sp +
393					4 * TZ_MAX_TIMES];
394	} u;
395
396	sp->goback = sp->goahead = FALSE;
397	if (name == NULL && (name = TZDEFAULT) == NULL)
398		return -1;
399	{
400		int	doaccess;
401		/*
402		** Section 4.9.1 of the C standard says that
403		** "FILENAME_MAX expands to an integral constant expression
404		** that is the size needed for an array of char large enough
405		** to hold the longest file name string that the implementation
406		** guarantees can be opened."
407		*/
408		char		fullname[FILENAME_MAX + 1];
409
410		if (name[0] == ':')
411			++name;
412		doaccess = name[0] == '/';
413		if (!doaccess) {
414			if ((p = TZDIR) == NULL)
415				return -1;
416			if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
417				return -1;
418			(void) strcpy(fullname, p);	/* XXX strcpy is safe */
419			(void) strcat(fullname, "/");	/* XXX strcat is safe */
420			(void) strcat(fullname, name);	/* XXX strcat is safe */
421			/*
422			** Set doaccess if '.' (as in "../") shows up in name.
423			*/
424			if (strchr(name, '.') != NULL)
425				doaccess = TRUE;
426			name = fullname;
427		}
428		if (doaccess && access(name, R_OK) != 0)
429			return -1;
430		/*
431		 * XXX potential security problem here if user of a set-id
432		 * program has set TZ (which is passed in as name) here,
433		 * and uses a race condition trick to defeat the access(2)
434		 * above.
435		 */
436		if ((fid = open(name, OPEN_MODE)) == -1)
437			return -1;
438	}
439	nread = read(fid, u.buf, sizeof u.buf);
440	if (close(fid) < 0 || nread <= 0)
441		return -1;
442	for (stored = 4; stored <= 8; stored *= 2) {
443		int		ttisstdcnt;
444		int		ttisgmtcnt;
445
446		ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
447		ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
448		sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
449		sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
450		sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
451		sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
452		p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
453		if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
454			sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
455			sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
456			sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
457			(ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
458			(ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
459				return -1;
460		if (nread - (p - u.buf) <
461			sp->timecnt * stored +		/* ats */
462			sp->timecnt +			/* types */
463			sp->typecnt * 6 +		/* ttinfos */
464			sp->charcnt +			/* chars */
465			sp->leapcnt * (stored + 4) +	/* lsinfos */
466			ttisstdcnt +			/* ttisstds */
467			ttisgmtcnt)			/* ttisgmts */
468				return -1;
469		for (i = 0; i < sp->timecnt; ++i) {
470			sp->ats[i] = (stored == 4) ?
471				detzcode(p) : detzcode64(p);
472			p += stored;
473		}
474		for (i = 0; i < sp->timecnt; ++i) {
475			sp->types[i] = (unsigned char) *p++;
476			if (sp->types[i] >= sp->typecnt)
477				return -1;
478		}
479		for (i = 0; i < sp->typecnt; ++i) {
480			struct ttinfo *	ttisp;
481
482			ttisp = &sp->ttis[i];
483			ttisp->tt_gmtoff = detzcode(p);
484			p += 4;
485			ttisp->tt_isdst = (unsigned char) *p++;
486			if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
487				return -1;
488			ttisp->tt_abbrind = (unsigned char) *p++;
489			if (ttisp->tt_abbrind < 0 ||
490				ttisp->tt_abbrind > sp->charcnt)
491					return -1;
492		}
493		for (i = 0; i < sp->charcnt; ++i)
494			sp->chars[i] = *p++;
495		sp->chars[i] = '\0';	/* ensure '\0' at end */
496		for (i = 0; i < sp->leapcnt; ++i) {
497			struct lsinfo *	lsisp;
498
499			lsisp = &sp->lsis[i];
500			lsisp->ls_trans = (stored == 4) ?
501				detzcode(p) : detzcode64(p);
502			p += stored;
503			lsisp->ls_corr = detzcode(p);
504			p += 4;
505		}
506		for (i = 0; i < sp->typecnt; ++i) {
507			struct ttinfo *	ttisp;
508
509			ttisp = &sp->ttis[i];
510			if (ttisstdcnt == 0)
511				ttisp->tt_ttisstd = FALSE;
512			else {
513				ttisp->tt_ttisstd = *p++;
514				if (ttisp->tt_ttisstd != TRUE &&
515					ttisp->tt_ttisstd != FALSE)
516						return -1;
517			}
518		}
519		for (i = 0; i < sp->typecnt; ++i) {
520			struct ttinfo *	ttisp;
521
522			ttisp = &sp->ttis[i];
523			if (ttisgmtcnt == 0)
524				ttisp->tt_ttisgmt = FALSE;
525			else {
526				ttisp->tt_ttisgmt = *p++;
527				if (ttisp->tt_ttisgmt != TRUE &&
528					ttisp->tt_ttisgmt != FALSE)
529						return -1;
530			}
531		}
532		/*
533		** Out-of-sort ats should mean we're running on a
534		** signed time_t system but using a data file with
535		** unsigned values (or vice versa).
536		*/
537		for (i = 0; i < sp->timecnt - 2; ++i)
538			if (sp->ats[i] > sp->ats[i + 1]) {
539				++i;
540/* CONSTCOND */
541				if (TYPE_SIGNED(time_t)) {
542					/*
543					** Ignore the end (easy).
544					*/
545					sp->timecnt = i;
546				} else {
547					/*
548					** Ignore the beginning (harder).
549					*/
550					int	j;
551
552					for (j = 0; j + i < sp->timecnt; ++j) {
553						sp->ats[j] = sp->ats[j + i];
554						sp->types[j] = sp->types[j + i];
555					}
556					sp->timecnt = j;
557				}
558				break;
559			}
560		/*
561		** If this is an old file, we're done.
562		*/
563		if (u.tzhead.tzh_version[0] == '\0')
564			break;
565		nread -= p - u.buf;
566		for (i = 0; i < nread; ++i)
567			u.buf[i] = p[i];
568		/*
569		** If this is a narrow integer time_t system, we're done.
570		*/
571		if (stored >= (int) sizeof(time_t)
572/* CONSTCOND */
573				&& TYPE_INTEGRAL(time_t))
574			break;
575	}
576	if (doextend && nread > 2 &&
577		u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
578		sp->typecnt + 2 <= TZ_MAX_TYPES) {
579			struct __state ts;
580			int	result;
581
582			u.buf[nread - 1] = '\0';
583			result = tzparse(&ts, &u.buf[1], FALSE);
584			if (result == 0 && ts.typecnt == 2 &&
585				sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
586					for (i = 0; i < 2; ++i)
587						ts.ttis[i].tt_abbrind +=
588							sp->charcnt;
589					for (i = 0; i < ts.charcnt; ++i)
590						sp->chars[sp->charcnt++] =
591							ts.chars[i];
592					i = 0;
593					while (i < ts.timecnt &&
594						ts.ats[i] <=
595						sp->ats[sp->timecnt - 1])
596							++i;
597					while (i < ts.timecnt &&
598					    sp->timecnt < TZ_MAX_TIMES) {
599						sp->ats[sp->timecnt] =
600							ts.ats[i];
601						sp->types[sp->timecnt] =
602							sp->typecnt +
603							ts.types[i];
604						++sp->timecnt;
605						++i;
606					}
607					sp->ttis[sp->typecnt++] = ts.ttis[0];
608					sp->ttis[sp->typecnt++] = ts.ttis[1];
609			}
610	}
611	if (sp->timecnt > 1) {
612		for (i = 1; i < sp->timecnt; ++i)
613			if (typesequiv(sp, sp->types[i], sp->types[0]) &&
614				differ_by_repeat(sp->ats[i], sp->ats[0])) {
615					sp->goback = TRUE;
616					break;
617				}
618		for (i = sp->timecnt - 2; i >= 0; --i)
619			if (typesequiv(sp, sp->types[sp->timecnt - 1],
620				sp->types[i]) &&
621				differ_by_repeat(sp->ats[sp->timecnt - 1],
622				sp->ats[i])) {
623					sp->goahead = TRUE;
624					break;
625		}
626	}
627	return 0;
628}
629
630static int
631typesequiv(const timezone_t sp, const int a, const int b)
632{
633	int	result;
634
635	if (sp == NULL ||
636		a < 0 || a >= sp->typecnt ||
637		b < 0 || b >= sp->typecnt)
638			result = FALSE;
639	else {
640		const struct ttinfo *	ap = &sp->ttis[a];
641		const struct ttinfo *	bp = &sp->ttis[b];
642		result = ap->tt_gmtoff == bp->tt_gmtoff &&
643			ap->tt_isdst == bp->tt_isdst &&
644			ap->tt_ttisstd == bp->tt_ttisstd &&
645			ap->tt_ttisgmt == bp->tt_ttisgmt &&
646			strcmp(&sp->chars[ap->tt_abbrind],
647			&sp->chars[bp->tt_abbrind]) == 0;
648	}
649	return result;
650}
651
652static const int	mon_lengths[2][MONSPERYEAR] = {
653	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
654	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
655};
656
657static const int	year_lengths[2] = {
658	DAYSPERNYEAR, DAYSPERLYEAR
659};
660
661/*
662** Given a pointer into a time zone string, scan until a character that is not
663** a valid character in a zone name is found. Return a pointer to that
664** character.
665*/
666
667static const char *
668getzname(strp)
669const char *	strp;
670{
671	char	c;
672
673	while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
674		c != '+')
675			++strp;
676	return strp;
677}
678
679/*
680** Given a pointer into an extended time zone string, scan until the ending
681** delimiter of the zone name is located. Return a pointer to the delimiter.
682**
683** As with getzname above, the legal character set is actually quite
684** restricted, with other characters producing undefined results.
685** We don't do any checking here; checking is done later in common-case code.
686*/
687
688static const char *
689getqzname(const char *strp, const int delim)
690{
691	int	c;
692
693	while ((c = *strp) != '\0' && c != delim)
694		++strp;
695	return strp;
696}
697
698/*
699** Given a pointer into a time zone string, extract a number from that string.
700** Check that the number is within a specified range; if it is not, return
701** NULL.
702** Otherwise, return a pointer to the first character not part of the number.
703*/
704
705static const char *
706getnum(strp, nump, min, max)
707const char *	strp;
708int * const		nump;
709const int		min;
710const int		max;
711{
712	char	c;
713	int	num;
714
715	if (strp == NULL || !is_digit(c = *strp)) {
716		errno = EINVAL;
717		return NULL;
718	}
719	num = 0;
720	do {
721		num = num * 10 + (c - '0');
722		if (num > max) {
723			errno = EOVERFLOW;
724			return NULL;	/* illegal value */
725		}
726		c = *++strp;
727	} while (is_digit(c));
728	if (num < min) {
729		errno = EINVAL;
730		return NULL;		/* illegal value */
731	}
732	*nump = num;
733	return strp;
734}
735
736/*
737** Given a pointer into a time zone string, extract a number of seconds,
738** in hh[:mm[:ss]] form, from the string.
739** If any error occurs, return NULL.
740** Otherwise, return a pointer to the first character not part of the number
741** of seconds.
742*/
743
744static const char *
745getsecs(const char *strp, long *const secsp)
746{
747	int	num;
748
749	/*
750	** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
751	** "M10.4.6/26", which does not conform to Posix,
752	** but which specifies the equivalent of
753	** ``02:00 on the first Sunday on or after 23 Oct''.
754	*/
755	strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
756	if (strp == NULL)
757		return NULL;
758	*secsp = num * (long) SECSPERHOUR;
759	if (*strp == ':') {
760		++strp;
761		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
762		if (strp == NULL)
763			return NULL;
764		*secsp += num * SECSPERMIN;
765		if (*strp == ':') {
766			++strp;
767			/* `SECSPERMIN' allows for leap seconds. */
768			strp = getnum(strp, &num, 0, SECSPERMIN);
769			if (strp == NULL)
770				return NULL;
771			*secsp += num;
772		}
773	}
774	return strp;
775}
776
777/*
778** Given a pointer into a time zone string, extract an offset, in
779** [+-]hh[:mm[:ss]] form, from the string.
780** If any error occurs, return NULL.
781** Otherwise, return a pointer to the first character not part of the time.
782*/
783
784static const char *
785getoffset(const char *strp, long *const offsetp)
786{
787	int	neg = 0;
788
789	if (*strp == '-') {
790		neg = 1;
791		++strp;
792	} else if (*strp == '+')
793		++strp;
794	strp = getsecs(strp, offsetp);
795	if (strp == NULL)
796		return NULL;		/* illegal time */
797	if (neg)
798		*offsetp = -*offsetp;
799	return strp;
800}
801
802/*
803** Given a pointer into a time zone string, extract a rule in the form
804** date[/time]. See POSIX section 8 for the format of "date" and "time".
805** If a valid rule is not found, return NULL.
806** Otherwise, return a pointer to the first character not part of the rule.
807*/
808
809static const char *
810getrule(const char *strp, struct rule *const rulep)
811{
812	if (*strp == 'J') {
813		/*
814		** Julian day.
815		*/
816		rulep->r_type = JULIAN_DAY;
817		++strp;
818		strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
819	} else if (*strp == 'M') {
820		/*
821		** Month, week, day.
822		*/
823		rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
824		++strp;
825		strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
826		if (strp == NULL)
827			return NULL;
828		if (*strp++ != '.')
829			return NULL;
830		strp = getnum(strp, &rulep->r_week, 1, 5);
831		if (strp == NULL)
832			return NULL;
833		if (*strp++ != '.')
834			return NULL;
835		strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
836	} else if (is_digit(*strp)) {
837		/*
838		** Day of year.
839		*/
840		rulep->r_type = DAY_OF_YEAR;
841		strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
842	} else	return NULL;		/* invalid format */
843	if (strp == NULL)
844		return NULL;
845	if (*strp == '/') {
846		/*
847		** Time specified.
848		*/
849		++strp;
850		strp = getsecs(strp, &rulep->r_time);
851	} else	rulep->r_time = 2 * SECSPERHOUR;	/* default = 2:00:00 */
852	return strp;
853}
854
855/*
856** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
857** year, a rule, and the offset from UTC at the time that rule takes effect,
858** calculate the Epoch-relative time that rule takes effect.
859*/
860
861static time_t
862transtime(const time_t janfirst, const int year, const struct rule *const rulep,
863    const long offset)
864{
865	int	leapyear;
866	time_t	value;
867	int	i;
868	int		d, m1, yy0, yy1, yy2, dow;
869
870	INITIALIZE(value);
871	leapyear = isleap(year);
872	switch (rulep->r_type) {
873
874	case JULIAN_DAY:
875		/*
876		** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
877		** years.
878		** In non-leap years, or if the day number is 59 or less, just
879		** add SECSPERDAY times the day number-1 to the time of
880		** January 1, midnight, to get the day.
881		*/
882		value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
883		if (leapyear && rulep->r_day >= 60)
884			value += SECSPERDAY;
885		break;
886
887	case DAY_OF_YEAR:
888		/*
889		** n - day of year.
890		** Just add SECSPERDAY times the day number to the time of
891		** January 1, midnight, to get the day.
892		*/
893		value = janfirst + rulep->r_day * SECSPERDAY;
894		break;
895
896	case MONTH_NTH_DAY_OF_WEEK:
897		/*
898		** Mm.n.d - nth "dth day" of month m.
899		*/
900		value = janfirst;
901		for (i = 0; i < rulep->r_mon - 1; ++i)
902			value += mon_lengths[leapyear][i] * SECSPERDAY;
903
904		/*
905		** Use Zeller's Congruence to get day-of-week of first day of
906		** month.
907		*/
908		m1 = (rulep->r_mon + 9) % 12 + 1;
909		yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
910		yy1 = yy0 / 100;
911		yy2 = yy0 % 100;
912		dow = ((26 * m1 - 2) / 10 +
913			1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
914		if (dow < 0)
915			dow += DAYSPERWEEK;
916
917		/*
918		** "dow" is the day-of-week of the first day of the month. Get
919		** the day-of-month (zero-origin) of the first "dow" day of the
920		** month.
921		*/
922		d = rulep->r_day - dow;
923		if (d < 0)
924			d += DAYSPERWEEK;
925		for (i = 1; i < rulep->r_week; ++i) {
926			if (d + DAYSPERWEEK >=
927				mon_lengths[leapyear][rulep->r_mon - 1])
928					break;
929			d += DAYSPERWEEK;
930		}
931
932		/*
933		** "d" is the day-of-month (zero-origin) of the day we want.
934		*/
935		value += d * SECSPERDAY;
936		break;
937	}
938
939	/*
940	** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
941	** question. To get the Epoch-relative time of the specified local
942	** time on that day, add the transition time and the current offset
943	** from UTC.
944	*/
945	return value + rulep->r_time + offset;
946}
947
948/*
949** Given a POSIX section 8-style TZ string, fill in the rule tables as
950** appropriate.
951*/
952
953static int
954tzparse(timezone_t sp, const char *name, const int lastditch)
955{
956	const char *			stdname;
957	const char *			dstname;
958	size_t				stdlen;
959	size_t				dstlen;
960	long				stdoffset;
961	long				dstoffset;
962	time_t *		atp;
963	unsigned char *	typep;
964	char *			cp;
965	int			load_result;
966
967	INITIALIZE(dstname);
968	stdname = name;
969	if (lastditch) {
970		stdlen = strlen(name);	/* length of standard zone name */
971		name += stdlen;
972		if (stdlen >= sizeof sp->chars)
973			stdlen = (sizeof sp->chars) - 1;
974		stdoffset = 0;
975	} else {
976		if (*name == '<') {
977			name++;
978			stdname = name;
979			name = getqzname(name, '>');
980			if (*name != '>')
981				return (-1);
982			stdlen = name - stdname;
983			name++;
984		} else {
985			name = getzname(name);
986			stdlen = name - stdname;
987		}
988		if (*name == '\0')
989			return -1;
990		name = getoffset(name, &stdoffset);
991		if (name == NULL)
992			return -1;
993	}
994	load_result = tzload(sp, TZDEFRULES, FALSE);
995	if (load_result != 0)
996		sp->leapcnt = 0;		/* so, we're off a little */
997	if (*name != '\0') {
998		if (*name == '<') {
999			dstname = ++name;
1000			name = getqzname(name, '>');
1001			if (*name != '>')
1002				return -1;
1003			dstlen = name - dstname;
1004			name++;
1005		} else {
1006			dstname = name;
1007			name = getzname(name);
1008			dstlen = name - dstname; /* length of DST zone name */
1009		}
1010		if (*name != '\0' && *name != ',' && *name != ';') {
1011			name = getoffset(name, &dstoffset);
1012			if (name == NULL)
1013				return -1;
1014		} else	dstoffset = stdoffset - SECSPERHOUR;
1015		if (*name == '\0' && load_result != 0)
1016			name = TZDEFRULESTRING;
1017		if (*name == ',' || *name == ';') {
1018			struct rule	start;
1019			struct rule	end;
1020			int	year;
1021			time_t	janfirst;
1022			time_t		starttime;
1023			time_t		endtime;
1024
1025			++name;
1026			if ((name = getrule(name, &start)) == NULL)
1027				return -1;
1028			if (*name++ != ',')
1029				return -1;
1030			if ((name = getrule(name, &end)) == NULL)
1031				return -1;
1032			if (*name != '\0')
1033				return -1;
1034			sp->typecnt = 2;	/* standard time and DST */
1035			/*
1036			** Two transitions per year, from EPOCH_YEAR forward.
1037			*/
1038			sp->ttis[0].tt_gmtoff = -dstoffset;
1039			sp->ttis[0].tt_isdst = 1;
1040			sp->ttis[0].tt_abbrind = stdlen + 1;
1041			sp->ttis[1].tt_gmtoff = -stdoffset;
1042			sp->ttis[1].tt_isdst = 0;
1043			sp->ttis[1].tt_abbrind = 0;
1044			atp = sp->ats;
1045			typep = sp->types;
1046			janfirst = 0;
1047			sp->timecnt = 0;
1048			for (year = EPOCH_YEAR;
1049			    sp->timecnt + 2 <= TZ_MAX_TIMES;
1050			    ++year) {
1051			    	time_t	newfirst;
1052
1053				starttime = transtime(janfirst, year, &start,
1054					stdoffset);
1055				endtime = transtime(janfirst, year, &end,
1056					dstoffset);
1057				if (starttime > endtime) {
1058					*atp++ = endtime;
1059					*typep++ = 1;	/* DST ends */
1060					*atp++ = starttime;
1061					*typep++ = 0;	/* DST begins */
1062				} else {
1063					*atp++ = starttime;
1064					*typep++ = 0;	/* DST begins */
1065					*atp++ = endtime;
1066					*typep++ = 1;	/* DST ends */
1067				}
1068				sp->timecnt += 2;
1069				newfirst = janfirst;
1070				newfirst += year_lengths[isleap(year)] *
1071					SECSPERDAY;
1072				if (newfirst <= janfirst)
1073					break;
1074				janfirst = newfirst;
1075			}
1076		} else {
1077			long	theirstdoffset;
1078			long	theirdstoffset;
1079			long	theiroffset;
1080			int	isdst;
1081			int	i;
1082			int	j;
1083
1084			if (*name != '\0')
1085				return -1;
1086			/*
1087			** Initial values of theirstdoffset
1088			*/
1089			theirstdoffset = 0;
1090			for (i = 0; i < sp->timecnt; ++i) {
1091				j = sp->types[i];
1092				if (!sp->ttis[j].tt_isdst) {
1093					theirstdoffset =
1094						-sp->ttis[j].tt_gmtoff;
1095					break;
1096				}
1097			}
1098			theirdstoffset = 0;
1099			for (i = 0; i < sp->timecnt; ++i) {
1100				j = sp->types[i];
1101				if (sp->ttis[j].tt_isdst) {
1102					theirdstoffset =
1103						-sp->ttis[j].tt_gmtoff;
1104					break;
1105				}
1106			}
1107			/*
1108			** Initially we're assumed to be in standard time.
1109			*/
1110			isdst = FALSE;
1111			theiroffset = theirstdoffset;
1112			/*
1113			** Now juggle transition times and types
1114			** tracking offsets as you do.
1115			*/
1116			for (i = 0; i < sp->timecnt; ++i) {
1117				j = sp->types[i];
1118				sp->types[i] = sp->ttis[j].tt_isdst;
1119				if (sp->ttis[j].tt_ttisgmt) {
1120					/* No adjustment to transition time */
1121				} else {
1122					/*
1123					** If summer time is in effect, and the
1124					** transition time was not specified as
1125					** standard time, add the summer time
1126					** offset to the transition time;
1127					** otherwise, add the standard time
1128					** offset to the transition time.
1129					*/
1130					/*
1131					** Transitions from DST to DDST
1132					** will effectively disappear since
1133					** POSIX provides for only one DST
1134					** offset.
1135					*/
1136					if (isdst && !sp->ttis[j].tt_ttisstd) {
1137						sp->ats[i] += dstoffset -
1138							theirdstoffset;
1139					} else {
1140						sp->ats[i] += stdoffset -
1141							theirstdoffset;
1142					}
1143				}
1144				theiroffset = -sp->ttis[j].tt_gmtoff;
1145				if (!sp->ttis[j].tt_isdst)
1146					theirstdoffset = theiroffset;
1147				else	theirdstoffset = theiroffset;
1148			}
1149			/*
1150			** Finally, fill in ttis.
1151			** ttisstd and ttisgmt need not be handled.
1152			*/
1153			sp->ttis[0].tt_gmtoff = -stdoffset;
1154			sp->ttis[0].tt_isdst = FALSE;
1155			sp->ttis[0].tt_abbrind = 0;
1156			sp->ttis[1].tt_gmtoff = -dstoffset;
1157			sp->ttis[1].tt_isdst = TRUE;
1158			sp->ttis[1].tt_abbrind = stdlen + 1;
1159			sp->typecnt = 2;
1160		}
1161	} else {
1162		dstlen = 0;
1163		sp->typecnt = 1;		/* only standard time */
1164		sp->timecnt = 0;
1165		sp->ttis[0].tt_gmtoff = -stdoffset;
1166		sp->ttis[0].tt_isdst = 0;
1167		sp->ttis[0].tt_abbrind = 0;
1168	}
1169	sp->charcnt = stdlen + 1;
1170	if (dstlen != 0)
1171		sp->charcnt += dstlen + 1;
1172	if ((size_t) sp->charcnt > sizeof sp->chars)
1173		return -1;
1174	cp = sp->chars;
1175	(void) strncpy(cp, stdname, stdlen);
1176	cp += stdlen;
1177	*cp++ = '\0';
1178	if (dstlen != 0) {
1179		(void) strncpy(cp, dstname, dstlen);
1180		*(cp + dstlen) = '\0';
1181	}
1182	return 0;
1183}
1184
1185static void
1186gmtload(timezone_t sp)
1187{
1188	if (tzload(sp, gmt, TRUE) != 0)
1189		(void) tzparse(sp, gmt, TRUE);
1190}
1191
1192timezone_t
1193tzalloc(const char *name)
1194{
1195	timezone_t sp = calloc(1, sizeof *sp);
1196	if (sp == NULL)
1197		return NULL;
1198	if (tzload(sp, name, TRUE) != 0) {
1199		free(sp);
1200		return NULL;
1201	}
1202	settzname_z(sp);
1203	return sp;
1204}
1205
1206void
1207tzfree(const timezone_t sp)
1208{
1209	free(sp);
1210}
1211
1212static void
1213tzsetwall_unlocked(void)
1214{
1215	if (lcl_is_set < 0)
1216		return;
1217	lcl_is_set = -1;
1218
1219	if (lclptr == NULL) {
1220		int saveerrno = errno;
1221		lclptr = calloc(1, sizeof *lclptr);
1222		errno = saveerrno;
1223		if (lclptr == NULL) {
1224			settzname();	/* all we can do */
1225			return;
1226		}
1227	}
1228	if (tzload(lclptr, NULL, TRUE) != 0)
1229		gmtload(lclptr);
1230	settzname();
1231}
1232
1233#ifndef STD_INSPIRED
1234/*
1235** A non-static declaration of tzsetwall in a system header file
1236** may cause a warning about this upcoming static declaration...
1237*/
1238static
1239#endif /* !defined STD_INSPIRED */
1240void
1241tzsetwall(void)
1242{
1243	rwlock_wrlock(&lcl_lock);
1244	tzsetwall_unlocked();
1245	rwlock_unlock(&lcl_lock);
1246}
1247
1248#ifndef STD_INSPIRED
1249/*
1250** A non-static declaration of tzsetwall in a system header file
1251** may cause a warning about this upcoming static declaration...
1252*/
1253static
1254#endif /* !defined STD_INSPIRED */
1255void
1256tzset_unlocked(void)
1257{
1258	const char *	name;
1259	int saveerrno;
1260
1261	saveerrno = errno;
1262	name = getenv("TZ");
1263	errno = saveerrno;
1264	if (name == NULL) {
1265		tzsetwall_unlocked();
1266		return;
1267	}
1268
1269	if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
1270		return;
1271	lcl_is_set = strlen(name) < sizeof lcl_TZname;
1272	if (lcl_is_set)
1273		(void)strlcpy(lcl_TZname, name, sizeof(lcl_TZname));
1274
1275	if (lclptr == NULL) {
1276		saveerrno = errno;
1277		lclptr = calloc(1, sizeof *lclptr);
1278		errno = saveerrno;
1279		if (lclptr == NULL) {
1280			settzname();	/* all we can do */
1281			return;
1282		}
1283	}
1284	if (*name == '\0') {
1285		/*
1286		** User wants it fast rather than right.
1287		*/
1288		lclptr->leapcnt = 0;		/* so, we're off a little */
1289		lclptr->timecnt = 0;
1290		lclptr->typecnt = 0;
1291		lclptr->ttis[0].tt_isdst = 0;
1292		lclptr->ttis[0].tt_gmtoff = 0;
1293		lclptr->ttis[0].tt_abbrind = 0;
1294		(void) strlcpy(lclptr->chars, gmt, sizeof(lclptr->chars));
1295	} else if (tzload(lclptr, name, TRUE) != 0)
1296		if (name[0] == ':' || tzparse(lclptr, name, FALSE) != 0)
1297			(void) gmtload(lclptr);
1298	settzname();
1299}
1300
1301void
1302tzset(void)
1303{
1304	rwlock_wrlock(&lcl_lock);
1305	tzset_unlocked();
1306	rwlock_unlock(&lcl_lock);
1307}
1308
1309/*
1310** The easy way to behave "as if no library function calls" localtime
1311** is to not call it--so we drop its guts into "localsub", which can be
1312** freely called. (And no, the PANS doesn't require the above behavior--
1313** but it *is* desirable.)
1314**
1315** The unused offset argument is for the benefit of mktime variants.
1316*/
1317
1318/*ARGSUSED*/
1319static struct tm *
1320localsub(const timezone_t sp, const time_t * const timep, const long offset,
1321    struct tm *const tmp)
1322{
1323	const struct ttinfo *	ttisp;
1324	int			i;
1325	struct tm *		result;
1326	const time_t			t = *timep;
1327
1328	if ((sp->goback && t < sp->ats[0]) ||
1329		(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1330			time_t			newt = t;
1331			time_t		seconds;
1332			time_t		tcycles;
1333			int_fast64_t	icycles;
1334
1335			if (t < sp->ats[0])
1336				seconds = sp->ats[0] - t;
1337			else	seconds = t - sp->ats[sp->timecnt - 1];
1338			--seconds;
1339			tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1340			++tcycles;
1341			icycles = tcycles;
1342			if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1343				return NULL;
1344			seconds = (time_t) icycles;
1345			seconds *= YEARSPERREPEAT;
1346			seconds *= AVGSECSPERYEAR;
1347			if (t < sp->ats[0])
1348				newt += seconds;
1349			else	newt -= seconds;
1350			if (newt < sp->ats[0] ||
1351				newt > sp->ats[sp->timecnt - 1]) {
1352					errno = EOVERFLOW;
1353					return NULL;	/* "cannot happen" */
1354			}
1355			result = localsub(sp, &newt, offset, tmp);
1356			if (result == tmp) {
1357				time_t	newy;
1358
1359				newy = tmp->tm_year;
1360				if (t < sp->ats[0])
1361					newy -= (time_t)icycles * YEARSPERREPEAT;
1362				else	newy += (time_t)icycles * YEARSPERREPEAT;
1363				tmp->tm_year = (int)newy;
1364				if (tmp->tm_year != newy) {
1365					errno = EOVERFLOW;
1366					return NULL;
1367				}
1368			}
1369			return result;
1370	}
1371	if (sp->timecnt == 0 || t < sp->ats[0]) {
1372		i = 0;
1373		while (sp->ttis[i].tt_isdst)
1374			if (++i >= sp->typecnt) {
1375				i = 0;
1376				break;
1377			}
1378	} else {
1379		int	lo = 1;
1380		int	hi = sp->timecnt;
1381
1382		while (lo < hi) {
1383			int	mid = (lo + hi) / 2;
1384
1385			if (t < sp->ats[mid])
1386				hi = mid;
1387			else	lo = mid + 1;
1388		}
1389		i = (int) sp->types[lo - 1];
1390	}
1391	ttisp = &sp->ttis[i];
1392	/*
1393	** To get (wrong) behavior that's compatible with System V Release 2.0
1394	** you'd replace the statement below with
1395	**	t += ttisp->tt_gmtoff;
1396	**	timesub(&t, 0L, sp, tmp);
1397	*/
1398	result = timesub(sp, &t, ttisp->tt_gmtoff, tmp);
1399	tmp->tm_isdst = ttisp->tt_isdst;
1400	tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
1401#ifdef TM_ZONE
1402	tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
1403#endif /* defined TM_ZONE */
1404	return result;
1405}
1406
1407/*
1408** Re-entrant version of localtime.
1409*/
1410
1411struct tm *
1412localtime_r(const time_t * __restrict timep, struct tm *tmp)
1413{
1414	rwlock_rdlock(&lcl_lock);
1415	tzset_unlocked();
1416	tmp = localtime_rz(lclptr, timep, tmp);
1417	rwlock_unlock(&lcl_lock);
1418	return tmp;
1419}
1420
1421struct tm *
1422localtime(const time_t *const timep)
1423{
1424	return localtime_r(timep, &tm);
1425}
1426
1427struct tm *
1428localtime_rz(const timezone_t sp, const time_t * __restrict timep, struct tm *tmp)
1429{
1430	if (sp == NULL)
1431		return gmtsub(NULL, timep, 0L, tmp);
1432	else
1433		return localsub(sp, timep, 0L, tmp);
1434}
1435
1436/*
1437** gmtsub is to gmtime as localsub is to localtime.
1438*/
1439
1440static struct tm *
1441gmtsub(const timezone_t sp, const time_t * const timep, const long offset,
1442    struct tm *const tmp)
1443{
1444	struct tm *	result;
1445#ifdef _REENTRANT
1446	static mutex_t gmt_mutex = MUTEX_INITIALIZER;
1447#endif
1448
1449	mutex_lock(&gmt_mutex);
1450	if (!gmt_is_set) {
1451		int saveerrno;
1452		gmt_is_set = TRUE;
1453		saveerrno = errno;
1454		gmtptr = calloc(1, sizeof *gmtptr);
1455		errno = saveerrno;
1456		if (gmtptr != NULL)
1457			gmtload(gmtptr);
1458	}
1459	mutex_unlock(&gmt_mutex);
1460	result = timesub(gmtptr, timep, offset, tmp);
1461#ifdef TM_ZONE
1462	/*
1463	** Could get fancy here and deliver something such as
1464	** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1465	** but this is no time for a treasure hunt.
1466	*/
1467	if (offset != 0)
1468		tmp->TM_ZONE = (__aconst char *)__UNCONST(wildabbr);
1469	else {
1470		if (gmtptr == NULL)
1471			tmp->TM_ZONE = (__aconst char *)__UNCONST(gmt);
1472		else	tmp->TM_ZONE = gmtptr->chars;
1473	}
1474#endif /* defined TM_ZONE */
1475	return result;
1476}
1477
1478struct tm *
1479gmtime(const time_t *const timep)
1480{
1481	return gmtsub(NULL, timep, 0L, &tm);
1482}
1483
1484/*
1485** Re-entrant version of gmtime.
1486*/
1487
1488struct tm *
1489gmtime_r(const time_t * const timep, struct tm *tmp)
1490{
1491	return gmtsub(NULL, timep, 0L, tmp);
1492}
1493
1494#ifdef STD_INSPIRED
1495
1496struct tm *
1497offtime(const time_t *const timep, long offset)
1498{
1499	return gmtsub(NULL, timep, offset, &tm);
1500}
1501
1502struct tm *
1503offtime_r(const time_t *timep, long offset, struct tm *tmp)
1504{
1505	return gmtsub(NULL, timep, offset, tmp);
1506}
1507
1508#endif /* defined STD_INSPIRED */
1509
1510/*
1511** Return the number of leap years through the end of the given year
1512** where, to make the math easy, the answer for year zero is defined as zero.
1513*/
1514
1515static int
1516leaps_thru_end_of(const int y)
1517{
1518	return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1519		-(leaps_thru_end_of(-(y + 1)) + 1);
1520}
1521
1522static struct tm *
1523timesub(const timezone_t sp, const time_t *const timep, const long offset,
1524    struct tm *const tmp)
1525{
1526	const struct lsinfo *	lp;
1527	time_t			tdays;
1528	int			idays;	/* unsigned would be so 2003 */
1529	long			rem;
1530	int			y;
1531	const int *		ip;
1532	long			corr;
1533	int			hit;
1534	int			i;
1535
1536	corr = 0;
1537	hit = 0;
1538	i = (sp == NULL) ? 0 : sp->leapcnt;
1539	while (--i >= 0) {
1540		lp = &sp->lsis[i];
1541		if (*timep >= lp->ls_trans) {
1542			if (*timep == lp->ls_trans) {
1543				hit = ((i == 0 && lp->ls_corr > 0) ||
1544					lp->ls_corr > sp->lsis[i - 1].ls_corr);
1545				if (hit)
1546					while (i > 0 &&
1547						sp->lsis[i].ls_trans ==
1548						sp->lsis[i - 1].ls_trans + 1 &&
1549						sp->lsis[i].ls_corr ==
1550						sp->lsis[i - 1].ls_corr + 1) {
1551							++hit;
1552							--i;
1553					}
1554			}
1555			corr = lp->ls_corr;
1556			break;
1557		}
1558	}
1559	y = EPOCH_YEAR;
1560	tdays = *timep / SECSPERDAY;
1561	rem = (long) (*timep - tdays * SECSPERDAY);
1562	while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
1563		int		newy;
1564		time_t	tdelta;
1565		int	idelta;
1566		int	leapdays;
1567
1568		tdelta = tdays / DAYSPERLYEAR;
1569		idelta = (int) tdelta;
1570		if (tdelta - idelta >= 1 || idelta - tdelta >= 1) {
1571			errno = EOVERFLOW;
1572			return NULL;
1573		}
1574		if (idelta == 0)
1575			idelta = (tdays < 0) ? -1 : 1;
1576		newy = y;
1577		if (increment_overflow(&newy, idelta)) {
1578			errno = EOVERFLOW;
1579			return NULL;
1580		}
1581		leapdays = leaps_thru_end_of(newy - 1) -
1582			leaps_thru_end_of(y - 1);
1583		tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
1584		tdays -= leapdays;
1585		y = newy;
1586	}
1587	{
1588		long	seconds;
1589
1590		seconds = tdays * SECSPERDAY + 0.5;
1591		tdays = seconds / SECSPERDAY;
1592		rem += (long) (seconds - tdays * SECSPERDAY);
1593	}
1594	/*
1595	** Given the range, we can now fearlessly cast...
1596	*/
1597	idays = (int) tdays;
1598	rem += offset - corr;
1599	while (rem < 0) {
1600		rem += SECSPERDAY;
1601		--idays;
1602	}
1603	while (rem >= SECSPERDAY) {
1604		rem -= SECSPERDAY;
1605		++idays;
1606	}
1607	while (idays < 0) {
1608		if (increment_overflow(&y, -1)) {
1609			errno = EOVERFLOW;
1610			return NULL;
1611		}
1612		idays += year_lengths[isleap(y)];
1613	}
1614	while (idays >= year_lengths[isleap(y)]) {
1615		idays -= year_lengths[isleap(y)];
1616		if (increment_overflow(&y, 1)) {
1617			errno = EOVERFLOW;
1618			return NULL;
1619		}
1620	}
1621	tmp->tm_year = y;
1622	if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) {
1623		errno = EOVERFLOW;
1624		return NULL;
1625	}
1626	tmp->tm_yday = idays;
1627	/*
1628	** The "extra" mods below avoid overflow problems.
1629	*/
1630	tmp->tm_wday = EPOCH_WDAY +
1631		((y - EPOCH_YEAR) % DAYSPERWEEK) *
1632		(DAYSPERNYEAR % DAYSPERWEEK) +
1633		leaps_thru_end_of(y - 1) -
1634		leaps_thru_end_of(EPOCH_YEAR - 1) +
1635		idays;
1636	tmp->tm_wday %= DAYSPERWEEK;
1637	if (tmp->tm_wday < 0)
1638		tmp->tm_wday += DAYSPERWEEK;
1639	tmp->tm_hour = (int) (rem / SECSPERHOUR);
1640	rem %= SECSPERHOUR;
1641	tmp->tm_min = (int) (rem / SECSPERMIN);
1642	/*
1643	** A positive leap second requires a special
1644	** representation. This uses "... ??:59:60" et seq.
1645	*/
1646	tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1647	ip = mon_lengths[isleap(y)];
1648	for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1649		idays -= ip[tmp->tm_mon];
1650	tmp->tm_mday = (int) (idays + 1);
1651	tmp->tm_isdst = 0;
1652#ifdef TM_GMTOFF
1653	tmp->TM_GMTOFF = offset;
1654#endif /* defined TM_GMTOFF */
1655	return tmp;
1656}
1657
1658char *
1659ctime(const time_t *const timep)
1660{
1661/*
1662** Section 4.12.3.2 of X3.159-1989 requires that
1663**	The ctime function converts the calendar time pointed to by timer
1664**	to local time in the form of a string. It is equivalent to
1665**		asctime(localtime(timer))
1666*/
1667	struct tm *rtm = localtime(timep);
1668	if (rtm == NULL)
1669		return NULL;
1670	return asctime(rtm);
1671}
1672
1673char *
1674ctime_r(const time_t *const timep, char *buf)
1675{
1676	struct tm	mytm, *rtm;
1677
1678	rtm = localtime_r(timep, &mytm);
1679	if (rtm == NULL)
1680		return NULL;
1681	return asctime_r(rtm, buf);
1682}
1683
1684char *
1685ctime_rz(const timezone_t sp, const time_t * timep, char *buf)
1686{
1687	struct tm	mytm, *rtm;
1688
1689	rtm = localtime_rz(sp, timep, &mytm);
1690	if (rtm == NULL)
1691		return NULL;
1692	return asctime_r(rtm, buf);
1693}
1694
1695/*
1696** Adapted from code provided by Robert Elz, who writes:
1697**	The "best" way to do mktime I think is based on an idea of Bob
1698**	Kridle's (so its said...) from a long time ago.
1699**	It does a binary search of the time_t space. Since time_t's are
1700**	just 32 bits, its a max of 32 iterations (even at 64 bits it
1701**	would still be very reasonable).
1702*/
1703
1704#ifndef WRONG
1705#define WRONG	(-1)
1706#endif /* !defined WRONG */
1707
1708/*
1709** Simplified normalize logic courtesy Paul Eggert.
1710*/
1711
1712static int
1713increment_overflow(int *number, int delta)
1714{
1715	int	number0;
1716
1717	number0 = *number;
1718	*number += delta;
1719	return (*number < number0) != (delta < 0);
1720}
1721
1722static int
1723long_increment_overflow(long *number, int delta)
1724{
1725	long	number0;
1726
1727	number0 = *number;
1728	*number += delta;
1729	return (*number < number0) != (delta < 0);
1730}
1731
1732static int
1733normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
1734{
1735	int	tensdelta;
1736
1737	tensdelta = (*unitsptr >= 0) ?
1738		(*unitsptr / base) :
1739		(-1 - (-1 - *unitsptr) / base);
1740	*unitsptr -= tensdelta * base;
1741	return increment_overflow(tensptr, tensdelta);
1742}
1743
1744static int
1745long_normalize_overflow(long *const tensptr, int *const unitsptr,
1746    const int base)
1747{
1748	int	tensdelta;
1749
1750	tensdelta = (*unitsptr >= 0) ?
1751		(*unitsptr / base) :
1752		(-1 - (-1 - *unitsptr) / base);
1753	*unitsptr -= tensdelta * base;
1754	return long_increment_overflow(tensptr, tensdelta);
1755}
1756
1757static int
1758tmcomp(const struct tm *const atmp, const struct tm *const btmp)
1759{
1760	int	result;
1761
1762	if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1763		(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1764		(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1765		(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1766		(result = (atmp->tm_min - btmp->tm_min)) == 0)
1767			result = atmp->tm_sec - btmp->tm_sec;
1768	return result;
1769}
1770
1771static time_t
1772time2sub(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
1773    const long offset, int *const okayp, const int do_norm_secs)
1774{
1775	int			dir;
1776	int			i, j;
1777	int			saved_seconds;
1778	long			li;
1779	time_t			lo;
1780	time_t			hi;
1781	long				y;
1782	time_t				newt;
1783	time_t				t;
1784	struct tm			yourtm, mytm;
1785
1786	*okayp = FALSE;
1787	yourtm = *tmp;
1788	if (do_norm_secs) {
1789		if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
1790			SECSPERMIN))
1791				return WRONG;
1792	}
1793	if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
1794		return WRONG;
1795	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
1796		return WRONG;
1797	y = yourtm.tm_year;
1798	if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
1799		return WRONG;
1800	/*
1801	** Turn y into an actual year number for now.
1802	** It is converted back to an offset from TM_YEAR_BASE later.
1803	*/
1804	if (long_increment_overflow(&y, TM_YEAR_BASE))
1805		return WRONG;
1806	while (yourtm.tm_mday <= 0) {
1807		if (long_increment_overflow(&y, -1))
1808			return WRONG;
1809		li = y + (1 < yourtm.tm_mon);
1810		yourtm.tm_mday += year_lengths[isleap(li)];
1811	}
1812	while (yourtm.tm_mday > DAYSPERLYEAR) {
1813		li = y + (1 < yourtm.tm_mon);
1814		yourtm.tm_mday -= year_lengths[isleap(li)];
1815		if (long_increment_overflow(&y, 1))
1816			return WRONG;
1817	}
1818	for ( ; ; ) {
1819		i = mon_lengths[isleap(y)][yourtm.tm_mon];
1820		if (yourtm.tm_mday <= i)
1821			break;
1822		yourtm.tm_mday -= i;
1823		if (++yourtm.tm_mon >= MONSPERYEAR) {
1824			yourtm.tm_mon = 0;
1825			if (long_increment_overflow(&y, 1))
1826				return WRONG;
1827		}
1828	}
1829	if (long_increment_overflow(&y, -TM_YEAR_BASE))
1830		return WRONG;
1831	yourtm.tm_year = y;
1832	if (yourtm.tm_year != y)
1833		return WRONG;
1834	if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
1835		saved_seconds = 0;
1836	else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
1837		/*
1838		** We can't set tm_sec to 0, because that might push the
1839		** time below the minimum representable time.
1840		** Set tm_sec to 59 instead.
1841		** This assumes that the minimum representable time is
1842		** not in the same minute that a leap second was deleted from,
1843		** which is a safer assumption than using 58 would be.
1844		*/
1845		if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
1846			return WRONG;
1847		saved_seconds = yourtm.tm_sec;
1848		yourtm.tm_sec = SECSPERMIN - 1;
1849	} else {
1850		saved_seconds = yourtm.tm_sec;
1851		yourtm.tm_sec = 0;
1852	}
1853	/*
1854	** Do a binary search (this works whatever time_t's type is).
1855	*/
1856/* LINTED constant */
1857	if (!TYPE_SIGNED(time_t)) {
1858		lo = 0;
1859		hi = lo - 1;
1860/* LINTED constant */
1861	} else if (!TYPE_INTEGRAL(time_t)) {
1862/* CONSTCOND */
1863		if (sizeof(time_t) > sizeof(float))
1864/* LINTED assumed double */
1865			hi = (time_t) DBL_MAX;
1866/* LINTED assumed float */
1867		else	hi = (time_t) FLT_MAX;
1868		lo = -hi;
1869	} else {
1870		lo = 1;
1871		for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
1872			lo *= 2;
1873		hi = -(lo + 1);
1874	}
1875	for ( ; ; ) {
1876		t = lo / 2 + hi / 2;
1877		if (t < lo)
1878			t = lo;
1879		else if (t > hi)
1880			t = hi;
1881		if ((*funcp)(sp, &t, offset, &mytm) == NULL) {
1882			/*
1883			** Assume that t is too extreme to be represented in
1884			** a struct tm; arrange things so that it is less
1885			** extreme on the next pass.
1886			*/
1887			dir = (t > 0) ? 1 : -1;
1888		} else	dir = tmcomp(&mytm, &yourtm);
1889		if (dir != 0) {
1890			if (t == lo) {
1891				++t;
1892				if (t <= lo)
1893					return WRONG;
1894				++lo;
1895			} else if (t == hi) {
1896				--t;
1897				if (t >= hi)
1898					return WRONG;
1899				--hi;
1900			}
1901			if (lo > hi)
1902				return WRONG;
1903			if (dir > 0)
1904				hi = t;
1905			else	lo = t;
1906			continue;
1907		}
1908		if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1909			break;
1910		/*
1911		** Right time, wrong type.
1912		** Hunt for right time, right type.
1913		** It's okay to guess wrong since the guess
1914		** gets checked.
1915		*/
1916		if (sp == NULL)
1917			return WRONG;
1918		for (i = sp->typecnt - 1; i >= 0; --i) {
1919			if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
1920				continue;
1921			for (j = sp->typecnt - 1; j >= 0; --j) {
1922				if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
1923					continue;
1924				newt = t + sp->ttis[j].tt_gmtoff -
1925					sp->ttis[i].tt_gmtoff;
1926				if ((*funcp)(sp, &newt, offset, &mytm) == NULL)
1927					continue;
1928				if (tmcomp(&mytm, &yourtm) != 0)
1929					continue;
1930				if (mytm.tm_isdst != yourtm.tm_isdst)
1931					continue;
1932				/*
1933				** We have a match.
1934				*/
1935				t = newt;
1936				goto label;
1937			}
1938		}
1939		return WRONG;
1940	}
1941label:
1942	newt = t + saved_seconds;
1943	if ((newt < t) != (saved_seconds < 0))
1944		return WRONG;
1945	t = newt;
1946	if ((*funcp)(sp, &t, offset, tmp))
1947		*okayp = TRUE;
1948	return t;
1949}
1950
1951static time_t
1952time2(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
1953    const long offset, int *const okayp)
1954{
1955	time_t	t;
1956
1957	/*
1958	** First try without normalization of seconds
1959	** (in case tm_sec contains a value associated with a leap second).
1960	** If that fails, try with normalization of seconds.
1961	*/
1962	t = time2sub(sp, tmp, funcp, offset, okayp, FALSE);
1963	return *okayp ? t : time2sub(sp, tmp, funcp, offset, okayp, TRUE);
1964}
1965
1966static time_t
1967time1(const timezone_t sp, struct tm *const tmp, subfun_t funcp,
1968    long offset)
1969{
1970	time_t			t;
1971	int			samei, otheri;
1972	int			sameind, otherind;
1973	int			i;
1974	int			nseen;
1975	int				seen[TZ_MAX_TYPES];
1976	int				types[TZ_MAX_TYPES];
1977	int				okay;
1978
1979	if (tmp->tm_isdst > 1)
1980		tmp->tm_isdst = 1;
1981	t = time2(sp, tmp, funcp, offset, &okay);
1982#ifdef PCTS
1983	/*
1984	** PCTS code courtesy Grant Sullivan.
1985	*/
1986	if (okay)
1987		return t;
1988	if (tmp->tm_isdst < 0)
1989		tmp->tm_isdst = 0;	/* reset to std and try again */
1990#endif /* defined PCTS */
1991#ifndef PCTS
1992	if (okay || tmp->tm_isdst < 0)
1993		return t;
1994#endif /* !defined PCTS */
1995	/*
1996	** We're supposed to assume that somebody took a time of one type
1997	** and did some math on it that yielded a "struct tm" that's bad.
1998	** We try to divine the type they started from and adjust to the
1999	** type they need.
2000	*/
2001	if (sp == NULL)
2002		return WRONG;
2003	for (i = 0; i < sp->typecnt; ++i)
2004		seen[i] = FALSE;
2005	nseen = 0;
2006	for (i = sp->timecnt - 1; i >= 0; --i)
2007		if (!seen[sp->types[i]]) {
2008			seen[sp->types[i]] = TRUE;
2009			types[nseen++] = sp->types[i];
2010		}
2011	for (sameind = 0; sameind < nseen; ++sameind) {
2012		samei = types[sameind];
2013		if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2014			continue;
2015		for (otherind = 0; otherind < nseen; ++otherind) {
2016			otheri = types[otherind];
2017			if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2018				continue;
2019			tmp->tm_sec += (int)(sp->ttis[otheri].tt_gmtoff -
2020					sp->ttis[samei].tt_gmtoff);
2021			tmp->tm_isdst = !tmp->tm_isdst;
2022			t = time2(sp, tmp, funcp, offset, &okay);
2023			if (okay)
2024				return t;
2025			tmp->tm_sec -= (int)(sp->ttis[otheri].tt_gmtoff -
2026					sp->ttis[samei].tt_gmtoff);
2027			tmp->tm_isdst = !tmp->tm_isdst;
2028		}
2029	}
2030	return WRONG;
2031}
2032
2033time_t
2034mktime_z(const timezone_t sp, struct tm *tmp)
2035{
2036	if (sp == NULL)
2037		return time1(NULL, tmp, gmtsub, 0L);
2038	else
2039		return time1(sp, tmp, localsub, 0L);
2040}
2041
2042time_t
2043mktime(struct tm * const	tmp)
2044{
2045	time_t result;
2046
2047	rwlock_wrlock(&lcl_lock);
2048	tzset_unlocked();
2049	result = mktime_z(lclptr, tmp);
2050	rwlock_unlock(&lcl_lock);
2051	return result;
2052}
2053
2054#ifdef STD_INSPIRED
2055
2056time_t
2057timelocal_z(const timezone_t sp, struct tm *tmp)
2058{
2059	if (tmp != NULL)
2060		tmp->tm_isdst = -1;	/* in case it wasn't initialized */
2061	return mktime_z(sp, tmp);
2062}
2063
2064time_t
2065timelocal(struct tm *const tmp)
2066{
2067	tmp->tm_isdst = -1;	/* in case it wasn't initialized */
2068	return mktime(tmp);
2069}
2070
2071time_t
2072timegm(struct tm *const tmp)
2073{
2074	tmp->tm_isdst = 0;
2075	return time1(gmtptr, tmp, gmtsub, 0L);
2076}
2077
2078time_t
2079timeoff(struct tm *const tmp, const long offset)
2080{
2081	tmp->tm_isdst = 0;
2082	return time1(gmtptr, tmp, gmtsub, offset);
2083}
2084
2085#endif /* defined STD_INSPIRED */
2086
2087#ifdef CMUCS
2088
2089/*
2090** The following is supplied for compatibility with
2091** previous versions of the CMUCS runtime library.
2092*/
2093
2094long
2095gtime(struct tm *const tmp)
2096{
2097	const time_t t = mktime(tmp);
2098
2099	if (t == WRONG)
2100		return -1;
2101	return t;
2102}
2103
2104#endif /* defined CMUCS */
2105
2106/*
2107** XXX--is the below the right way to conditionalize??
2108*/
2109
2110#ifdef STD_INSPIRED
2111
2112/*
2113** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
2114** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2115** is not the case if we are accounting for leap seconds.
2116** So, we provide the following conversion routines for use
2117** when exchanging timestamps with POSIX conforming systems.
2118*/
2119
2120static long
2121leapcorr(const timezone_t sp, time_t *timep)
2122{
2123	struct lsinfo * lp;
2124	int		i;
2125
2126	i = sp->leapcnt;
2127	while (--i >= 0) {
2128		lp = &sp->lsis[i];
2129		if (*timep >= lp->ls_trans)
2130			return lp->ls_corr;
2131	}
2132	return 0;
2133}
2134
2135time_t
2136time2posix_z(const timezone_t sp, time_t t)
2137{
2138	return t - leapcorr(sp, &t);
2139}
2140
2141time_t
2142time2posix(time_t t)
2143{
2144	time_t result;
2145	rwlock_wrlock(&lcl_lock);
2146	tzset_unlocked();
2147	result = t - leapcorr(lclptr, &t);
2148	rwlock_unlock(&lcl_lock);
2149	return (result);
2150}
2151
2152time_t
2153posix2time_z(const timezone_t sp, time_t t)
2154{
2155	time_t	x;
2156	time_t	y;
2157
2158	/*
2159	** For a positive leap second hit, the result
2160	** is not unique. For a negative leap second
2161	** hit, the corresponding time doesn't exist,
2162	** so we return an adjacent second.
2163	*/
2164	x = t + leapcorr(sp, &t);
2165	y = x - leapcorr(sp, &x);
2166	if (y < t) {
2167		do {
2168			x++;
2169			y = x - leapcorr(sp, &x);
2170		} while (y < t);
2171		if (t != y) {
2172			return x - 1;
2173		}
2174	} else if (y > t) {
2175		do {
2176			--x;
2177			y = x - leapcorr(sp, &x);
2178		} while (y > t);
2179		if (t != y) {
2180			return x + 1;
2181		}
2182	}
2183	return x;
2184}
2185
2186
2187
2188time_t
2189posix2time(time_t t)
2190{
2191	time_t result;
2192
2193	rwlock_wrlock(&lcl_lock);
2194	tzset_unlocked();
2195	result = posix2time_z(lclptr, t);
2196	rwlock_unlock(&lcl_lock);
2197	return result;
2198}
2199
2200#endif /* defined STD_INSPIRED */
2201