xref: /aosp_15_r20/bionic/libc/tzcode/localtime.c (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /* Convert timestamp from time_t to struct tm.  */
2*8d67ca89SAndroid Build Coastguard Worker 
3*8d67ca89SAndroid Build Coastguard Worker /*
4*8d67ca89SAndroid Build Coastguard Worker ** This file is in the public domain, so clarified as of
5*8d67ca89SAndroid Build Coastguard Worker ** 1996-06-05 by Arthur David Olson.
6*8d67ca89SAndroid Build Coastguard Worker */
7*8d67ca89SAndroid Build Coastguard Worker 
8*8d67ca89SAndroid Build Coastguard Worker /*
9*8d67ca89SAndroid Build Coastguard Worker ** Leap second handling from Bradley White.
10*8d67ca89SAndroid Build Coastguard Worker ** POSIX-style TZ environment variable handling from Guy Harris.
11*8d67ca89SAndroid Build Coastguard Worker */
12*8d67ca89SAndroid Build Coastguard Worker 
13*8d67ca89SAndroid Build Coastguard Worker /*LINTLIBRARY*/
14*8d67ca89SAndroid Build Coastguard Worker 
15*8d67ca89SAndroid Build Coastguard Worker #define LOCALTIME_IMPLEMENTATION
16*8d67ca89SAndroid Build Coastguard Worker #include "private.h"
17*8d67ca89SAndroid Build Coastguard Worker 
18*8d67ca89SAndroid Build Coastguard Worker #include "tzfile.h"
19*8d67ca89SAndroid Build Coastguard Worker #include <fcntl.h>
20*8d67ca89SAndroid Build Coastguard Worker 
21*8d67ca89SAndroid Build Coastguard Worker #if defined THREAD_SAFE && THREAD_SAFE
22*8d67ca89SAndroid Build Coastguard Worker # include <pthread.h>
23*8d67ca89SAndroid Build Coastguard Worker static pthread_mutex_t locallock = PTHREAD_MUTEX_INITIALIZER;
lock(void)24*8d67ca89SAndroid Build Coastguard Worker static int lock(void) { return pthread_mutex_lock(&locallock); }
unlock(void)25*8d67ca89SAndroid Build Coastguard Worker static void unlock(void) { pthread_mutex_unlock(&locallock); }
26*8d67ca89SAndroid Build Coastguard Worker #else
lock(void)27*8d67ca89SAndroid Build Coastguard Worker static int lock(void) { return 0; }
unlock(void)28*8d67ca89SAndroid Build Coastguard Worker static void unlock(void) { }
29*8d67ca89SAndroid Build Coastguard Worker #endif
30*8d67ca89SAndroid Build Coastguard Worker 
31*8d67ca89SAndroid Build Coastguard Worker #ifndef TZ_ABBR_CHAR_SET
32*8d67ca89SAndroid Build Coastguard Worker # define TZ_ABBR_CHAR_SET \
33*8d67ca89SAndroid Build Coastguard Worker     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
34*8d67ca89SAndroid Build Coastguard Worker #endif /* !defined TZ_ABBR_CHAR_SET */
35*8d67ca89SAndroid Build Coastguard Worker 
36*8d67ca89SAndroid Build Coastguard Worker #ifndef TZ_ABBR_ERR_CHAR
37*8d67ca89SAndroid Build Coastguard Worker # define TZ_ABBR_ERR_CHAR    '_'
38*8d67ca89SAndroid Build Coastguard Worker #endif /* !defined TZ_ABBR_ERR_CHAR */
39*8d67ca89SAndroid Build Coastguard Worker 
40*8d67ca89SAndroid Build Coastguard Worker /*
41*8d67ca89SAndroid Build Coastguard Worker +** Support non-POSIX platforms that distinguish between text and binary files.
42*8d67ca89SAndroid Build Coastguard Worker */
43*8d67ca89SAndroid Build Coastguard Worker 
44*8d67ca89SAndroid Build Coastguard Worker #ifndef O_BINARY
45*8d67ca89SAndroid Build Coastguard Worker # define O_BINARY 0
46*8d67ca89SAndroid Build Coastguard Worker #endif
47*8d67ca89SAndroid Build Coastguard Worker 
48*8d67ca89SAndroid Build Coastguard Worker #ifndef WILDABBR
49*8d67ca89SAndroid Build Coastguard Worker /*
50*8d67ca89SAndroid Build Coastguard Worker ** Someone might make incorrect use of a time zone abbreviation:
51*8d67ca89SAndroid Build Coastguard Worker **  1.  They might reference tzname[0] before calling tzset (explicitly
52*8d67ca89SAndroid Build Coastguard Worker **      or implicitly).
53*8d67ca89SAndroid Build Coastguard Worker **  2.  They might reference tzname[1] before calling tzset (explicitly
54*8d67ca89SAndroid Build Coastguard Worker **      or implicitly).
55*8d67ca89SAndroid Build Coastguard Worker **  3.  They might reference tzname[1] after setting to a time zone
56*8d67ca89SAndroid Build Coastguard Worker **      in which Daylight Saving Time is never observed.
57*8d67ca89SAndroid Build Coastguard Worker **  4.  They might reference tzname[0] after setting to a time zone
58*8d67ca89SAndroid Build Coastguard Worker **      in which Standard Time is never observed.
59*8d67ca89SAndroid Build Coastguard Worker **  5.  They might reference tm.TM_ZONE after calling offtime.
60*8d67ca89SAndroid Build Coastguard Worker ** What's best to do in the above cases is open to debate;
61*8d67ca89SAndroid Build Coastguard Worker ** for now, we just set things up so that in any of the five cases
62*8d67ca89SAndroid Build Coastguard Worker ** WILDABBR is used. Another possibility: initialize tzname[0] to the
63*8d67ca89SAndroid Build Coastguard Worker ** string "tzname[0] used before set", and similarly for the other cases.
64*8d67ca89SAndroid Build Coastguard Worker ** And another: initialize tzname[0] to "ERA", with an explanation in the
65*8d67ca89SAndroid Build Coastguard Worker ** manual page of what this "time zone abbreviation" means (doing this so
66*8d67ca89SAndroid Build Coastguard Worker ** that tzname[0] has the "normal" length of three characters).
67*8d67ca89SAndroid Build Coastguard Worker */
68*8d67ca89SAndroid Build Coastguard Worker # define WILDABBR    "   "
69*8d67ca89SAndroid Build Coastguard Worker #endif /* !defined WILDABBR */
70*8d67ca89SAndroid Build Coastguard Worker 
71*8d67ca89SAndroid Build Coastguard Worker static const char       wildabbr[] = WILDABBR;
72*8d67ca89SAndroid Build Coastguard Worker 
73*8d67ca89SAndroid Build Coastguard Worker static char const etc_utc[] = "Etc/UTC";
74*8d67ca89SAndroid Build Coastguard Worker static char const *utc = etc_utc + sizeof "Etc/" - 1;
75*8d67ca89SAndroid Build Coastguard Worker 
76*8d67ca89SAndroid Build Coastguard Worker /*
77*8d67ca89SAndroid Build Coastguard Worker ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
78*8d67ca89SAndroid Build Coastguard Worker ** Default to US rules as of 2017-05-07.
79*8d67ca89SAndroid Build Coastguard Worker ** POSIX does not specify the default DST rules;
80*8d67ca89SAndroid Build Coastguard Worker ** for historical reasons, US rules are a common default.
81*8d67ca89SAndroid Build Coastguard Worker */
82*8d67ca89SAndroid Build Coastguard Worker #ifndef TZDEFRULESTRING
83*8d67ca89SAndroid Build Coastguard Worker # define TZDEFRULESTRING ",M3.2.0,M11.1.0"
84*8d67ca89SAndroid Build Coastguard Worker #endif
85*8d67ca89SAndroid Build Coastguard Worker 
86*8d67ca89SAndroid Build Coastguard Worker struct ttinfo {              /* time type information */
87*8d67ca89SAndroid Build Coastguard Worker     int_fast32_t tt_utoff; /* UT offset in seconds */
88*8d67ca89SAndroid Build Coastguard Worker     bool         tt_isdst;   /* used to set tm_isdst */
89*8d67ca89SAndroid Build Coastguard Worker     int          tt_desigidx; /* abbreviation list index */
90*8d67ca89SAndroid Build Coastguard Worker     bool         tt_ttisstd; /* transition is std time */
91*8d67ca89SAndroid Build Coastguard Worker     bool         tt_ttisut; /* transition is UT */
92*8d67ca89SAndroid Build Coastguard Worker };
93*8d67ca89SAndroid Build Coastguard Worker 
94*8d67ca89SAndroid Build Coastguard Worker struct lsinfo {              /* leap second information */
95*8d67ca89SAndroid Build Coastguard Worker     time_t       ls_trans;   /* transition time */
96*8d67ca89SAndroid Build Coastguard Worker     int_fast32_t ls_corr;    /* correction to apply */
97*8d67ca89SAndroid Build Coastguard Worker };
98*8d67ca89SAndroid Build Coastguard Worker 
99*8d67ca89SAndroid Build Coastguard Worker /* This abbreviation means local time is unspecified.  */
100*8d67ca89SAndroid Build Coastguard Worker static char const UNSPEC[] = "-00";
101*8d67ca89SAndroid Build Coastguard Worker 
102*8d67ca89SAndroid Build Coastguard Worker /* How many extra bytes are needed at the end of struct state's chars array.
103*8d67ca89SAndroid Build Coastguard Worker    This needs to be at least 1 for null termination in case the input
104*8d67ca89SAndroid Build Coastguard Worker    data isn't properly terminated, and it also needs to be big enough
105*8d67ca89SAndroid Build Coastguard Worker    for ttunspecified to work without crashing.  */
106*8d67ca89SAndroid Build Coastguard Worker enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 };
107*8d67ca89SAndroid Build Coastguard Worker 
108*8d67ca89SAndroid Build Coastguard Worker /* Limit to time zone abbreviation length in POSIX-style TZ strings.
109*8d67ca89SAndroid Build Coastguard Worker    This is distinct from TZ_MAX_CHARS, which limits TZif file contents.  */
110*8d67ca89SAndroid Build Coastguard Worker #ifndef TZNAME_MAXIMUM
111*8d67ca89SAndroid Build Coastguard Worker # define TZNAME_MAXIMUM 255
112*8d67ca89SAndroid Build Coastguard Worker #endif
113*8d67ca89SAndroid Build Coastguard Worker 
114*8d67ca89SAndroid Build Coastguard Worker struct state {
115*8d67ca89SAndroid Build Coastguard Worker     int           leapcnt;
116*8d67ca89SAndroid Build Coastguard Worker     int           timecnt;
117*8d67ca89SAndroid Build Coastguard Worker     int           typecnt;
118*8d67ca89SAndroid Build Coastguard Worker     int           charcnt;
119*8d67ca89SAndroid Build Coastguard Worker     bool          goback;
120*8d67ca89SAndroid Build Coastguard Worker     bool          goahead;
121*8d67ca89SAndroid Build Coastguard Worker     time_t        ats[TZ_MAX_TIMES];
122*8d67ca89SAndroid Build Coastguard Worker     unsigned char types[TZ_MAX_TIMES];
123*8d67ca89SAndroid Build Coastguard Worker     struct ttinfo ttis[TZ_MAX_TYPES];
124*8d67ca89SAndroid Build Coastguard Worker     char chars[max(max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof "UTC"),
125*8d67ca89SAndroid Build Coastguard Worker 		         2 * (TZNAME_MAXIMUM + 1))];
126*8d67ca89SAndroid Build Coastguard Worker     struct lsinfo lsis[TZ_MAX_LEAPS];
127*8d67ca89SAndroid Build Coastguard Worker     /* The time type to use for early times or if no transitions.
128*8d67ca89SAndroid Build Coastguard Worker        It is always zero for recent tzdb releases.
129*8d67ca89SAndroid Build Coastguard Worker        It might be nonzero for data from tzdb 2018e or earlier.  */
130*8d67ca89SAndroid Build Coastguard Worker     int defaulttype;
131*8d67ca89SAndroid Build Coastguard Worker };
132*8d67ca89SAndroid Build Coastguard Worker 
133*8d67ca89SAndroid Build Coastguard Worker enum r_type {
134*8d67ca89SAndroid Build Coastguard Worker   JULIAN_DAY,		/* Jn = Julian day */
135*8d67ca89SAndroid Build Coastguard Worker   DAY_OF_YEAR,		/* n = day of year */
136*8d67ca89SAndroid Build Coastguard Worker   MONTH_NTH_DAY_OF_WEEK	/* Mm.n.d = month, week, day of week */
137*8d67ca89SAndroid Build Coastguard Worker };
138*8d67ca89SAndroid Build Coastguard Worker 
139*8d67ca89SAndroid Build Coastguard Worker struct rule {
140*8d67ca89SAndroid Build Coastguard Worker 	enum r_type	r_type;		/* type of rule */
141*8d67ca89SAndroid Build Coastguard Worker     int          r_day;  /* day number of rule */
142*8d67ca89SAndroid Build Coastguard Worker     int          r_week; /* week number of rule */
143*8d67ca89SAndroid Build Coastguard Worker     int          r_mon;  /* month number of rule */
144*8d67ca89SAndroid Build Coastguard Worker     int_fast32_t r_time; /* transition time of rule */
145*8d67ca89SAndroid Build Coastguard Worker };
146*8d67ca89SAndroid Build Coastguard Worker 
147*8d67ca89SAndroid Build Coastguard Worker static struct tm *gmtsub(struct state const *, time_t const *, int_fast32_t,
148*8d67ca89SAndroid Build Coastguard Worker 			 struct tm *);
149*8d67ca89SAndroid Build Coastguard Worker static bool increment_overflow(int *, int);
150*8d67ca89SAndroid Build Coastguard Worker static bool increment_overflow_time(time_t *, int_fast32_t);
151*8d67ca89SAndroid Build Coastguard Worker static int_fast32_t leapcorr(struct state const *, time_t);
152*8d67ca89SAndroid Build Coastguard Worker static bool normalize_overflow32(int_fast32_t *, int *, int);
153*8d67ca89SAndroid Build Coastguard Worker static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
154*8d67ca89SAndroid Build Coastguard Worker 			  struct tm *);
155*8d67ca89SAndroid Build Coastguard Worker static bool typesequiv(struct state const *, int, int);
156*8d67ca89SAndroid Build Coastguard Worker static bool tzparse(char const *, struct state *, struct state *);
157*8d67ca89SAndroid Build Coastguard Worker 
158*8d67ca89SAndroid Build Coastguard Worker #ifdef ALL_STATE
159*8d67ca89SAndroid Build Coastguard Worker static struct state * lclptr;
160*8d67ca89SAndroid Build Coastguard Worker static struct state * gmtptr;
161*8d67ca89SAndroid Build Coastguard Worker #endif /* defined ALL_STATE */
162*8d67ca89SAndroid Build Coastguard Worker 
163*8d67ca89SAndroid Build Coastguard Worker #ifndef ALL_STATE
164*8d67ca89SAndroid Build Coastguard Worker static struct state lclmem;
165*8d67ca89SAndroid Build Coastguard Worker static struct state gmtmem;
166*8d67ca89SAndroid Build Coastguard Worker static struct state *const lclptr = &lclmem;
167*8d67ca89SAndroid Build Coastguard Worker static struct state *const gmtptr = &gmtmem;
168*8d67ca89SAndroid Build Coastguard Worker #endif /* State Farm */
169*8d67ca89SAndroid Build Coastguard Worker 
170*8d67ca89SAndroid Build Coastguard Worker #ifndef TZ_STRLEN_MAX
171*8d67ca89SAndroid Build Coastguard Worker # define TZ_STRLEN_MAX 255
172*8d67ca89SAndroid Build Coastguard Worker #endif /* !defined TZ_STRLEN_MAX */
173*8d67ca89SAndroid Build Coastguard Worker 
174*8d67ca89SAndroid Build Coastguard Worker static char lcl_TZname[TZ_STRLEN_MAX + 1];
175*8d67ca89SAndroid Build Coastguard Worker static int  lcl_is_set;
176*8d67ca89SAndroid Build Coastguard Worker 
177*8d67ca89SAndroid Build Coastguard Worker /*
178*8d67ca89SAndroid Build Coastguard Worker ** Section 4.12.3 of X3.159-1989 requires that
179*8d67ca89SAndroid Build Coastguard Worker **  Except for the strftime function, these functions [asctime,
180*8d67ca89SAndroid Build Coastguard Worker **  ctime, gmtime, localtime] return values in one of two static
181*8d67ca89SAndroid Build Coastguard Worker **  objects: a broken-down time structure and an array of char.
182*8d67ca89SAndroid Build Coastguard Worker ** Thanks to Paul Eggert for noting this.
183*8d67ca89SAndroid Build Coastguard Worker **
184*8d67ca89SAndroid Build Coastguard Worker ** This requirement was removed in C99, so support it only if requested,
185*8d67ca89SAndroid Build Coastguard Worker ** as support is more likely to lead to bugs in badly written programs.
186*8d67ca89SAndroid Build Coastguard Worker */
187*8d67ca89SAndroid Build Coastguard Worker 
188*8d67ca89SAndroid Build Coastguard Worker #if SUPPORT_C89
189*8d67ca89SAndroid Build Coastguard Worker static struct tm	tm;
190*8d67ca89SAndroid Build Coastguard Worker #endif
191*8d67ca89SAndroid Build Coastguard Worker 
192*8d67ca89SAndroid Build Coastguard Worker #if 2 <= HAVE_TZNAME + TZ_TIME_T
193*8d67ca89SAndroid Build Coastguard Worker char *			tzname[2] = {
194*8d67ca89SAndroid Build Coastguard Worker 	(char *) wildabbr,
195*8d67ca89SAndroid Build Coastguard Worker 	(char *) wildabbr
196*8d67ca89SAndroid Build Coastguard Worker };
197*8d67ca89SAndroid Build Coastguard Worker #endif
198*8d67ca89SAndroid Build Coastguard Worker #if 2 <= USG_COMPAT + TZ_TIME_T
199*8d67ca89SAndroid Build Coastguard Worker long			timezone;
200*8d67ca89SAndroid Build Coastguard Worker int			daylight;
201*8d67ca89SAndroid Build Coastguard Worker #endif
202*8d67ca89SAndroid Build Coastguard Worker 
203*8d67ca89SAndroid Build Coastguard Worker #if 2 <= ALTZONE + TZ_TIME_T
204*8d67ca89SAndroid Build Coastguard Worker long			altzone;
205*8d67ca89SAndroid Build Coastguard Worker #endif
206*8d67ca89SAndroid Build Coastguard Worker 
207*8d67ca89SAndroid Build Coastguard Worker /* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX.  */
208*8d67ca89SAndroid Build Coastguard Worker static void
init_ttinfo(struct ttinfo * s,int_fast32_t utoff,bool isdst,int desigidx)209*8d67ca89SAndroid Build Coastguard Worker init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
210*8d67ca89SAndroid Build Coastguard Worker {
211*8d67ca89SAndroid Build Coastguard Worker   s->tt_utoff = utoff;
212*8d67ca89SAndroid Build Coastguard Worker   s->tt_isdst = isdst;
213*8d67ca89SAndroid Build Coastguard Worker   s->tt_desigidx = desigidx;
214*8d67ca89SAndroid Build Coastguard Worker   s->tt_ttisstd = false;
215*8d67ca89SAndroid Build Coastguard Worker   s->tt_ttisut = false;
216*8d67ca89SAndroid Build Coastguard Worker }
217*8d67ca89SAndroid Build Coastguard Worker 
218*8d67ca89SAndroid Build Coastguard Worker /* Return true if SP's time type I does not specify local time.  */
219*8d67ca89SAndroid Build Coastguard Worker static bool
ttunspecified(struct state const * sp,int i)220*8d67ca89SAndroid Build Coastguard Worker ttunspecified(struct state const *sp, int i)
221*8d67ca89SAndroid Build Coastguard Worker {
222*8d67ca89SAndroid Build Coastguard Worker   char const *abbr = &sp->chars[sp->ttis[i].tt_desigidx];
223*8d67ca89SAndroid Build Coastguard Worker   /* memcmp is likely faster than strcmp, and is safe due to CHARS_EXTRA.  */
224*8d67ca89SAndroid Build Coastguard Worker   return memcmp(abbr, UNSPEC, sizeof UNSPEC) == 0;
225*8d67ca89SAndroid Build Coastguard Worker }
226*8d67ca89SAndroid Build Coastguard Worker 
227*8d67ca89SAndroid Build Coastguard Worker static int_fast32_t
detzcode(const char * const codep)228*8d67ca89SAndroid Build Coastguard Worker detzcode(const char *const codep)
229*8d67ca89SAndroid Build Coastguard Worker {
230*8d67ca89SAndroid Build Coastguard Worker 	register int_fast32_t	result;
231*8d67ca89SAndroid Build Coastguard Worker 	register int		i;
232*8d67ca89SAndroid Build Coastguard Worker 	int_fast32_t one = 1;
233*8d67ca89SAndroid Build Coastguard Worker 	int_fast32_t halfmaxval = one << (32 - 2);
234*8d67ca89SAndroid Build Coastguard Worker 	int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
235*8d67ca89SAndroid Build Coastguard Worker 	int_fast32_t minval = -1 - maxval;
236*8d67ca89SAndroid Build Coastguard Worker 
237*8d67ca89SAndroid Build Coastguard Worker 	result = codep[0] & 0x7f;
238*8d67ca89SAndroid Build Coastguard Worker 	for (i = 1; i < 4; ++i)
239*8d67ca89SAndroid Build Coastguard Worker 		result = (result << 8) | (codep[i] & 0xff);
240*8d67ca89SAndroid Build Coastguard Worker 
241*8d67ca89SAndroid Build Coastguard Worker 	if (codep[0] & 0x80) {
242*8d67ca89SAndroid Build Coastguard Worker 	  /* Do two's-complement negation even on non-two's-complement machines.
243*8d67ca89SAndroid Build Coastguard Worker 	     If the result would be minval - 1, return minval.  */
244*8d67ca89SAndroid Build Coastguard Worker 	  result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
245*8d67ca89SAndroid Build Coastguard Worker 	  result += minval;
246*8d67ca89SAndroid Build Coastguard Worker 	}
247*8d67ca89SAndroid Build Coastguard Worker 	return result;
248*8d67ca89SAndroid Build Coastguard Worker }
249*8d67ca89SAndroid Build Coastguard Worker 
250*8d67ca89SAndroid Build Coastguard Worker static int_fast64_t
detzcode64(const char * const codep)251*8d67ca89SAndroid Build Coastguard Worker detzcode64(const char *const codep)
252*8d67ca89SAndroid Build Coastguard Worker {
253*8d67ca89SAndroid Build Coastguard Worker 	register int_fast64_t result;
254*8d67ca89SAndroid Build Coastguard Worker 	register int	i;
255*8d67ca89SAndroid Build Coastguard Worker 	int_fast64_t one = 1;
256*8d67ca89SAndroid Build Coastguard Worker 	int_fast64_t halfmaxval = one << (64 - 2);
257*8d67ca89SAndroid Build Coastguard Worker 	int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
258*8d67ca89SAndroid Build Coastguard Worker 	int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
259*8d67ca89SAndroid Build Coastguard Worker 
260*8d67ca89SAndroid Build Coastguard Worker 	result = codep[0] & 0x7f;
261*8d67ca89SAndroid Build Coastguard Worker 	for (i = 1; i < 8; ++i)
262*8d67ca89SAndroid Build Coastguard Worker 		result = (result << 8) | (codep[i] & 0xff);
263*8d67ca89SAndroid Build Coastguard Worker 
264*8d67ca89SAndroid Build Coastguard Worker 	if (codep[0] & 0x80) {
265*8d67ca89SAndroid Build Coastguard Worker 	  /* Do two's-complement negation even on non-two's-complement machines.
266*8d67ca89SAndroid Build Coastguard Worker 	     If the result would be minval - 1, return minval.  */
267*8d67ca89SAndroid Build Coastguard Worker 	  result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
268*8d67ca89SAndroid Build Coastguard Worker 	  result += minval;
269*8d67ca89SAndroid Build Coastguard Worker 	}
270*8d67ca89SAndroid Build Coastguard Worker 	return result;
271*8d67ca89SAndroid Build Coastguard Worker }
272*8d67ca89SAndroid Build Coastguard Worker 
273*8d67ca89SAndroid Build Coastguard Worker static void
update_tzname_etc(struct state const * sp,struct ttinfo const * ttisp)274*8d67ca89SAndroid Build Coastguard Worker update_tzname_etc(struct state const *sp, struct ttinfo const *ttisp)
275*8d67ca89SAndroid Build Coastguard Worker {
276*8d67ca89SAndroid Build Coastguard Worker #if HAVE_TZNAME
277*8d67ca89SAndroid Build Coastguard Worker   tzname[ttisp->tt_isdst] = (char *) &sp->chars[ttisp->tt_desigidx];
278*8d67ca89SAndroid Build Coastguard Worker #endif
279*8d67ca89SAndroid Build Coastguard Worker #if USG_COMPAT
280*8d67ca89SAndroid Build Coastguard Worker   if (!ttisp->tt_isdst)
281*8d67ca89SAndroid Build Coastguard Worker     timezone = - ttisp->tt_utoff;
282*8d67ca89SAndroid Build Coastguard Worker #endif
283*8d67ca89SAndroid Build Coastguard Worker #if ALTZONE
284*8d67ca89SAndroid Build Coastguard Worker   if (ttisp->tt_isdst)
285*8d67ca89SAndroid Build Coastguard Worker     altzone = - ttisp->tt_utoff;
286*8d67ca89SAndroid Build Coastguard Worker #endif
287*8d67ca89SAndroid Build Coastguard Worker }
288*8d67ca89SAndroid Build Coastguard Worker 
289*8d67ca89SAndroid Build Coastguard Worker /* If STDDST_MASK indicates that SP's TYPE provides useful info,
290*8d67ca89SAndroid Build Coastguard Worker    update tzname, timezone, and/or altzone and return STDDST_MASK,
291*8d67ca89SAndroid Build Coastguard Worker    diminished by the provided info if it is a specified local time.
292*8d67ca89SAndroid Build Coastguard Worker    Otherwise, return STDDST_MASK.  See settzname for STDDST_MASK.  */
293*8d67ca89SAndroid Build Coastguard Worker static int
may_update_tzname_etc(int stddst_mask,struct state * sp,int type)294*8d67ca89SAndroid Build Coastguard Worker may_update_tzname_etc(int stddst_mask, struct state *sp, int type)
295*8d67ca89SAndroid Build Coastguard Worker {
296*8d67ca89SAndroid Build Coastguard Worker   struct ttinfo *ttisp = &sp->ttis[type];
297*8d67ca89SAndroid Build Coastguard Worker   int this_bit = 1 << ttisp->tt_isdst;
298*8d67ca89SAndroid Build Coastguard Worker   if (stddst_mask & this_bit) {
299*8d67ca89SAndroid Build Coastguard Worker     update_tzname_etc(sp, ttisp);
300*8d67ca89SAndroid Build Coastguard Worker     if (!ttunspecified(sp, type))
301*8d67ca89SAndroid Build Coastguard Worker       return stddst_mask & ~this_bit;
302*8d67ca89SAndroid Build Coastguard Worker   }
303*8d67ca89SAndroid Build Coastguard Worker   return stddst_mask;
304*8d67ca89SAndroid Build Coastguard Worker }
305*8d67ca89SAndroid Build Coastguard Worker 
306*8d67ca89SAndroid Build Coastguard Worker static void
settzname(void)307*8d67ca89SAndroid Build Coastguard Worker settzname(void)
308*8d67ca89SAndroid Build Coastguard Worker {
309*8d67ca89SAndroid Build Coastguard Worker 	register struct state * const	sp = lclptr;
310*8d67ca89SAndroid Build Coastguard Worker 	register int			i;
311*8d67ca89SAndroid Build Coastguard Worker 
312*8d67ca89SAndroid Build Coastguard Worker 	/* If STDDST_MASK & 1 we need info about a standard time.
313*8d67ca89SAndroid Build Coastguard Worker 	   If STDDST_MASK & 2 we need info about a daylight saving time.
314*8d67ca89SAndroid Build Coastguard Worker 	   When STDDST_MASK becomes zero we can stop looking.  */
315*8d67ca89SAndroid Build Coastguard Worker 	int stddst_mask = 0;
316*8d67ca89SAndroid Build Coastguard Worker 
317*8d67ca89SAndroid Build Coastguard Worker #if HAVE_TZNAME
318*8d67ca89SAndroid Build Coastguard Worker 	tzname[0] = tzname[1] = (char *) (sp ? wildabbr : utc);
319*8d67ca89SAndroid Build Coastguard Worker 	stddst_mask = 3;
320*8d67ca89SAndroid Build Coastguard Worker #endif
321*8d67ca89SAndroid Build Coastguard Worker #if USG_COMPAT
322*8d67ca89SAndroid Build Coastguard Worker 	timezone = 0;
323*8d67ca89SAndroid Build Coastguard Worker 	stddst_mask = 3;
324*8d67ca89SAndroid Build Coastguard Worker #endif
325*8d67ca89SAndroid Build Coastguard Worker #if ALTZONE
326*8d67ca89SAndroid Build Coastguard Worker 	altzone = 0;
327*8d67ca89SAndroid Build Coastguard Worker 	stddst_mask |= 2;
328*8d67ca89SAndroid Build Coastguard Worker #endif
329*8d67ca89SAndroid Build Coastguard Worker 	/*
330*8d67ca89SAndroid Build Coastguard Worker 	** And to get the latest time zone abbreviations into tzname. . .
331*8d67ca89SAndroid Build Coastguard Worker 	*/
332*8d67ca89SAndroid Build Coastguard Worker 	if (sp) {
333*8d67ca89SAndroid Build Coastguard Worker 	  for (i = sp->timecnt - 1; stddst_mask && 0 <= i; i--)
334*8d67ca89SAndroid Build Coastguard Worker 	    stddst_mask = may_update_tzname_etc(stddst_mask, sp, sp->types[i]);
335*8d67ca89SAndroid Build Coastguard Worker 	  for (i = sp->typecnt - 1; stddst_mask && 0 <= i; i--)
336*8d67ca89SAndroid Build Coastguard Worker 	    stddst_mask = may_update_tzname_etc(stddst_mask, sp, i);
337*8d67ca89SAndroid Build Coastguard Worker 	}
338*8d67ca89SAndroid Build Coastguard Worker #if USG_COMPAT
339*8d67ca89SAndroid Build Coastguard Worker 	daylight = stddst_mask >> 1 ^ 1;
340*8d67ca89SAndroid Build Coastguard Worker #endif
341*8d67ca89SAndroid Build Coastguard Worker }
342*8d67ca89SAndroid Build Coastguard Worker 
343*8d67ca89SAndroid Build Coastguard Worker /* Replace bogus characters in time zone abbreviations.
344*8d67ca89SAndroid Build Coastguard Worker    Return 0 on success, an errno value if a time zone abbreviation is
345*8d67ca89SAndroid Build Coastguard Worker    too long.  */
346*8d67ca89SAndroid Build Coastguard Worker static int
scrub_abbrs(struct state * sp)347*8d67ca89SAndroid Build Coastguard Worker scrub_abbrs(struct state *sp)
348*8d67ca89SAndroid Build Coastguard Worker {
349*8d67ca89SAndroid Build Coastguard Worker 	int i;
350*8d67ca89SAndroid Build Coastguard Worker 
351*8d67ca89SAndroid Build Coastguard Worker 	/* Reject overlong abbreviations.  */
352*8d67ca89SAndroid Build Coastguard Worker 	for (i = 0; i < sp->charcnt - (TZNAME_MAXIMUM + 1); ) {
353*8d67ca89SAndroid Build Coastguard Worker 	  int len = strlen(&sp->chars[i]);
354*8d67ca89SAndroid Build Coastguard Worker 	  if (TZNAME_MAXIMUM < len)
355*8d67ca89SAndroid Build Coastguard Worker 	    return EOVERFLOW;
356*8d67ca89SAndroid Build Coastguard Worker 	  i += len + 1;
357*8d67ca89SAndroid Build Coastguard Worker 	}
358*8d67ca89SAndroid Build Coastguard Worker 
359*8d67ca89SAndroid Build Coastguard Worker 	/* Replace bogus characters.  */
360*8d67ca89SAndroid Build Coastguard Worker 	for (i = 0; i < sp->charcnt; ++i)
361*8d67ca89SAndroid Build Coastguard Worker 		if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
362*8d67ca89SAndroid Build Coastguard Worker 			sp->chars[i] = TZ_ABBR_ERR_CHAR;
363*8d67ca89SAndroid Build Coastguard Worker 
364*8d67ca89SAndroid Build Coastguard Worker 	return 0;
365*8d67ca89SAndroid Build Coastguard Worker }
366*8d67ca89SAndroid Build Coastguard Worker 
367*8d67ca89SAndroid Build Coastguard Worker /* Input buffer for data read from a compiled tz file.  */
368*8d67ca89SAndroid Build Coastguard Worker union input_buffer {
369*8d67ca89SAndroid Build Coastguard Worker   /* The first part of the buffer, interpreted as a header.  */
370*8d67ca89SAndroid Build Coastguard Worker   struct tzhead tzhead;
371*8d67ca89SAndroid Build Coastguard Worker 
372*8d67ca89SAndroid Build Coastguard Worker   /* The entire buffer.  */
373*8d67ca89SAndroid Build Coastguard Worker   char buf[2 * sizeof(struct tzhead) + 2 * sizeof(struct state)
374*8d67ca89SAndroid Build Coastguard Worker      + 4 * TZ_MAX_TIMES];
375*8d67ca89SAndroid Build Coastguard Worker };
376*8d67ca89SAndroid Build Coastguard Worker 
377*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
378*8d67ca89SAndroid Build Coastguard Worker // Android: there is no directory with one file per timezone on Android,
379*8d67ca89SAndroid Build Coastguard Worker // but we do have a system property instead.
380*8d67ca89SAndroid Build Coastguard Worker #include <sys/system_properties.h>
381*8d67ca89SAndroid Build Coastguard Worker #else
382*8d67ca89SAndroid Build Coastguard Worker /* TZDIR with a trailing '/' rather than a trailing '\0'.  */
383*8d67ca89SAndroid Build Coastguard Worker static char const tzdirslash[sizeof TZDIR] = TZDIR "/";
384*8d67ca89SAndroid Build Coastguard Worker #endif
385*8d67ca89SAndroid Build Coastguard Worker 
386*8d67ca89SAndroid Build Coastguard Worker /* Local storage needed for 'tzloadbody'.  */
387*8d67ca89SAndroid Build Coastguard Worker union local_storage {
388*8d67ca89SAndroid Build Coastguard Worker   /* The results of analyzing the file's contents after it is opened.  */
389*8d67ca89SAndroid Build Coastguard Worker   struct file_analysis {
390*8d67ca89SAndroid Build Coastguard Worker     /* The input buffer.  */
391*8d67ca89SAndroid Build Coastguard Worker     union input_buffer u;
392*8d67ca89SAndroid Build Coastguard Worker 
393*8d67ca89SAndroid Build Coastguard Worker     /* A temporary state used for parsing a TZ string in the file.  */
394*8d67ca89SAndroid Build Coastguard Worker     struct state st;
395*8d67ca89SAndroid Build Coastguard Worker   } u;
396*8d67ca89SAndroid Build Coastguard Worker 
397*8d67ca89SAndroid Build Coastguard Worker   // Android-removed: There is no directory with file-per-time zone on Android.
398*8d67ca89SAndroid Build Coastguard Worker   #ifndef __BIONIC__
399*8d67ca89SAndroid Build Coastguard Worker   /* The file name to be opened.  */
400*8d67ca89SAndroid Build Coastguard Worker   char fullname[max(sizeof(struct file_analysis), sizeof tzdirslash + 1024)];
401*8d67ca89SAndroid Build Coastguard Worker   #endif
402*8d67ca89SAndroid Build Coastguard Worker };
403*8d67ca89SAndroid Build Coastguard Worker 
404*8d67ca89SAndroid Build Coastguard Worker /* Load tz data from the file named NAME into *SP.  Read extended
405*8d67ca89SAndroid Build Coastguard Worker    format if DOEXTEND.  Use *LSP for temporary storage.  Return 0 on
406*8d67ca89SAndroid Build Coastguard Worker    success, an errno value on failure.  */
407*8d67ca89SAndroid Build Coastguard Worker static int
tzloadbody(char const * name,struct state * sp,bool doextend,union local_storage * lsp)408*8d67ca89SAndroid Build Coastguard Worker tzloadbody(char const *name, struct state *sp, bool doextend,
409*8d67ca89SAndroid Build Coastguard Worker 	   union local_storage *lsp)
410*8d67ca89SAndroid Build Coastguard Worker {
411*8d67ca89SAndroid Build Coastguard Worker 	register int			i;
412*8d67ca89SAndroid Build Coastguard Worker 	register int			fid;
413*8d67ca89SAndroid Build Coastguard Worker 	register int			stored;
414*8d67ca89SAndroid Build Coastguard Worker 	register ssize_t		nread;
415*8d67ca89SAndroid Build Coastguard Worker #if !defined(__BIONIC__)
416*8d67ca89SAndroid Build Coastguard Worker 	register bool doaccess;
417*8d67ca89SAndroid Build Coastguard Worker 	register char *fullname = lsp->fullname;
418*8d67ca89SAndroid Build Coastguard Worker #endif
419*8d67ca89SAndroid Build Coastguard Worker 	register union input_buffer *up = &lsp->u.u;
420*8d67ca89SAndroid Build Coastguard Worker 	register int tzheadsize = sizeof(struct tzhead);
421*8d67ca89SAndroid Build Coastguard Worker 	char system_tz_name[PROP_VALUE_MAX];
422*8d67ca89SAndroid Build Coastguard Worker 
423*8d67ca89SAndroid Build Coastguard Worker 	sp->goback = sp->goahead = false;
424*8d67ca89SAndroid Build Coastguard Worker 
425*8d67ca89SAndroid Build Coastguard Worker 	if (! name) {
426*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
427*8d67ca89SAndroid Build Coastguard Worker 		extern void __bionic_get_system_tz(char* , size_t);
428*8d67ca89SAndroid Build Coastguard Worker 		__bionic_get_system_tz(system_tz_name, sizeof(system_tz_name));
429*8d67ca89SAndroid Build Coastguard Worker 		name = system_tz_name;
430*8d67ca89SAndroid Build Coastguard Worker #else
431*8d67ca89SAndroid Build Coastguard Worker 		name = TZDEFAULT;
432*8d67ca89SAndroid Build Coastguard Worker 		if (! name)
433*8d67ca89SAndroid Build Coastguard Worker 		  return EINVAL;
434*8d67ca89SAndroid Build Coastguard Worker #endif
435*8d67ca89SAndroid Build Coastguard Worker 	}
436*8d67ca89SAndroid Build Coastguard Worker 
437*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
438*8d67ca89SAndroid Build Coastguard Worker 	extern int __bionic_open_tzdata(const char*, int32_t*);
439*8d67ca89SAndroid Build Coastguard Worker 	int32_t entry_length;
440*8d67ca89SAndroid Build Coastguard Worker 	fid = __bionic_open_tzdata(name, &entry_length);
441*8d67ca89SAndroid Build Coastguard Worker #else
442*8d67ca89SAndroid Build Coastguard Worker 	if (name[0] == ':')
443*8d67ca89SAndroid Build Coastguard Worker 		++name;
444*8d67ca89SAndroid Build Coastguard Worker #ifdef SUPPRESS_TZDIR
445*8d67ca89SAndroid Build Coastguard Worker 	/* Do not prepend TZDIR.  This is intended for specialized
446*8d67ca89SAndroid Build Coastguard Worker 	   applications only, due to its security implications.  */
447*8d67ca89SAndroid Build Coastguard Worker 	doaccess = true;
448*8d67ca89SAndroid Build Coastguard Worker #else
449*8d67ca89SAndroid Build Coastguard Worker 	doaccess = name[0] == '/';
450*8d67ca89SAndroid Build Coastguard Worker #endif
451*8d67ca89SAndroid Build Coastguard Worker 	if (!doaccess) {
452*8d67ca89SAndroid Build Coastguard Worker 		char const *dot;
453*8d67ca89SAndroid Build Coastguard Worker 		if (sizeof lsp->fullname - sizeof tzdirslash <= strlen(name))
454*8d67ca89SAndroid Build Coastguard Worker 		  return ENAMETOOLONG;
455*8d67ca89SAndroid Build Coastguard Worker 
456*8d67ca89SAndroid Build Coastguard Worker 		/* Create a string "TZDIR/NAME".  Using sprintf here
457*8d67ca89SAndroid Build Coastguard Worker 		   would pull in stdio (and would fail if the
458*8d67ca89SAndroid Build Coastguard Worker 		   resulting string length exceeded INT_MAX!).  */
459*8d67ca89SAndroid Build Coastguard Worker 		memcpy(lsp->fullname, tzdirslash, sizeof tzdirslash);
460*8d67ca89SAndroid Build Coastguard Worker 		strcpy(lsp->fullname + sizeof tzdirslash, name);
461*8d67ca89SAndroid Build Coastguard Worker 
462*8d67ca89SAndroid Build Coastguard Worker 		/* Set doaccess if NAME contains a ".." file name
463*8d67ca89SAndroid Build Coastguard Worker 		   component, as such a name could read a file outside
464*8d67ca89SAndroid Build Coastguard Worker 		   the TZDIR virtual subtree.  */
465*8d67ca89SAndroid Build Coastguard Worker 		for (dot = name; (dot = strchr(dot, '.')); dot++)
466*8d67ca89SAndroid Build Coastguard Worker 		  if ((dot == name || dot[-1] == '/') && dot[1] == '.'
467*8d67ca89SAndroid Build Coastguard Worker 		      && (dot[2] == '/' || !dot[2])) {
468*8d67ca89SAndroid Build Coastguard Worker 		    doaccess = true;
469*8d67ca89SAndroid Build Coastguard Worker 		    break;
470*8d67ca89SAndroid Build Coastguard Worker 		  }
471*8d67ca89SAndroid Build Coastguard Worker 
472*8d67ca89SAndroid Build Coastguard Worker 		name = lsp->fullname;
473*8d67ca89SAndroid Build Coastguard Worker 	}
474*8d67ca89SAndroid Build Coastguard Worker 	if (doaccess && access(name, R_OK) != 0)
475*8d67ca89SAndroid Build Coastguard Worker 	  return errno;
476*8d67ca89SAndroid Build Coastguard Worker   fid = open(name, O_RDONLY | O_BINARY);
477*8d67ca89SAndroid Build Coastguard Worker #endif
478*8d67ca89SAndroid Build Coastguard Worker 	if (fid < 0)
479*8d67ca89SAndroid Build Coastguard Worker 	  return errno;
480*8d67ca89SAndroid Build Coastguard Worker 
481*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
482*8d67ca89SAndroid Build Coastguard Worker 	nread = TEMP_FAILURE_RETRY(read(fid, up->buf, entry_length));
483*8d67ca89SAndroid Build Coastguard Worker #else
484*8d67ca89SAndroid Build Coastguard Worker 	nread = read(fid, up->buf, sizeof up->buf);
485*8d67ca89SAndroid Build Coastguard Worker #endif
486*8d67ca89SAndroid Build Coastguard Worker 	if (nread < tzheadsize) {
487*8d67ca89SAndroid Build Coastguard Worker 	  int err = nread < 0 ? errno : EINVAL;
488*8d67ca89SAndroid Build Coastguard Worker 	  close(fid);
489*8d67ca89SAndroid Build Coastguard Worker 	  return err;
490*8d67ca89SAndroid Build Coastguard Worker 	}
491*8d67ca89SAndroid Build Coastguard Worker 	if (close(fid) < 0)
492*8d67ca89SAndroid Build Coastguard Worker 	  return errno;
493*8d67ca89SAndroid Build Coastguard Worker 	for (stored = 4; stored <= 8; stored *= 2) {
494*8d67ca89SAndroid Build Coastguard Worker 	    char version = up->tzhead.tzh_version[0];
495*8d67ca89SAndroid Build Coastguard Worker 	    bool skip_datablock = stored == 4 && version;
496*8d67ca89SAndroid Build Coastguard Worker 	    int_fast32_t datablock_size;
497*8d67ca89SAndroid Build Coastguard Worker 	    int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
498*8d67ca89SAndroid Build Coastguard Worker 	    int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
499*8d67ca89SAndroid Build Coastguard Worker 	    int_fast64_t prevtr = -1;
500*8d67ca89SAndroid Build Coastguard Worker 	    int_fast32_t prevcorr;
501*8d67ca89SAndroid Build Coastguard Worker 	    int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
502*8d67ca89SAndroid Build Coastguard Worker 	    int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
503*8d67ca89SAndroid Build Coastguard Worker 	    int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
504*8d67ca89SAndroid Build Coastguard Worker 	    int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
505*8d67ca89SAndroid Build Coastguard Worker 	    char const *p = up->buf + tzheadsize;
506*8d67ca89SAndroid Build Coastguard Worker 	    /* Although tzfile(5) currently requires typecnt to be nonzero,
507*8d67ca89SAndroid Build Coastguard Worker 	       support future formats that may allow zero typecnt
508*8d67ca89SAndroid Build Coastguard Worker 	       in files that have a TZ string and no transitions.  */
509*8d67ca89SAndroid Build Coastguard Worker 	    if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
510*8d67ca89SAndroid Build Coastguard Worker 		   && 0 <= typecnt && typecnt < TZ_MAX_TYPES
511*8d67ca89SAndroid Build Coastguard Worker 		   && 0 <= timecnt && timecnt < TZ_MAX_TIMES
512*8d67ca89SAndroid Build Coastguard Worker 		   && 0 <= charcnt && charcnt < TZ_MAX_CHARS
513*8d67ca89SAndroid Build Coastguard Worker 		   && 0 <= ttisstdcnt && ttisstdcnt < TZ_MAX_TYPES
514*8d67ca89SAndroid Build Coastguard Worker 		   && 0 <= ttisutcnt && ttisutcnt < TZ_MAX_TYPES))
515*8d67ca89SAndroid Build Coastguard Worker 	      return EINVAL;
516*8d67ca89SAndroid Build Coastguard Worker 	    datablock_size
517*8d67ca89SAndroid Build Coastguard Worker 		    = (timecnt * stored		/* ats */
518*8d67ca89SAndroid Build Coastguard Worker 		       + timecnt		/* types */
519*8d67ca89SAndroid Build Coastguard Worker 		       + typecnt * 6		/* ttinfos */
520*8d67ca89SAndroid Build Coastguard Worker 		       + charcnt		/* chars */
521*8d67ca89SAndroid Build Coastguard Worker 		       + leapcnt * (stored + 4)	/* lsinfos */
522*8d67ca89SAndroid Build Coastguard Worker 		       + ttisstdcnt		/* ttisstds */
523*8d67ca89SAndroid Build Coastguard Worker 		       + ttisutcnt);		/* ttisuts */
524*8d67ca89SAndroid Build Coastguard Worker 	    if (nread < tzheadsize + datablock_size)
525*8d67ca89SAndroid Build Coastguard Worker 	      return EINVAL;
526*8d67ca89SAndroid Build Coastguard Worker 	    if (skip_datablock)
527*8d67ca89SAndroid Build Coastguard Worker 		p += datablock_size;
528*8d67ca89SAndroid Build Coastguard Worker 	    else {
529*8d67ca89SAndroid Build Coastguard Worker 		if (! ((ttisstdcnt == typecnt || ttisstdcnt == 0)
530*8d67ca89SAndroid Build Coastguard Worker 		       && (ttisutcnt == typecnt || ttisutcnt == 0)))
531*8d67ca89SAndroid Build Coastguard Worker 		  return EINVAL;
532*8d67ca89SAndroid Build Coastguard Worker 
533*8d67ca89SAndroid Build Coastguard Worker 		sp->leapcnt = leapcnt;
534*8d67ca89SAndroid Build Coastguard Worker 		sp->timecnt = timecnt;
535*8d67ca89SAndroid Build Coastguard Worker 		sp->typecnt = typecnt;
536*8d67ca89SAndroid Build Coastguard Worker 		sp->charcnt = charcnt;
537*8d67ca89SAndroid Build Coastguard Worker 
538*8d67ca89SAndroid Build Coastguard Worker 		/* Read transitions, discarding those out of time_t range.
539*8d67ca89SAndroid Build Coastguard Worker 		   But pretend the last transition before TIME_T_MIN
540*8d67ca89SAndroid Build Coastguard Worker 		   occurred at TIME_T_MIN.  */
541*8d67ca89SAndroid Build Coastguard Worker 		timecnt = 0;
542*8d67ca89SAndroid Build Coastguard Worker 		for (i = 0; i < sp->timecnt; ++i) {
543*8d67ca89SAndroid Build Coastguard Worker 			int_fast64_t at
544*8d67ca89SAndroid Build Coastguard Worker 			  = stored == 4 ? detzcode(p) : detzcode64(p);
545*8d67ca89SAndroid Build Coastguard Worker 			sp->types[i] = at <= TIME_T_MAX;
546*8d67ca89SAndroid Build Coastguard Worker 			if (sp->types[i]) {
547*8d67ca89SAndroid Build Coastguard Worker 			  time_t attime
548*8d67ca89SAndroid Build Coastguard Worker 			    = ((TYPE_SIGNED(time_t) ? at < TIME_T_MIN : at < 0)
549*8d67ca89SAndroid Build Coastguard Worker 			       ? TIME_T_MIN : at);
550*8d67ca89SAndroid Build Coastguard Worker 			  if (timecnt && attime <= sp->ats[timecnt - 1]) {
551*8d67ca89SAndroid Build Coastguard Worker 			    if (attime < sp->ats[timecnt - 1])
552*8d67ca89SAndroid Build Coastguard Worker 			      return EINVAL;
553*8d67ca89SAndroid Build Coastguard Worker 			    sp->types[i - 1] = 0;
554*8d67ca89SAndroid Build Coastguard Worker 			    timecnt--;
555*8d67ca89SAndroid Build Coastguard Worker 			  }
556*8d67ca89SAndroid Build Coastguard Worker 			  sp->ats[timecnt++] = attime;
557*8d67ca89SAndroid Build Coastguard Worker 			}
558*8d67ca89SAndroid Build Coastguard Worker 			p += stored;
559*8d67ca89SAndroid Build Coastguard Worker 		}
560*8d67ca89SAndroid Build Coastguard Worker 
561*8d67ca89SAndroid Build Coastguard Worker 		timecnt = 0;
562*8d67ca89SAndroid Build Coastguard Worker 		for (i = 0; i < sp->timecnt; ++i) {
563*8d67ca89SAndroid Build Coastguard Worker 			unsigned char typ = *p++;
564*8d67ca89SAndroid Build Coastguard Worker 			if (sp->typecnt <= typ)
565*8d67ca89SAndroid Build Coastguard Worker 			  return EINVAL;
566*8d67ca89SAndroid Build Coastguard Worker 			if (sp->types[i])
567*8d67ca89SAndroid Build Coastguard Worker 				sp->types[timecnt++] = typ;
568*8d67ca89SAndroid Build Coastguard Worker 		}
569*8d67ca89SAndroid Build Coastguard Worker 		sp->timecnt = timecnt;
570*8d67ca89SAndroid Build Coastguard Worker 		for (i = 0; i < sp->typecnt; ++i) {
571*8d67ca89SAndroid Build Coastguard Worker 			register struct ttinfo *	ttisp;
572*8d67ca89SAndroid Build Coastguard Worker 			unsigned char isdst, desigidx;
573*8d67ca89SAndroid Build Coastguard Worker 
574*8d67ca89SAndroid Build Coastguard Worker 			ttisp = &sp->ttis[i];
575*8d67ca89SAndroid Build Coastguard Worker 			ttisp->tt_utoff = detzcode(p);
576*8d67ca89SAndroid Build Coastguard Worker 			p += 4;
577*8d67ca89SAndroid Build Coastguard Worker 			isdst = *p++;
578*8d67ca89SAndroid Build Coastguard Worker 			if (! (isdst < 2))
579*8d67ca89SAndroid Build Coastguard Worker 			  return EINVAL;
580*8d67ca89SAndroid Build Coastguard Worker 			ttisp->tt_isdst = isdst;
581*8d67ca89SAndroid Build Coastguard Worker 			desigidx = *p++;
582*8d67ca89SAndroid Build Coastguard Worker 			if (! (desigidx < sp->charcnt))
583*8d67ca89SAndroid Build Coastguard Worker 			  return EINVAL;
584*8d67ca89SAndroid Build Coastguard Worker 			ttisp->tt_desigidx = desigidx;
585*8d67ca89SAndroid Build Coastguard Worker 		}
586*8d67ca89SAndroid Build Coastguard Worker 		for (i = 0; i < sp->charcnt; ++i)
587*8d67ca89SAndroid Build Coastguard Worker 			sp->chars[i] = *p++;
588*8d67ca89SAndroid Build Coastguard Worker 		/* Ensure '\0'-terminated, and make it safe to call
589*8d67ca89SAndroid Build Coastguard Worker 		   ttunspecified later.  */
590*8d67ca89SAndroid Build Coastguard Worker 		memset(&sp->chars[i], 0, CHARS_EXTRA);
591*8d67ca89SAndroid Build Coastguard Worker 
592*8d67ca89SAndroid Build Coastguard Worker 		/* Read leap seconds, discarding those out of time_t range.  */
593*8d67ca89SAndroid Build Coastguard Worker 		leapcnt = 0;
594*8d67ca89SAndroid Build Coastguard Worker 		for (i = 0; i < sp->leapcnt; ++i) {
595*8d67ca89SAndroid Build Coastguard Worker 		  int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
596*8d67ca89SAndroid Build Coastguard Worker 		  int_fast32_t corr = detzcode(p + stored);
597*8d67ca89SAndroid Build Coastguard Worker 		  p += stored + 4;
598*8d67ca89SAndroid Build Coastguard Worker 
599*8d67ca89SAndroid Build Coastguard Worker 		  /* Leap seconds cannot occur before the Epoch,
600*8d67ca89SAndroid Build Coastguard Worker 		     or out of order.  */
601*8d67ca89SAndroid Build Coastguard Worker 		  if (tr <= prevtr)
602*8d67ca89SAndroid Build Coastguard Worker 		    return EINVAL;
603*8d67ca89SAndroid Build Coastguard Worker 
604*8d67ca89SAndroid Build Coastguard Worker 		  /* To avoid other botches in this code, each leap second's
605*8d67ca89SAndroid Build Coastguard Worker 		     correction must differ from the previous one's by 1
606*8d67ca89SAndroid Build Coastguard Worker 		     second or less, except that the first correction can be
607*8d67ca89SAndroid Build Coastguard Worker 		     any value; these requirements are more generous than
608*8d67ca89SAndroid Build Coastguard Worker 		     RFC 8536, to allow future RFC extensions.  */
609*8d67ca89SAndroid Build Coastguard Worker 		  if (! (i == 0
610*8d67ca89SAndroid Build Coastguard Worker 			 || (prevcorr < corr
611*8d67ca89SAndroid Build Coastguard Worker 			     ? corr == prevcorr + 1
612*8d67ca89SAndroid Build Coastguard Worker 			     : (corr == prevcorr
613*8d67ca89SAndroid Build Coastguard Worker 				|| corr == prevcorr - 1))))
614*8d67ca89SAndroid Build Coastguard Worker 		    return EINVAL;
615*8d67ca89SAndroid Build Coastguard Worker 		  prevtr = tr;
616*8d67ca89SAndroid Build Coastguard Worker 		  prevcorr = corr;
617*8d67ca89SAndroid Build Coastguard Worker 
618*8d67ca89SAndroid Build Coastguard Worker 		  if (tr <= TIME_T_MAX) {
619*8d67ca89SAndroid Build Coastguard Worker 		    sp->lsis[leapcnt].ls_trans = tr;
620*8d67ca89SAndroid Build Coastguard Worker 		    sp->lsis[leapcnt].ls_corr = corr;
621*8d67ca89SAndroid Build Coastguard Worker 		    leapcnt++;
622*8d67ca89SAndroid Build Coastguard Worker 		  }
623*8d67ca89SAndroid Build Coastguard Worker 		}
624*8d67ca89SAndroid Build Coastguard Worker 		sp->leapcnt = leapcnt;
625*8d67ca89SAndroid Build Coastguard Worker 
626*8d67ca89SAndroid Build Coastguard Worker 		for (i = 0; i < sp->typecnt; ++i) {
627*8d67ca89SAndroid Build Coastguard Worker 			register struct ttinfo *	ttisp;
628*8d67ca89SAndroid Build Coastguard Worker 
629*8d67ca89SAndroid Build Coastguard Worker 			ttisp = &sp->ttis[i];
630*8d67ca89SAndroid Build Coastguard Worker 			if (ttisstdcnt == 0)
631*8d67ca89SAndroid Build Coastguard Worker 				ttisp->tt_ttisstd = false;
632*8d67ca89SAndroid Build Coastguard Worker 			else {
633*8d67ca89SAndroid Build Coastguard Worker 				if (*p != true && *p != false)
634*8d67ca89SAndroid Build Coastguard Worker 				  return EINVAL;
635*8d67ca89SAndroid Build Coastguard Worker 				ttisp->tt_ttisstd = *p++;
636*8d67ca89SAndroid Build Coastguard Worker 			}
637*8d67ca89SAndroid Build Coastguard Worker 		}
638*8d67ca89SAndroid Build Coastguard Worker 		for (i = 0; i < sp->typecnt; ++i) {
639*8d67ca89SAndroid Build Coastguard Worker 			register struct ttinfo *	ttisp;
640*8d67ca89SAndroid Build Coastguard Worker 
641*8d67ca89SAndroid Build Coastguard Worker 			ttisp = &sp->ttis[i];
642*8d67ca89SAndroid Build Coastguard Worker 			if (ttisutcnt == 0)
643*8d67ca89SAndroid Build Coastguard Worker 				ttisp->tt_ttisut = false;
644*8d67ca89SAndroid Build Coastguard Worker 			else {
645*8d67ca89SAndroid Build Coastguard Worker 				if (*p != true && *p != false)
646*8d67ca89SAndroid Build Coastguard Worker 						return EINVAL;
647*8d67ca89SAndroid Build Coastguard Worker 				ttisp->tt_ttisut = *p++;
648*8d67ca89SAndroid Build Coastguard Worker 			}
649*8d67ca89SAndroid Build Coastguard Worker 		}
650*8d67ca89SAndroid Build Coastguard Worker 	    }
651*8d67ca89SAndroid Build Coastguard Worker 
652*8d67ca89SAndroid Build Coastguard Worker 	    nread -= p - up->buf;
653*8d67ca89SAndroid Build Coastguard Worker 	    memmove(up->buf, p, nread);
654*8d67ca89SAndroid Build Coastguard Worker 
655*8d67ca89SAndroid Build Coastguard Worker 	    /* If this is an old file, we're done.  */
656*8d67ca89SAndroid Build Coastguard Worker 	    if (!version)
657*8d67ca89SAndroid Build Coastguard Worker 	      break;
658*8d67ca89SAndroid Build Coastguard Worker 	}
659*8d67ca89SAndroid Build Coastguard Worker 	if (doextend && nread > 2 &&
660*8d67ca89SAndroid Build Coastguard Worker 		up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
661*8d67ca89SAndroid Build Coastguard Worker 		sp->typecnt + 2 <= TZ_MAX_TYPES) {
662*8d67ca89SAndroid Build Coastguard Worker 			struct state	*ts = &lsp->u.st;
663*8d67ca89SAndroid Build Coastguard Worker 
664*8d67ca89SAndroid Build Coastguard Worker 			up->buf[nread - 1] = '\0';
665*8d67ca89SAndroid Build Coastguard Worker 			if (tzparse(&up->buf[1], ts, sp)) {
666*8d67ca89SAndroid Build Coastguard Worker 
667*8d67ca89SAndroid Build Coastguard Worker 			  /* Attempt to reuse existing abbreviations.
668*8d67ca89SAndroid Build Coastguard Worker 			     Without this, America/Anchorage would be right on
669*8d67ca89SAndroid Build Coastguard Worker 			     the edge after 2037 when TZ_MAX_CHARS is 50, as
670*8d67ca89SAndroid Build Coastguard Worker 			     sp->charcnt equals 40 (for LMT AST AWT APT AHST
671*8d67ca89SAndroid Build Coastguard Worker 			     AHDT YST AKDT AKST) and ts->charcnt equals 10
672*8d67ca89SAndroid Build Coastguard Worker 			     (for AKST AKDT).  Reusing means sp->charcnt can
673*8d67ca89SAndroid Build Coastguard Worker 			     stay 40 in this example.  */
674*8d67ca89SAndroid Build Coastguard Worker 			  int gotabbr = 0;
675*8d67ca89SAndroid Build Coastguard Worker 			  int charcnt = sp->charcnt;
676*8d67ca89SAndroid Build Coastguard Worker 			  for (i = 0; i < ts->typecnt; i++) {
677*8d67ca89SAndroid Build Coastguard Worker 			    char *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
678*8d67ca89SAndroid Build Coastguard Worker 			    int j;
679*8d67ca89SAndroid Build Coastguard Worker 			    for (j = 0; j < charcnt; j++)
680*8d67ca89SAndroid Build Coastguard Worker 			      if (strcmp(sp->chars + j, tsabbr) == 0) {
681*8d67ca89SAndroid Build Coastguard Worker 				ts->ttis[i].tt_desigidx = j;
682*8d67ca89SAndroid Build Coastguard Worker 				gotabbr++;
683*8d67ca89SAndroid Build Coastguard Worker 				break;
684*8d67ca89SAndroid Build Coastguard Worker 			      }
685*8d67ca89SAndroid Build Coastguard Worker 			    if (! (j < charcnt)) {
686*8d67ca89SAndroid Build Coastguard Worker 			      int tsabbrlen = strlen(tsabbr);
687*8d67ca89SAndroid Build Coastguard Worker 			      if (j + tsabbrlen < TZ_MAX_CHARS) {
688*8d67ca89SAndroid Build Coastguard Worker 				strcpy(sp->chars + j, tsabbr);
689*8d67ca89SAndroid Build Coastguard Worker 				charcnt = j + tsabbrlen + 1;
690*8d67ca89SAndroid Build Coastguard Worker 				ts->ttis[i].tt_desigidx = j;
691*8d67ca89SAndroid Build Coastguard Worker 				gotabbr++;
692*8d67ca89SAndroid Build Coastguard Worker 			      }
693*8d67ca89SAndroid Build Coastguard Worker 			    }
694*8d67ca89SAndroid Build Coastguard Worker 			  }
695*8d67ca89SAndroid Build Coastguard Worker 			  if (gotabbr == ts->typecnt) {
696*8d67ca89SAndroid Build Coastguard Worker 			    sp->charcnt = charcnt;
697*8d67ca89SAndroid Build Coastguard Worker 
698*8d67ca89SAndroid Build Coastguard Worker 			    /* Ignore any trailing, no-op transitions generated
699*8d67ca89SAndroid Build Coastguard Worker 			       by zic as they don't help here and can run afoul
700*8d67ca89SAndroid Build Coastguard Worker 			       of bugs in zic 2016j or earlier.  */
701*8d67ca89SAndroid Build Coastguard Worker 			    while (1 < sp->timecnt
702*8d67ca89SAndroid Build Coastguard Worker 				   && (sp->types[sp->timecnt - 1]
703*8d67ca89SAndroid Build Coastguard Worker 				       == sp->types[sp->timecnt - 2]))
704*8d67ca89SAndroid Build Coastguard Worker 			      sp->timecnt--;
705*8d67ca89SAndroid Build Coastguard Worker 
706*8d67ca89SAndroid Build Coastguard Worker 			    for (i = 0;
707*8d67ca89SAndroid Build Coastguard Worker 				 i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES;
708*8d67ca89SAndroid Build Coastguard Worker 				 i++) {
709*8d67ca89SAndroid Build Coastguard Worker 			      time_t t = ts->ats[i];
710*8d67ca89SAndroid Build Coastguard Worker 			      if (increment_overflow_time(&t, leapcorr(sp, t))
711*8d67ca89SAndroid Build Coastguard Worker 				  || (0 < sp->timecnt
712*8d67ca89SAndroid Build Coastguard Worker 				      && t <= sp->ats[sp->timecnt - 1]))
713*8d67ca89SAndroid Build Coastguard Worker 				continue;
714*8d67ca89SAndroid Build Coastguard Worker 			      sp->ats[sp->timecnt] = t;
715*8d67ca89SAndroid Build Coastguard Worker 			      sp->types[sp->timecnt] = (sp->typecnt
716*8d67ca89SAndroid Build Coastguard Worker 							+ ts->types[i]);
717*8d67ca89SAndroid Build Coastguard Worker 			      sp->timecnt++;
718*8d67ca89SAndroid Build Coastguard Worker 			    }
719*8d67ca89SAndroid Build Coastguard Worker 			    for (i = 0; i < ts->typecnt; i++)
720*8d67ca89SAndroid Build Coastguard Worker 			      sp->ttis[sp->typecnt++] = ts->ttis[i];
721*8d67ca89SAndroid Build Coastguard Worker 			  }
722*8d67ca89SAndroid Build Coastguard Worker 			}
723*8d67ca89SAndroid Build Coastguard Worker 	}
724*8d67ca89SAndroid Build Coastguard Worker 	if (sp->typecnt == 0)
725*8d67ca89SAndroid Build Coastguard Worker 	  return EINVAL;
726*8d67ca89SAndroid Build Coastguard Worker 	if (sp->timecnt > 1) {
727*8d67ca89SAndroid Build Coastguard Worker 	    if (sp->ats[0] <= TIME_T_MAX - SECSPERREPEAT) {
728*8d67ca89SAndroid Build Coastguard Worker 		time_t repeatat = sp->ats[0] + SECSPERREPEAT;
729*8d67ca89SAndroid Build Coastguard Worker 		int repeattype = sp->types[0];
730*8d67ca89SAndroid Build Coastguard Worker 		for (i = 1; i < sp->timecnt; ++i)
731*8d67ca89SAndroid Build Coastguard Worker 		  if (sp->ats[i] == repeatat
732*8d67ca89SAndroid Build Coastguard Worker 		      && typesequiv(sp, sp->types[i], repeattype)) {
733*8d67ca89SAndroid Build Coastguard Worker 					sp->goback = true;
734*8d67ca89SAndroid Build Coastguard Worker 					break;
735*8d67ca89SAndroid Build Coastguard Worker 		  }
736*8d67ca89SAndroid Build Coastguard Worker 	    }
737*8d67ca89SAndroid Build Coastguard Worker 	    if (TIME_T_MIN + SECSPERREPEAT <= sp->ats[sp->timecnt - 1]) {
738*8d67ca89SAndroid Build Coastguard Worker 		time_t repeatat = sp->ats[sp->timecnt - 1] - SECSPERREPEAT;
739*8d67ca89SAndroid Build Coastguard Worker 		int repeattype = sp->types[sp->timecnt - 1];
740*8d67ca89SAndroid Build Coastguard Worker 		for (i = sp->timecnt - 2; i >= 0; --i)
741*8d67ca89SAndroid Build Coastguard Worker 		  if (sp->ats[i] == repeatat
742*8d67ca89SAndroid Build Coastguard Worker 		      && typesequiv(sp, sp->types[i], repeattype)) {
743*8d67ca89SAndroid Build Coastguard Worker 					sp->goahead = true;
744*8d67ca89SAndroid Build Coastguard Worker 					break;
745*8d67ca89SAndroid Build Coastguard Worker 		  }
746*8d67ca89SAndroid Build Coastguard Worker 	    }
747*8d67ca89SAndroid Build Coastguard Worker 	}
748*8d67ca89SAndroid Build Coastguard Worker 
749*8d67ca89SAndroid Build Coastguard Worker 	/* Infer sp->defaulttype from the data.  Although this default
750*8d67ca89SAndroid Build Coastguard Worker 	   type is always zero for data from recent tzdb releases,
751*8d67ca89SAndroid Build Coastguard Worker 	   things are trickier for data from tzdb 2018e or earlier.
752*8d67ca89SAndroid Build Coastguard Worker 
753*8d67ca89SAndroid Build Coastguard Worker 	   The first set of heuristics work around bugs in 32-bit data
754*8d67ca89SAndroid Build Coastguard Worker 	   generated by tzdb 2013c or earlier.  The workaround is for
755*8d67ca89SAndroid Build Coastguard Worker 	   zones like Australia/Macquarie where timestamps before the
756*8d67ca89SAndroid Build Coastguard Worker 	   first transition have a time type that is not the earliest
757*8d67ca89SAndroid Build Coastguard Worker 	   standard-time type.  See:
758*8d67ca89SAndroid Build Coastguard Worker 	   https://mm.icann.org/pipermail/tz/2013-May/019368.html */
759*8d67ca89SAndroid Build Coastguard Worker 	/*
760*8d67ca89SAndroid Build Coastguard Worker 	** If type 0 does not specify local time, or is unused in transitions,
761*8d67ca89SAndroid Build Coastguard Worker 	** it's the type to use for early times.
762*8d67ca89SAndroid Build Coastguard Worker 	*/
763*8d67ca89SAndroid Build Coastguard Worker 	for (i = 0; i < sp->timecnt; ++i)
764*8d67ca89SAndroid Build Coastguard Worker 		if (sp->types[i] == 0)
765*8d67ca89SAndroid Build Coastguard Worker 			break;
766*8d67ca89SAndroid Build Coastguard Worker 	i = i < sp->timecnt && ! ttunspecified(sp, 0) ? -1 : 0;
767*8d67ca89SAndroid Build Coastguard Worker 	/*
768*8d67ca89SAndroid Build Coastguard Worker 	** Absent the above,
769*8d67ca89SAndroid Build Coastguard Worker 	** if there are transition times
770*8d67ca89SAndroid Build Coastguard Worker 	** and the first transition is to a daylight time
771*8d67ca89SAndroid Build Coastguard Worker 	** find the standard type less than and closest to
772*8d67ca89SAndroid Build Coastguard Worker 	** the type of the first transition.
773*8d67ca89SAndroid Build Coastguard Worker 	*/
774*8d67ca89SAndroid Build Coastguard Worker 	if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) {
775*8d67ca89SAndroid Build Coastguard Worker 		i = sp->types[0];
776*8d67ca89SAndroid Build Coastguard Worker 		while (--i >= 0)
777*8d67ca89SAndroid Build Coastguard Worker 			if (!sp->ttis[i].tt_isdst)
778*8d67ca89SAndroid Build Coastguard Worker 				break;
779*8d67ca89SAndroid Build Coastguard Worker 	}
780*8d67ca89SAndroid Build Coastguard Worker 	/* The next heuristics are for data generated by tzdb 2018e or
781*8d67ca89SAndroid Build Coastguard Worker 	   earlier, for zones like EST5EDT where the first transition
782*8d67ca89SAndroid Build Coastguard Worker 	   is to DST.  */
783*8d67ca89SAndroid Build Coastguard Worker 	/*
784*8d67ca89SAndroid Build Coastguard Worker 	** If no result yet, find the first standard type.
785*8d67ca89SAndroid Build Coastguard Worker 	** If there is none, punt to type zero.
786*8d67ca89SAndroid Build Coastguard Worker 	*/
787*8d67ca89SAndroid Build Coastguard Worker 	if (i < 0) {
788*8d67ca89SAndroid Build Coastguard Worker 		i = 0;
789*8d67ca89SAndroid Build Coastguard Worker 		while (sp->ttis[i].tt_isdst)
790*8d67ca89SAndroid Build Coastguard Worker 			if (++i >= sp->typecnt) {
791*8d67ca89SAndroid Build Coastguard Worker 				i = 0;
792*8d67ca89SAndroid Build Coastguard Worker 				break;
793*8d67ca89SAndroid Build Coastguard Worker 			}
794*8d67ca89SAndroid Build Coastguard Worker 	}
795*8d67ca89SAndroid Build Coastguard Worker 	/* A simple 'sp->defaulttype = 0;' would suffice here if we
796*8d67ca89SAndroid Build Coastguard Worker 	   didn't have to worry about 2018e-or-earlier data.  Even
797*8d67ca89SAndroid Build Coastguard Worker 	   simpler would be to remove the defaulttype member and just
798*8d67ca89SAndroid Build Coastguard Worker 	   use 0 in its place.  */
799*8d67ca89SAndroid Build Coastguard Worker 	sp->defaulttype = i;
800*8d67ca89SAndroid Build Coastguard Worker 
801*8d67ca89SAndroid Build Coastguard Worker 	return 0;
802*8d67ca89SAndroid Build Coastguard Worker }
803*8d67ca89SAndroid Build Coastguard Worker 
804*8d67ca89SAndroid Build Coastguard Worker /* Load tz data from the file named NAME into *SP.  Read extended
805*8d67ca89SAndroid Build Coastguard Worker    format if DOEXTEND.  Return 0 on success, an errno value on failure.  */
806*8d67ca89SAndroid Build Coastguard Worker static int
tzload(char const * name,struct state * sp,bool doextend)807*8d67ca89SAndroid Build Coastguard Worker tzload(char const *name, struct state *sp, bool doextend)
808*8d67ca89SAndroid Build Coastguard Worker {
809*8d67ca89SAndroid Build Coastguard Worker #ifdef ALL_STATE
810*8d67ca89SAndroid Build Coastguard Worker   union local_storage *lsp = malloc(sizeof *lsp);
811*8d67ca89SAndroid Build Coastguard Worker   if (!lsp) {
812*8d67ca89SAndroid Build Coastguard Worker     return HAVE_MALLOC_ERRNO ? errno : ENOMEM;
813*8d67ca89SAndroid Build Coastguard Worker   } else {
814*8d67ca89SAndroid Build Coastguard Worker     int err = tzloadbody(name, sp, doextend, lsp);
815*8d67ca89SAndroid Build Coastguard Worker     free(lsp);
816*8d67ca89SAndroid Build Coastguard Worker     return err;
817*8d67ca89SAndroid Build Coastguard Worker   }
818*8d67ca89SAndroid Build Coastguard Worker #else
819*8d67ca89SAndroid Build Coastguard Worker   union local_storage ls;
820*8d67ca89SAndroid Build Coastguard Worker   return tzloadbody(name, sp, doextend, &ls);
821*8d67ca89SAndroid Build Coastguard Worker #endif
822*8d67ca89SAndroid Build Coastguard Worker }
823*8d67ca89SAndroid Build Coastguard Worker 
824*8d67ca89SAndroid Build Coastguard Worker static bool
typesequiv(const struct state * sp,int a,int b)825*8d67ca89SAndroid Build Coastguard Worker typesequiv(const struct state *sp, int a, int b)
826*8d67ca89SAndroid Build Coastguard Worker {
827*8d67ca89SAndroid Build Coastguard Worker 	register bool result;
828*8d67ca89SAndroid Build Coastguard Worker 
829*8d67ca89SAndroid Build Coastguard Worker 	if (sp == NULL ||
830*8d67ca89SAndroid Build Coastguard Worker 		a < 0 || a >= sp->typecnt ||
831*8d67ca89SAndroid Build Coastguard Worker 		b < 0 || b >= sp->typecnt)
832*8d67ca89SAndroid Build Coastguard Worker 			result = false;
833*8d67ca89SAndroid Build Coastguard Worker 	else {
834*8d67ca89SAndroid Build Coastguard Worker 		/* Compare the relevant members of *AP and *BP.
835*8d67ca89SAndroid Build Coastguard Worker 		   Ignore tt_ttisstd and tt_ttisut, as they are
836*8d67ca89SAndroid Build Coastguard Worker 		   irrelevant now and counting them could cause
837*8d67ca89SAndroid Build Coastguard Worker 		   sp->goahead to mistakenly remain false.  */
838*8d67ca89SAndroid Build Coastguard Worker 		register const struct ttinfo *	ap = &sp->ttis[a];
839*8d67ca89SAndroid Build Coastguard Worker 		register const struct ttinfo *	bp = &sp->ttis[b];
840*8d67ca89SAndroid Build Coastguard Worker 		result = (ap->tt_utoff == bp->tt_utoff
841*8d67ca89SAndroid Build Coastguard Worker 			  && ap->tt_isdst == bp->tt_isdst
842*8d67ca89SAndroid Build Coastguard Worker 			  && (strcmp(&sp->chars[ap->tt_desigidx],
843*8d67ca89SAndroid Build Coastguard Worker 				     &sp->chars[bp->tt_desigidx])
844*8d67ca89SAndroid Build Coastguard Worker 			      == 0));
845*8d67ca89SAndroid Build Coastguard Worker 	}
846*8d67ca89SAndroid Build Coastguard Worker 	return result;
847*8d67ca89SAndroid Build Coastguard Worker }
848*8d67ca89SAndroid Build Coastguard Worker 
849*8d67ca89SAndroid Build Coastguard Worker static const int	mon_lengths[2][MONSPERYEAR] = {
850*8d67ca89SAndroid Build Coastguard Worker 	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
851*8d67ca89SAndroid Build Coastguard Worker 	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
852*8d67ca89SAndroid Build Coastguard Worker };
853*8d67ca89SAndroid Build Coastguard Worker 
854*8d67ca89SAndroid Build Coastguard Worker static const int	year_lengths[2] = {
855*8d67ca89SAndroid Build Coastguard Worker 	DAYSPERNYEAR, DAYSPERLYEAR
856*8d67ca89SAndroid Build Coastguard Worker };
857*8d67ca89SAndroid Build Coastguard Worker 
858*8d67ca89SAndroid Build Coastguard Worker /* Is C an ASCII digit?  */
859*8d67ca89SAndroid Build Coastguard Worker static bool
is_digit(char c)860*8d67ca89SAndroid Build Coastguard Worker is_digit(char c)
861*8d67ca89SAndroid Build Coastguard Worker {
862*8d67ca89SAndroid Build Coastguard Worker   return '0' <= c && c <= '9';
863*8d67ca89SAndroid Build Coastguard Worker }
864*8d67ca89SAndroid Build Coastguard Worker 
865*8d67ca89SAndroid Build Coastguard Worker /*
866*8d67ca89SAndroid Build Coastguard Worker ** Given a pointer into a timezone string, scan until a character that is not
867*8d67ca89SAndroid Build Coastguard Worker ** a valid character in a time zone abbreviation is found.
868*8d67ca89SAndroid Build Coastguard Worker ** Return a pointer to that character.
869*8d67ca89SAndroid Build Coastguard Worker */
870*8d67ca89SAndroid Build Coastguard Worker 
871*8d67ca89SAndroid Build Coastguard Worker ATTRIBUTE_REPRODUCIBLE static const char *
getzname(register const char * strp)872*8d67ca89SAndroid Build Coastguard Worker getzname(register const char *strp)
873*8d67ca89SAndroid Build Coastguard Worker {
874*8d67ca89SAndroid Build Coastguard Worker 	register char	c;
875*8d67ca89SAndroid Build Coastguard Worker 
876*8d67ca89SAndroid Build Coastguard Worker 	while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
877*8d67ca89SAndroid Build Coastguard Worker 		c != '+')
878*8d67ca89SAndroid Build Coastguard Worker 			++strp;
879*8d67ca89SAndroid Build Coastguard Worker 	return strp;
880*8d67ca89SAndroid Build Coastguard Worker }
881*8d67ca89SAndroid Build Coastguard Worker 
882*8d67ca89SAndroid Build Coastguard Worker /*
883*8d67ca89SAndroid Build Coastguard Worker ** Given a pointer into an extended timezone string, scan until the ending
884*8d67ca89SAndroid Build Coastguard Worker ** delimiter of the time zone abbreviation is located.
885*8d67ca89SAndroid Build Coastguard Worker ** Return a pointer to the delimiter.
886*8d67ca89SAndroid Build Coastguard Worker **
887*8d67ca89SAndroid Build Coastguard Worker ** As with getzname above, the legal character set is actually quite
888*8d67ca89SAndroid Build Coastguard Worker ** restricted, with other characters producing undefined results.
889*8d67ca89SAndroid Build Coastguard Worker ** We don't do any checking here; checking is done later in common-case code.
890*8d67ca89SAndroid Build Coastguard Worker */
891*8d67ca89SAndroid Build Coastguard Worker 
892*8d67ca89SAndroid Build Coastguard Worker ATTRIBUTE_REPRODUCIBLE static const char *
getqzname(register const char * strp,const int delim)893*8d67ca89SAndroid Build Coastguard Worker getqzname(register const char *strp, const int delim)
894*8d67ca89SAndroid Build Coastguard Worker {
895*8d67ca89SAndroid Build Coastguard Worker 	register int	c;
896*8d67ca89SAndroid Build Coastguard Worker 
897*8d67ca89SAndroid Build Coastguard Worker 	while ((c = *strp) != '\0' && c != delim)
898*8d67ca89SAndroid Build Coastguard Worker 		++strp;
899*8d67ca89SAndroid Build Coastguard Worker 	return strp;
900*8d67ca89SAndroid Build Coastguard Worker }
901*8d67ca89SAndroid Build Coastguard Worker 
902*8d67ca89SAndroid Build Coastguard Worker /*
903*8d67ca89SAndroid Build Coastguard Worker ** Given a pointer into a timezone string, extract a number from that string.
904*8d67ca89SAndroid Build Coastguard Worker ** Check that the number is within a specified range; if it is not, return
905*8d67ca89SAndroid Build Coastguard Worker ** NULL.
906*8d67ca89SAndroid Build Coastguard Worker ** Otherwise, return a pointer to the first character not part of the number.
907*8d67ca89SAndroid Build Coastguard Worker */
908*8d67ca89SAndroid Build Coastguard Worker 
909*8d67ca89SAndroid Build Coastguard Worker static const char *
getnum(register const char * strp,int * const nump,const int min,const int max)910*8d67ca89SAndroid Build Coastguard Worker getnum(register const char *strp, int *const nump, const int min, const int max)
911*8d67ca89SAndroid Build Coastguard Worker {
912*8d67ca89SAndroid Build Coastguard Worker 	register char	c;
913*8d67ca89SAndroid Build Coastguard Worker 	register int	num;
914*8d67ca89SAndroid Build Coastguard Worker 
915*8d67ca89SAndroid Build Coastguard Worker 	if (strp == NULL || !is_digit(c = *strp))
916*8d67ca89SAndroid Build Coastguard Worker 		return NULL;
917*8d67ca89SAndroid Build Coastguard Worker 	num = 0;
918*8d67ca89SAndroid Build Coastguard Worker 	do {
919*8d67ca89SAndroid Build Coastguard Worker 		num = num * 10 + (c - '0');
920*8d67ca89SAndroid Build Coastguard Worker 		if (num > max)
921*8d67ca89SAndroid Build Coastguard Worker 			return NULL;	/* illegal value */
922*8d67ca89SAndroid Build Coastguard Worker 		c = *++strp;
923*8d67ca89SAndroid Build Coastguard Worker 	} while (is_digit(c));
924*8d67ca89SAndroid Build Coastguard Worker 	if (num < min)
925*8d67ca89SAndroid Build Coastguard Worker 		return NULL;		/* illegal value */
926*8d67ca89SAndroid Build Coastguard Worker 	*nump = num;
927*8d67ca89SAndroid Build Coastguard Worker 	return strp;
928*8d67ca89SAndroid Build Coastguard Worker }
929*8d67ca89SAndroid Build Coastguard Worker 
930*8d67ca89SAndroid Build Coastguard Worker /*
931*8d67ca89SAndroid Build Coastguard Worker ** Given a pointer into a timezone string, extract a number of seconds,
932*8d67ca89SAndroid Build Coastguard Worker ** in hh[:mm[:ss]] form, from the string.
933*8d67ca89SAndroid Build Coastguard Worker ** If any error occurs, return NULL.
934*8d67ca89SAndroid Build Coastguard Worker ** Otherwise, return a pointer to the first character not part of the number
935*8d67ca89SAndroid Build Coastguard Worker ** of seconds.
936*8d67ca89SAndroid Build Coastguard Worker */
937*8d67ca89SAndroid Build Coastguard Worker 
938*8d67ca89SAndroid Build Coastguard Worker static const char *
getsecs(register const char * strp,int_fast32_t * const secsp)939*8d67ca89SAndroid Build Coastguard Worker getsecs(register const char *strp, int_fast32_t *const secsp)
940*8d67ca89SAndroid Build Coastguard Worker {
941*8d67ca89SAndroid Build Coastguard Worker 	int	num;
942*8d67ca89SAndroid Build Coastguard Worker 	int_fast32_t secsperhour = SECSPERHOUR;
943*8d67ca89SAndroid Build Coastguard Worker 
944*8d67ca89SAndroid Build Coastguard Worker 	/*
945*8d67ca89SAndroid Build Coastguard Worker 	** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
946*8d67ca89SAndroid Build Coastguard Worker 	** "M10.4.6/26", which does not conform to Posix,
947*8d67ca89SAndroid Build Coastguard Worker 	** but which specifies the equivalent of
948*8d67ca89SAndroid Build Coastguard Worker 	** "02:00 on the first Sunday on or after 23 Oct".
949*8d67ca89SAndroid Build Coastguard Worker 	*/
950*8d67ca89SAndroid Build Coastguard Worker 	strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
951*8d67ca89SAndroid Build Coastguard Worker 	if (strp == NULL)
952*8d67ca89SAndroid Build Coastguard Worker 		return NULL;
953*8d67ca89SAndroid Build Coastguard Worker 	*secsp = num * secsperhour;
954*8d67ca89SAndroid Build Coastguard Worker 	if (*strp == ':') {
955*8d67ca89SAndroid Build Coastguard Worker 		++strp;
956*8d67ca89SAndroid Build Coastguard Worker 		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
957*8d67ca89SAndroid Build Coastguard Worker 		if (strp == NULL)
958*8d67ca89SAndroid Build Coastguard Worker 			return NULL;
959*8d67ca89SAndroid Build Coastguard Worker 		*secsp += num * SECSPERMIN;
960*8d67ca89SAndroid Build Coastguard Worker 		if (*strp == ':') {
961*8d67ca89SAndroid Build Coastguard Worker 			++strp;
962*8d67ca89SAndroid Build Coastguard Worker 			/* 'SECSPERMIN' allows for leap seconds.  */
963*8d67ca89SAndroid Build Coastguard Worker 			strp = getnum(strp, &num, 0, SECSPERMIN);
964*8d67ca89SAndroid Build Coastguard Worker 			if (strp == NULL)
965*8d67ca89SAndroid Build Coastguard Worker 				return NULL;
966*8d67ca89SAndroid Build Coastguard Worker 			*secsp += num;
967*8d67ca89SAndroid Build Coastguard Worker 		}
968*8d67ca89SAndroid Build Coastguard Worker 	}
969*8d67ca89SAndroid Build Coastguard Worker 	return strp;
970*8d67ca89SAndroid Build Coastguard Worker }
971*8d67ca89SAndroid Build Coastguard Worker 
972*8d67ca89SAndroid Build Coastguard Worker /*
973*8d67ca89SAndroid Build Coastguard Worker ** Given a pointer into a timezone string, extract an offset, in
974*8d67ca89SAndroid Build Coastguard Worker ** [+-]hh[:mm[:ss]] form, from the string.
975*8d67ca89SAndroid Build Coastguard Worker ** If any error occurs, return NULL.
976*8d67ca89SAndroid Build Coastguard Worker ** Otherwise, return a pointer to the first character not part of the time.
977*8d67ca89SAndroid Build Coastguard Worker */
978*8d67ca89SAndroid Build Coastguard Worker 
979*8d67ca89SAndroid Build Coastguard Worker static const char *
getoffset(register const char * strp,int_fast32_t * const offsetp)980*8d67ca89SAndroid Build Coastguard Worker getoffset(register const char *strp, int_fast32_t *const offsetp)
981*8d67ca89SAndroid Build Coastguard Worker {
982*8d67ca89SAndroid Build Coastguard Worker 	register bool neg = false;
983*8d67ca89SAndroid Build Coastguard Worker 
984*8d67ca89SAndroid Build Coastguard Worker 	if (*strp == '-') {
985*8d67ca89SAndroid Build Coastguard Worker 		neg = true;
986*8d67ca89SAndroid Build Coastguard Worker 		++strp;
987*8d67ca89SAndroid Build Coastguard Worker 	} else if (*strp == '+')
988*8d67ca89SAndroid Build Coastguard Worker 		++strp;
989*8d67ca89SAndroid Build Coastguard Worker 	strp = getsecs(strp, offsetp);
990*8d67ca89SAndroid Build Coastguard Worker 	if (strp == NULL)
991*8d67ca89SAndroid Build Coastguard Worker 		return NULL;		/* illegal time */
992*8d67ca89SAndroid Build Coastguard Worker 	if (neg)
993*8d67ca89SAndroid Build Coastguard Worker 		*offsetp = -*offsetp;
994*8d67ca89SAndroid Build Coastguard Worker 	return strp;
995*8d67ca89SAndroid Build Coastguard Worker }
996*8d67ca89SAndroid Build Coastguard Worker 
997*8d67ca89SAndroid Build Coastguard Worker /*
998*8d67ca89SAndroid Build Coastguard Worker ** Given a pointer into a timezone string, extract a rule in the form
999*8d67ca89SAndroid Build Coastguard Worker ** date[/time]. See POSIX section 8 for the format of "date" and "time".
1000*8d67ca89SAndroid Build Coastguard Worker ** If a valid rule is not found, return NULL.
1001*8d67ca89SAndroid Build Coastguard Worker ** Otherwise, return a pointer to the first character not part of the rule.
1002*8d67ca89SAndroid Build Coastguard Worker */
1003*8d67ca89SAndroid Build Coastguard Worker 
1004*8d67ca89SAndroid Build Coastguard Worker static const char *
getrule(const char * strp,register struct rule * const rulep)1005*8d67ca89SAndroid Build Coastguard Worker getrule(const char *strp, register struct rule *const rulep)
1006*8d67ca89SAndroid Build Coastguard Worker {
1007*8d67ca89SAndroid Build Coastguard Worker 	if (*strp == 'J') {
1008*8d67ca89SAndroid Build Coastguard Worker 		/*
1009*8d67ca89SAndroid Build Coastguard Worker 		** Julian day.
1010*8d67ca89SAndroid Build Coastguard Worker 		*/
1011*8d67ca89SAndroid Build Coastguard Worker 		rulep->r_type = JULIAN_DAY;
1012*8d67ca89SAndroid Build Coastguard Worker 		++strp;
1013*8d67ca89SAndroid Build Coastguard Worker 		strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
1014*8d67ca89SAndroid Build Coastguard Worker 	} else if (*strp == 'M') {
1015*8d67ca89SAndroid Build Coastguard Worker 		/*
1016*8d67ca89SAndroid Build Coastguard Worker 		** Month, week, day.
1017*8d67ca89SAndroid Build Coastguard Worker 		*/
1018*8d67ca89SAndroid Build Coastguard Worker 		rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
1019*8d67ca89SAndroid Build Coastguard Worker 		++strp;
1020*8d67ca89SAndroid Build Coastguard Worker 		strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
1021*8d67ca89SAndroid Build Coastguard Worker 		if (strp == NULL)
1022*8d67ca89SAndroid Build Coastguard Worker 			return NULL;
1023*8d67ca89SAndroid Build Coastguard Worker 		if (*strp++ != '.')
1024*8d67ca89SAndroid Build Coastguard Worker 			return NULL;
1025*8d67ca89SAndroid Build Coastguard Worker 		strp = getnum(strp, &rulep->r_week, 1, 5);
1026*8d67ca89SAndroid Build Coastguard Worker 		if (strp == NULL)
1027*8d67ca89SAndroid Build Coastguard Worker 			return NULL;
1028*8d67ca89SAndroid Build Coastguard Worker 		if (*strp++ != '.')
1029*8d67ca89SAndroid Build Coastguard Worker 			return NULL;
1030*8d67ca89SAndroid Build Coastguard Worker 		strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
1031*8d67ca89SAndroid Build Coastguard Worker 	} else if (is_digit(*strp)) {
1032*8d67ca89SAndroid Build Coastguard Worker 		/*
1033*8d67ca89SAndroid Build Coastguard Worker 		** Day of year.
1034*8d67ca89SAndroid Build Coastguard Worker 		*/
1035*8d67ca89SAndroid Build Coastguard Worker 		rulep->r_type = DAY_OF_YEAR;
1036*8d67ca89SAndroid Build Coastguard Worker 		strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
1037*8d67ca89SAndroid Build Coastguard Worker 	} else	return NULL;		/* invalid format */
1038*8d67ca89SAndroid Build Coastguard Worker 	if (strp == NULL)
1039*8d67ca89SAndroid Build Coastguard Worker 		return NULL;
1040*8d67ca89SAndroid Build Coastguard Worker 	if (*strp == '/') {
1041*8d67ca89SAndroid Build Coastguard Worker 		/*
1042*8d67ca89SAndroid Build Coastguard Worker 		** Time specified.
1043*8d67ca89SAndroid Build Coastguard Worker 		*/
1044*8d67ca89SAndroid Build Coastguard Worker 		++strp;
1045*8d67ca89SAndroid Build Coastguard Worker 		strp = getoffset(strp, &rulep->r_time);
1046*8d67ca89SAndroid Build Coastguard Worker 	} else	rulep->r_time = 2 * SECSPERHOUR;	/* default = 2:00:00 */
1047*8d67ca89SAndroid Build Coastguard Worker 	return strp;
1048*8d67ca89SAndroid Build Coastguard Worker }
1049*8d67ca89SAndroid Build Coastguard Worker 
1050*8d67ca89SAndroid Build Coastguard Worker /*
1051*8d67ca89SAndroid Build Coastguard Worker ** Given a year, a rule, and the offset from UT at the time that rule takes
1052*8d67ca89SAndroid Build Coastguard Worker ** effect, calculate the year-relative time that rule takes effect.
1053*8d67ca89SAndroid Build Coastguard Worker */
1054*8d67ca89SAndroid Build Coastguard Worker 
1055*8d67ca89SAndroid Build Coastguard Worker static int_fast32_t
transtime(const int year,register const struct rule * const rulep,const int_fast32_t offset)1056*8d67ca89SAndroid Build Coastguard Worker transtime(const int year, register const struct rule *const rulep,
1057*8d67ca89SAndroid Build Coastguard Worker           const int_fast32_t offset)
1058*8d67ca89SAndroid Build Coastguard Worker {
1059*8d67ca89SAndroid Build Coastguard Worker     register bool         leapyear;
1060*8d67ca89SAndroid Build Coastguard Worker     register int_fast32_t value;
1061*8d67ca89SAndroid Build Coastguard Worker     register int          i;
1062*8d67ca89SAndroid Build Coastguard Worker     int d, m1, yy0, yy1, yy2, dow;
1063*8d67ca89SAndroid Build Coastguard Worker 
1064*8d67ca89SAndroid Build Coastguard Worker     leapyear = isleap(year);
1065*8d67ca89SAndroid Build Coastguard Worker     switch (rulep->r_type) {
1066*8d67ca89SAndroid Build Coastguard Worker 
1067*8d67ca89SAndroid Build Coastguard Worker     case JULIAN_DAY:
1068*8d67ca89SAndroid Build Coastguard Worker         /*
1069*8d67ca89SAndroid Build Coastguard Worker         ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
1070*8d67ca89SAndroid Build Coastguard Worker         ** years.
1071*8d67ca89SAndroid Build Coastguard Worker         ** In non-leap years, or if the day number is 59 or less, just
1072*8d67ca89SAndroid Build Coastguard Worker         ** add SECSPERDAY times the day number-1 to the time of
1073*8d67ca89SAndroid Build Coastguard Worker         ** January 1, midnight, to get the day.
1074*8d67ca89SAndroid Build Coastguard Worker         */
1075*8d67ca89SAndroid Build Coastguard Worker         value = (rulep->r_day - 1) * SECSPERDAY;
1076*8d67ca89SAndroid Build Coastguard Worker         if (leapyear && rulep->r_day >= 60)
1077*8d67ca89SAndroid Build Coastguard Worker             value += SECSPERDAY;
1078*8d67ca89SAndroid Build Coastguard Worker         break;
1079*8d67ca89SAndroid Build Coastguard Worker 
1080*8d67ca89SAndroid Build Coastguard Worker     case DAY_OF_YEAR:
1081*8d67ca89SAndroid Build Coastguard Worker         /*
1082*8d67ca89SAndroid Build Coastguard Worker         ** n - day of year.
1083*8d67ca89SAndroid Build Coastguard Worker         ** Just add SECSPERDAY times the day number to the time of
1084*8d67ca89SAndroid Build Coastguard Worker         ** January 1, midnight, to get the day.
1085*8d67ca89SAndroid Build Coastguard Worker         */
1086*8d67ca89SAndroid Build Coastguard Worker         value = rulep->r_day * SECSPERDAY;
1087*8d67ca89SAndroid Build Coastguard Worker         break;
1088*8d67ca89SAndroid Build Coastguard Worker 
1089*8d67ca89SAndroid Build Coastguard Worker     case MONTH_NTH_DAY_OF_WEEK:
1090*8d67ca89SAndroid Build Coastguard Worker         /*
1091*8d67ca89SAndroid Build Coastguard Worker         ** Mm.n.d - nth "dth day" of month m.
1092*8d67ca89SAndroid Build Coastguard Worker         */
1093*8d67ca89SAndroid Build Coastguard Worker 
1094*8d67ca89SAndroid Build Coastguard Worker         /*
1095*8d67ca89SAndroid Build Coastguard Worker         ** Use Zeller's Congruence to get day-of-week of first day of
1096*8d67ca89SAndroid Build Coastguard Worker         ** month.
1097*8d67ca89SAndroid Build Coastguard Worker         */
1098*8d67ca89SAndroid Build Coastguard Worker         m1 = (rulep->r_mon + 9) % 12 + 1;
1099*8d67ca89SAndroid Build Coastguard Worker         yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
1100*8d67ca89SAndroid Build Coastguard Worker         yy1 = yy0 / 100;
1101*8d67ca89SAndroid Build Coastguard Worker         yy2 = yy0 % 100;
1102*8d67ca89SAndroid Build Coastguard Worker         dow = ((26 * m1 - 2) / 10 +
1103*8d67ca89SAndroid Build Coastguard Worker             1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1104*8d67ca89SAndroid Build Coastguard Worker         if (dow < 0)
1105*8d67ca89SAndroid Build Coastguard Worker             dow += DAYSPERWEEK;
1106*8d67ca89SAndroid Build Coastguard Worker 
1107*8d67ca89SAndroid Build Coastguard Worker         /*
1108*8d67ca89SAndroid Build Coastguard Worker         ** "dow" is the day-of-week of the first day of the month. Get
1109*8d67ca89SAndroid Build Coastguard Worker         ** the day-of-month (zero-origin) of the first "dow" day of the
1110*8d67ca89SAndroid Build Coastguard Worker         ** month.
1111*8d67ca89SAndroid Build Coastguard Worker         */
1112*8d67ca89SAndroid Build Coastguard Worker         d = rulep->r_day - dow;
1113*8d67ca89SAndroid Build Coastguard Worker         if (d < 0)
1114*8d67ca89SAndroid Build Coastguard Worker             d += DAYSPERWEEK;
1115*8d67ca89SAndroid Build Coastguard Worker         for (i = 1; i < rulep->r_week; ++i) {
1116*8d67ca89SAndroid Build Coastguard Worker             if (d + DAYSPERWEEK >=
1117*8d67ca89SAndroid Build Coastguard Worker                 mon_lengths[leapyear][rulep->r_mon - 1])
1118*8d67ca89SAndroid Build Coastguard Worker                     break;
1119*8d67ca89SAndroid Build Coastguard Worker             d += DAYSPERWEEK;
1120*8d67ca89SAndroid Build Coastguard Worker         }
1121*8d67ca89SAndroid Build Coastguard Worker 
1122*8d67ca89SAndroid Build Coastguard Worker         /*
1123*8d67ca89SAndroid Build Coastguard Worker         ** "d" is the day-of-month (zero-origin) of the day we want.
1124*8d67ca89SAndroid Build Coastguard Worker         */
1125*8d67ca89SAndroid Build Coastguard Worker         value = d * SECSPERDAY;
1126*8d67ca89SAndroid Build Coastguard Worker         for (i = 0; i < rulep->r_mon - 1; ++i)
1127*8d67ca89SAndroid Build Coastguard Worker             value += mon_lengths[leapyear][i] * SECSPERDAY;
1128*8d67ca89SAndroid Build Coastguard Worker         break;
1129*8d67ca89SAndroid Build Coastguard Worker 
1130*8d67ca89SAndroid Build Coastguard Worker         default: unreachable();
1131*8d67ca89SAndroid Build Coastguard Worker     }
1132*8d67ca89SAndroid Build Coastguard Worker 
1133*8d67ca89SAndroid Build Coastguard Worker     /*
1134*8d67ca89SAndroid Build Coastguard Worker     ** "value" is the year-relative time of 00:00:00 UT on the day in
1135*8d67ca89SAndroid Build Coastguard Worker     ** question. To get the year-relative time of the specified local
1136*8d67ca89SAndroid Build Coastguard Worker     ** time on that day, add the transition time and the current offset
1137*8d67ca89SAndroid Build Coastguard Worker     ** from UT.
1138*8d67ca89SAndroid Build Coastguard Worker     */
1139*8d67ca89SAndroid Build Coastguard Worker     return value + rulep->r_time + offset;
1140*8d67ca89SAndroid Build Coastguard Worker }
1141*8d67ca89SAndroid Build Coastguard Worker 
1142*8d67ca89SAndroid Build Coastguard Worker /*
1143*8d67ca89SAndroid Build Coastguard Worker ** Given a POSIX section 8-style TZ string, fill in the rule tables as
1144*8d67ca89SAndroid Build Coastguard Worker ** appropriate.
1145*8d67ca89SAndroid Build Coastguard Worker */
1146*8d67ca89SAndroid Build Coastguard Worker 
1147*8d67ca89SAndroid Build Coastguard Worker static bool
tzparse(const char * name,struct state * sp,struct state * basep)1148*8d67ca89SAndroid Build Coastguard Worker tzparse(const char *name, struct state *sp, struct state *basep)
1149*8d67ca89SAndroid Build Coastguard Worker {
1150*8d67ca89SAndroid Build Coastguard Worker 	const char *			stdname;
1151*8d67ca89SAndroid Build Coastguard Worker 	const char *			dstname;
1152*8d67ca89SAndroid Build Coastguard Worker 	int_fast32_t			stdoffset;
1153*8d67ca89SAndroid Build Coastguard Worker 	int_fast32_t			dstoffset;
1154*8d67ca89SAndroid Build Coastguard Worker 	register char *			cp;
1155*8d67ca89SAndroid Build Coastguard Worker 	register bool			load_ok;
1156*8d67ca89SAndroid Build Coastguard Worker 	ptrdiff_t stdlen, dstlen, charcnt;
1157*8d67ca89SAndroid Build Coastguard Worker 	time_t atlo = TIME_T_MIN, leaplo = TIME_T_MIN;
1158*8d67ca89SAndroid Build Coastguard Worker 
1159*8d67ca89SAndroid Build Coastguard Worker 	stdname = name;
1160*8d67ca89SAndroid Build Coastguard Worker 	if (*name == '<') {
1161*8d67ca89SAndroid Build Coastguard Worker 	  name++;
1162*8d67ca89SAndroid Build Coastguard Worker 	  stdname = name;
1163*8d67ca89SAndroid Build Coastguard Worker 	  name = getqzname(name, '>');
1164*8d67ca89SAndroid Build Coastguard Worker 	  if (*name != '>')
1165*8d67ca89SAndroid Build Coastguard Worker 	    return false;
1166*8d67ca89SAndroid Build Coastguard Worker 	  stdlen = name - stdname;
1167*8d67ca89SAndroid Build Coastguard Worker 	  name++;
1168*8d67ca89SAndroid Build Coastguard Worker 	} else {
1169*8d67ca89SAndroid Build Coastguard Worker 	  name = getzname(name);
1170*8d67ca89SAndroid Build Coastguard Worker 	  stdlen = name - stdname;
1171*8d67ca89SAndroid Build Coastguard Worker 	}
1172*8d67ca89SAndroid Build Coastguard Worker 	if (! (0 < stdlen && stdlen <= TZNAME_MAXIMUM))
1173*8d67ca89SAndroid Build Coastguard Worker 	  return false;
1174*8d67ca89SAndroid Build Coastguard Worker 	name = getoffset(name, &stdoffset);
1175*8d67ca89SAndroid Build Coastguard Worker 	if (name == NULL)
1176*8d67ca89SAndroid Build Coastguard Worker 	  return false;
1177*8d67ca89SAndroid Build Coastguard Worker 	charcnt = stdlen + 1;
1178*8d67ca89SAndroid Build Coastguard Worker 	if (basep) {
1179*8d67ca89SAndroid Build Coastguard Worker 	  if (0 < basep->timecnt)
1180*8d67ca89SAndroid Build Coastguard Worker 	    atlo = basep->ats[basep->timecnt - 1];
1181*8d67ca89SAndroid Build Coastguard Worker 	  load_ok = false;
1182*8d67ca89SAndroid Build Coastguard Worker 	  sp->leapcnt = basep->leapcnt;
1183*8d67ca89SAndroid Build Coastguard Worker 	  memcpy(sp->lsis, basep->lsis, sp->leapcnt * sizeof *sp->lsis);
1184*8d67ca89SAndroid Build Coastguard Worker 	} else {
1185*8d67ca89SAndroid Build Coastguard Worker 	  load_ok = tzload(TZDEFRULES, sp, false) == 0;
1186*8d67ca89SAndroid Build Coastguard Worker 	  if (!load_ok)
1187*8d67ca89SAndroid Build Coastguard Worker 	    sp->leapcnt = 0;	/* So, we're off a little.  */
1188*8d67ca89SAndroid Build Coastguard Worker 	}
1189*8d67ca89SAndroid Build Coastguard Worker 	if (0 < sp->leapcnt)
1190*8d67ca89SAndroid Build Coastguard Worker 	  leaplo = sp->lsis[sp->leapcnt - 1].ls_trans;
1191*8d67ca89SAndroid Build Coastguard Worker 	if (*name != '\0') {
1192*8d67ca89SAndroid Build Coastguard Worker 		if (*name == '<') {
1193*8d67ca89SAndroid Build Coastguard Worker 			dstname = ++name;
1194*8d67ca89SAndroid Build Coastguard Worker 			name = getqzname(name, '>');
1195*8d67ca89SAndroid Build Coastguard Worker 			if (*name != '>')
1196*8d67ca89SAndroid Build Coastguard Worker 			  return false;
1197*8d67ca89SAndroid Build Coastguard Worker 			dstlen = name - dstname;
1198*8d67ca89SAndroid Build Coastguard Worker 			name++;
1199*8d67ca89SAndroid Build Coastguard Worker 		} else {
1200*8d67ca89SAndroid Build Coastguard Worker 			dstname = name;
1201*8d67ca89SAndroid Build Coastguard Worker 			name = getzname(name);
1202*8d67ca89SAndroid Build Coastguard Worker 			dstlen = name - dstname; /* length of DST abbr. */
1203*8d67ca89SAndroid Build Coastguard Worker 		}
1204*8d67ca89SAndroid Build Coastguard Worker 		if (! (0 < dstlen && dstlen <= TZNAME_MAXIMUM))
1205*8d67ca89SAndroid Build Coastguard Worker 		  return false;
1206*8d67ca89SAndroid Build Coastguard Worker 		charcnt += dstlen + 1;
1207*8d67ca89SAndroid Build Coastguard Worker 		if (*name != '\0' && *name != ',' && *name != ';') {
1208*8d67ca89SAndroid Build Coastguard Worker 			name = getoffset(name, &dstoffset);
1209*8d67ca89SAndroid Build Coastguard Worker 			if (name == NULL)
1210*8d67ca89SAndroid Build Coastguard Worker 			  return false;
1211*8d67ca89SAndroid Build Coastguard Worker 		} else	dstoffset = stdoffset - SECSPERHOUR;
1212*8d67ca89SAndroid Build Coastguard Worker 		if (*name == '\0' && !load_ok)
1213*8d67ca89SAndroid Build Coastguard Worker 			name = TZDEFRULESTRING;
1214*8d67ca89SAndroid Build Coastguard Worker 		if (*name == ',' || *name == ';') {
1215*8d67ca89SAndroid Build Coastguard Worker 			struct rule	start;
1216*8d67ca89SAndroid Build Coastguard Worker 			struct rule	end;
1217*8d67ca89SAndroid Build Coastguard Worker 			register int	year;
1218*8d67ca89SAndroid Build Coastguard Worker 			register int	timecnt;
1219*8d67ca89SAndroid Build Coastguard Worker 			time_t		janfirst;
1220*8d67ca89SAndroid Build Coastguard Worker 			int_fast32_t janoffset = 0;
1221*8d67ca89SAndroid Build Coastguard Worker 			int yearbeg, yearlim;
1222*8d67ca89SAndroid Build Coastguard Worker 
1223*8d67ca89SAndroid Build Coastguard Worker 			++name;
1224*8d67ca89SAndroid Build Coastguard Worker 			if ((name = getrule(name, &start)) == NULL)
1225*8d67ca89SAndroid Build Coastguard Worker 			  return false;
1226*8d67ca89SAndroid Build Coastguard Worker 			if (*name++ != ',')
1227*8d67ca89SAndroid Build Coastguard Worker 			  return false;
1228*8d67ca89SAndroid Build Coastguard Worker 			if ((name = getrule(name, &end)) == NULL)
1229*8d67ca89SAndroid Build Coastguard Worker 			  return false;
1230*8d67ca89SAndroid Build Coastguard Worker 			if (*name != '\0')
1231*8d67ca89SAndroid Build Coastguard Worker 			  return false;
1232*8d67ca89SAndroid Build Coastguard Worker 			sp->typecnt = 2;	/* standard time and DST */
1233*8d67ca89SAndroid Build Coastguard Worker 			/*
1234*8d67ca89SAndroid Build Coastguard Worker 			** Two transitions per year, from EPOCH_YEAR forward.
1235*8d67ca89SAndroid Build Coastguard Worker 			*/
1236*8d67ca89SAndroid Build Coastguard Worker 			init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1237*8d67ca89SAndroid Build Coastguard Worker 			init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1238*8d67ca89SAndroid Build Coastguard Worker 			sp->defaulttype = 0;
1239*8d67ca89SAndroid Build Coastguard Worker 			timecnt = 0;
1240*8d67ca89SAndroid Build Coastguard Worker 			janfirst = 0;
1241*8d67ca89SAndroid Build Coastguard Worker 			yearbeg = EPOCH_YEAR;
1242*8d67ca89SAndroid Build Coastguard Worker 
1243*8d67ca89SAndroid Build Coastguard Worker 			do {
1244*8d67ca89SAndroid Build Coastguard Worker 			  int_fast32_t yearsecs
1245*8d67ca89SAndroid Build Coastguard Worker 			    = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1246*8d67ca89SAndroid Build Coastguard Worker 			  yearbeg--;
1247*8d67ca89SAndroid Build Coastguard Worker 			  if (increment_overflow_time(&janfirst, -yearsecs)) {
1248*8d67ca89SAndroid Build Coastguard Worker 			    janoffset = -yearsecs;
1249*8d67ca89SAndroid Build Coastguard Worker 			    break;
1250*8d67ca89SAndroid Build Coastguard Worker 			  }
1251*8d67ca89SAndroid Build Coastguard Worker 			} while (atlo < janfirst
1252*8d67ca89SAndroid Build Coastguard Worker 				 && EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1253*8d67ca89SAndroid Build Coastguard Worker 
1254*8d67ca89SAndroid Build Coastguard Worker 			while (true) {
1255*8d67ca89SAndroid Build Coastguard Worker 			  int_fast32_t yearsecs
1256*8d67ca89SAndroid Build Coastguard Worker 			    = year_lengths[isleap(yearbeg)] * SECSPERDAY;
1257*8d67ca89SAndroid Build Coastguard Worker 			  int yearbeg1 = yearbeg;
1258*8d67ca89SAndroid Build Coastguard Worker 			  time_t janfirst1 = janfirst;
1259*8d67ca89SAndroid Build Coastguard Worker 			  if (increment_overflow_time(&janfirst1, yearsecs)
1260*8d67ca89SAndroid Build Coastguard Worker 			      || increment_overflow(&yearbeg1, 1)
1261*8d67ca89SAndroid Build Coastguard Worker 			      || atlo <= janfirst1)
1262*8d67ca89SAndroid Build Coastguard Worker 			    break;
1263*8d67ca89SAndroid Build Coastguard Worker 			  yearbeg = yearbeg1;
1264*8d67ca89SAndroid Build Coastguard Worker 			  janfirst = janfirst1;
1265*8d67ca89SAndroid Build Coastguard Worker 			}
1266*8d67ca89SAndroid Build Coastguard Worker 
1267*8d67ca89SAndroid Build Coastguard Worker 			yearlim = yearbeg;
1268*8d67ca89SAndroid Build Coastguard Worker 			if (increment_overflow(&yearlim, YEARSPERREPEAT + 1))
1269*8d67ca89SAndroid Build Coastguard Worker 			  yearlim = INT_MAX;
1270*8d67ca89SAndroid Build Coastguard Worker 			for (year = yearbeg; year < yearlim; year++) {
1271*8d67ca89SAndroid Build Coastguard Worker 				int_fast32_t
1272*8d67ca89SAndroid Build Coastguard Worker 				  starttime = transtime(year, &start, stdoffset),
1273*8d67ca89SAndroid Build Coastguard Worker 				  endtime = transtime(year, &end, dstoffset);
1274*8d67ca89SAndroid Build Coastguard Worker 				int_fast32_t
1275*8d67ca89SAndroid Build Coastguard Worker 				  yearsecs = (year_lengths[isleap(year)]
1276*8d67ca89SAndroid Build Coastguard Worker 					      * SECSPERDAY);
1277*8d67ca89SAndroid Build Coastguard Worker 				bool reversed = endtime < starttime;
1278*8d67ca89SAndroid Build Coastguard Worker 				if (reversed) {
1279*8d67ca89SAndroid Build Coastguard Worker 					int_fast32_t swap = starttime;
1280*8d67ca89SAndroid Build Coastguard Worker 					starttime = endtime;
1281*8d67ca89SAndroid Build Coastguard Worker 					endtime = swap;
1282*8d67ca89SAndroid Build Coastguard Worker 				}
1283*8d67ca89SAndroid Build Coastguard Worker 				if (reversed
1284*8d67ca89SAndroid Build Coastguard Worker 				    || (starttime < endtime
1285*8d67ca89SAndroid Build Coastguard Worker 					&& endtime - starttime < yearsecs)) {
1286*8d67ca89SAndroid Build Coastguard Worker 					if (TZ_MAX_TIMES - 2 < timecnt)
1287*8d67ca89SAndroid Build Coastguard Worker 						break;
1288*8d67ca89SAndroid Build Coastguard Worker 					sp->ats[timecnt] = janfirst;
1289*8d67ca89SAndroid Build Coastguard Worker 					if (! increment_overflow_time
1290*8d67ca89SAndroid Build Coastguard Worker 					    (&sp->ats[timecnt],
1291*8d67ca89SAndroid Build Coastguard Worker 					     janoffset + starttime)
1292*8d67ca89SAndroid Build Coastguard Worker 					    && atlo <= sp->ats[timecnt])
1293*8d67ca89SAndroid Build Coastguard Worker 					  sp->types[timecnt++] = !reversed;
1294*8d67ca89SAndroid Build Coastguard Worker 					sp->ats[timecnt] = janfirst;
1295*8d67ca89SAndroid Build Coastguard Worker 					if (! increment_overflow_time
1296*8d67ca89SAndroid Build Coastguard Worker 					    (&sp->ats[timecnt],
1297*8d67ca89SAndroid Build Coastguard Worker 					     janoffset + endtime)
1298*8d67ca89SAndroid Build Coastguard Worker 					    && atlo <= sp->ats[timecnt]) {
1299*8d67ca89SAndroid Build Coastguard Worker 					  sp->types[timecnt++] = reversed;
1300*8d67ca89SAndroid Build Coastguard Worker 					}
1301*8d67ca89SAndroid Build Coastguard Worker 				}
1302*8d67ca89SAndroid Build Coastguard Worker 				if (endtime < leaplo) {
1303*8d67ca89SAndroid Build Coastguard Worker 				  yearlim = year;
1304*8d67ca89SAndroid Build Coastguard Worker 				  if (increment_overflow(&yearlim,
1305*8d67ca89SAndroid Build Coastguard Worker 							 YEARSPERREPEAT + 1))
1306*8d67ca89SAndroid Build Coastguard Worker 				    yearlim = INT_MAX;
1307*8d67ca89SAndroid Build Coastguard Worker 				}
1308*8d67ca89SAndroid Build Coastguard Worker 				if (increment_overflow_time
1309*8d67ca89SAndroid Build Coastguard Worker 				    (&janfirst, janoffset + yearsecs))
1310*8d67ca89SAndroid Build Coastguard Worker 					break;
1311*8d67ca89SAndroid Build Coastguard Worker 				janoffset = 0;
1312*8d67ca89SAndroid Build Coastguard Worker 			}
1313*8d67ca89SAndroid Build Coastguard Worker 			sp->timecnt = timecnt;
1314*8d67ca89SAndroid Build Coastguard Worker 			if (! timecnt) {
1315*8d67ca89SAndroid Build Coastguard Worker 				sp->ttis[0] = sp->ttis[1];
1316*8d67ca89SAndroid Build Coastguard Worker 				sp->typecnt = 1;	/* Perpetual DST.  */
1317*8d67ca89SAndroid Build Coastguard Worker 			} else if (YEARSPERREPEAT < year - yearbeg)
1318*8d67ca89SAndroid Build Coastguard Worker 				sp->goback = sp->goahead = true;
1319*8d67ca89SAndroid Build Coastguard Worker 		} else {
1320*8d67ca89SAndroid Build Coastguard Worker 			register int_fast32_t	theirstdoffset;
1321*8d67ca89SAndroid Build Coastguard Worker 			register int_fast32_t	theirdstoffset;
1322*8d67ca89SAndroid Build Coastguard Worker 			register int_fast32_t	theiroffset;
1323*8d67ca89SAndroid Build Coastguard Worker 			register bool		isdst;
1324*8d67ca89SAndroid Build Coastguard Worker 			register int		i;
1325*8d67ca89SAndroid Build Coastguard Worker 			register int		j;
1326*8d67ca89SAndroid Build Coastguard Worker 
1327*8d67ca89SAndroid Build Coastguard Worker 			if (*name != '\0')
1328*8d67ca89SAndroid Build Coastguard Worker 			  return false;
1329*8d67ca89SAndroid Build Coastguard Worker 			/*
1330*8d67ca89SAndroid Build Coastguard Worker 			** Initial values of theirstdoffset and theirdstoffset.
1331*8d67ca89SAndroid Build Coastguard Worker 			*/
1332*8d67ca89SAndroid Build Coastguard Worker 			theirstdoffset = 0;
1333*8d67ca89SAndroid Build Coastguard Worker 			for (i = 0; i < sp->timecnt; ++i) {
1334*8d67ca89SAndroid Build Coastguard Worker 				j = sp->types[i];
1335*8d67ca89SAndroid Build Coastguard Worker 				if (!sp->ttis[j].tt_isdst) {
1336*8d67ca89SAndroid Build Coastguard Worker 					theirstdoffset =
1337*8d67ca89SAndroid Build Coastguard Worker 						- sp->ttis[j].tt_utoff;
1338*8d67ca89SAndroid Build Coastguard Worker 					break;
1339*8d67ca89SAndroid Build Coastguard Worker 				}
1340*8d67ca89SAndroid Build Coastguard Worker 			}
1341*8d67ca89SAndroid Build Coastguard Worker 			theirdstoffset = 0;
1342*8d67ca89SAndroid Build Coastguard Worker 			for (i = 0; i < sp->timecnt; ++i) {
1343*8d67ca89SAndroid Build Coastguard Worker 				j = sp->types[i];
1344*8d67ca89SAndroid Build Coastguard Worker 				if (sp->ttis[j].tt_isdst) {
1345*8d67ca89SAndroid Build Coastguard Worker 					theirdstoffset =
1346*8d67ca89SAndroid Build Coastguard Worker 						- sp->ttis[j].tt_utoff;
1347*8d67ca89SAndroid Build Coastguard Worker 					break;
1348*8d67ca89SAndroid Build Coastguard Worker 				}
1349*8d67ca89SAndroid Build Coastguard Worker 			}
1350*8d67ca89SAndroid Build Coastguard Worker 			/*
1351*8d67ca89SAndroid Build Coastguard Worker 			** Initially we're assumed to be in standard time.
1352*8d67ca89SAndroid Build Coastguard Worker 			*/
1353*8d67ca89SAndroid Build Coastguard Worker 			isdst = false;
1354*8d67ca89SAndroid Build Coastguard Worker 			/*
1355*8d67ca89SAndroid Build Coastguard Worker 			** Now juggle transition times and types
1356*8d67ca89SAndroid Build Coastguard Worker 			** tracking offsets as you do.
1357*8d67ca89SAndroid Build Coastguard Worker 			*/
1358*8d67ca89SAndroid Build Coastguard Worker 			for (i = 0; i < sp->timecnt; ++i) {
1359*8d67ca89SAndroid Build Coastguard Worker 				j = sp->types[i];
1360*8d67ca89SAndroid Build Coastguard Worker 				sp->types[i] = sp->ttis[j].tt_isdst;
1361*8d67ca89SAndroid Build Coastguard Worker 				if (sp->ttis[j].tt_ttisut) {
1362*8d67ca89SAndroid Build Coastguard Worker 					/* No adjustment to transition time */
1363*8d67ca89SAndroid Build Coastguard Worker 				} else {
1364*8d67ca89SAndroid Build Coastguard Worker 					/*
1365*8d67ca89SAndroid Build Coastguard Worker 					** If daylight saving time is in
1366*8d67ca89SAndroid Build Coastguard Worker 					** effect, and the transition time was
1367*8d67ca89SAndroid Build Coastguard Worker 					** not specified as standard time, add
1368*8d67ca89SAndroid Build Coastguard Worker 					** the daylight saving time offset to
1369*8d67ca89SAndroid Build Coastguard Worker 					** the transition time; otherwise, add
1370*8d67ca89SAndroid Build Coastguard Worker 					** the standard time offset to the
1371*8d67ca89SAndroid Build Coastguard Worker 					** transition time.
1372*8d67ca89SAndroid Build Coastguard Worker 					*/
1373*8d67ca89SAndroid Build Coastguard Worker 					/*
1374*8d67ca89SAndroid Build Coastguard Worker 					** Transitions from DST to DDST
1375*8d67ca89SAndroid Build Coastguard Worker 					** will effectively disappear since
1376*8d67ca89SAndroid Build Coastguard Worker 					** POSIX provides for only one DST
1377*8d67ca89SAndroid Build Coastguard Worker 					** offset.
1378*8d67ca89SAndroid Build Coastguard Worker 					*/
1379*8d67ca89SAndroid Build Coastguard Worker 					if (isdst && !sp->ttis[j].tt_ttisstd) {
1380*8d67ca89SAndroid Build Coastguard Worker 						sp->ats[i] += dstoffset -
1381*8d67ca89SAndroid Build Coastguard Worker 							theirdstoffset;
1382*8d67ca89SAndroid Build Coastguard Worker 					} else {
1383*8d67ca89SAndroid Build Coastguard Worker 						sp->ats[i] += stdoffset -
1384*8d67ca89SAndroid Build Coastguard Worker 							theirstdoffset;
1385*8d67ca89SAndroid Build Coastguard Worker 					}
1386*8d67ca89SAndroid Build Coastguard Worker 				}
1387*8d67ca89SAndroid Build Coastguard Worker 				theiroffset = -sp->ttis[j].tt_utoff;
1388*8d67ca89SAndroid Build Coastguard Worker 				if (sp->ttis[j].tt_isdst)
1389*8d67ca89SAndroid Build Coastguard Worker 					theirdstoffset = theiroffset;
1390*8d67ca89SAndroid Build Coastguard Worker 				else	theirstdoffset = theiroffset;
1391*8d67ca89SAndroid Build Coastguard Worker 			}
1392*8d67ca89SAndroid Build Coastguard Worker 			/*
1393*8d67ca89SAndroid Build Coastguard Worker 			** Finally, fill in ttis.
1394*8d67ca89SAndroid Build Coastguard Worker 			*/
1395*8d67ca89SAndroid Build Coastguard Worker 			init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1396*8d67ca89SAndroid Build Coastguard Worker 			init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1397*8d67ca89SAndroid Build Coastguard Worker 			sp->typecnt = 2;
1398*8d67ca89SAndroid Build Coastguard Worker 			sp->defaulttype = 0;
1399*8d67ca89SAndroid Build Coastguard Worker 		}
1400*8d67ca89SAndroid Build Coastguard Worker 	} else {
1401*8d67ca89SAndroid Build Coastguard Worker 		dstlen = 0;
1402*8d67ca89SAndroid Build Coastguard Worker 		sp->typecnt = 1;		/* only standard time */
1403*8d67ca89SAndroid Build Coastguard Worker 		sp->timecnt = 0;
1404*8d67ca89SAndroid Build Coastguard Worker 		init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1405*8d67ca89SAndroid Build Coastguard Worker 		sp->defaulttype = 0;
1406*8d67ca89SAndroid Build Coastguard Worker 	}
1407*8d67ca89SAndroid Build Coastguard Worker 	sp->charcnt = charcnt;
1408*8d67ca89SAndroid Build Coastguard Worker 	cp = sp->chars;
1409*8d67ca89SAndroid Build Coastguard Worker 	memcpy(cp, stdname, stdlen);
1410*8d67ca89SAndroid Build Coastguard Worker 	cp += stdlen;
1411*8d67ca89SAndroid Build Coastguard Worker 	*cp++ = '\0';
1412*8d67ca89SAndroid Build Coastguard Worker 	if (dstlen != 0) {
1413*8d67ca89SAndroid Build Coastguard Worker 		memcpy(cp, dstname, dstlen);
1414*8d67ca89SAndroid Build Coastguard Worker 		*(cp + dstlen) = '\0';
1415*8d67ca89SAndroid Build Coastguard Worker 	}
1416*8d67ca89SAndroid Build Coastguard Worker 	return true;
1417*8d67ca89SAndroid Build Coastguard Worker }
1418*8d67ca89SAndroid Build Coastguard Worker 
1419*8d67ca89SAndroid Build Coastguard Worker static void
gmtload(struct state * const sp)1420*8d67ca89SAndroid Build Coastguard Worker gmtload(struct state *const sp)
1421*8d67ca89SAndroid Build Coastguard Worker {
1422*8d67ca89SAndroid Build Coastguard Worker 	if (tzload(etc_utc, sp, true) != 0)
1423*8d67ca89SAndroid Build Coastguard Worker 	  tzparse("UTC0", sp, NULL);
1424*8d67ca89SAndroid Build Coastguard Worker }
1425*8d67ca89SAndroid Build Coastguard Worker 
1426*8d67ca89SAndroid Build Coastguard Worker /* Initialize *SP to a value appropriate for the TZ setting NAME.
1427*8d67ca89SAndroid Build Coastguard Worker    Return 0 on success, an errno value on failure.  */
1428*8d67ca89SAndroid Build Coastguard Worker static int
zoneinit(struct state * sp,char const * name)1429*8d67ca89SAndroid Build Coastguard Worker zoneinit(struct state *sp, char const *name)
1430*8d67ca89SAndroid Build Coastguard Worker {
1431*8d67ca89SAndroid Build Coastguard Worker   if (name && ! name[0]) {
1432*8d67ca89SAndroid Build Coastguard Worker     /*
1433*8d67ca89SAndroid Build Coastguard Worker     ** User wants it fast rather than right.
1434*8d67ca89SAndroid Build Coastguard Worker     */
1435*8d67ca89SAndroid Build Coastguard Worker     sp->leapcnt = 0;		/* so, we're off a little */
1436*8d67ca89SAndroid Build Coastguard Worker     sp->timecnt = 0;
1437*8d67ca89SAndroid Build Coastguard Worker     sp->typecnt = 0;
1438*8d67ca89SAndroid Build Coastguard Worker     sp->charcnt = 0;
1439*8d67ca89SAndroid Build Coastguard Worker     sp->goback = sp->goahead = false;
1440*8d67ca89SAndroid Build Coastguard Worker     init_ttinfo(&sp->ttis[0], 0, false, 0);
1441*8d67ca89SAndroid Build Coastguard Worker     strcpy(sp->chars, utc);
1442*8d67ca89SAndroid Build Coastguard Worker     sp->defaulttype = 0;
1443*8d67ca89SAndroid Build Coastguard Worker     return 0;
1444*8d67ca89SAndroid Build Coastguard Worker   } else {
1445*8d67ca89SAndroid Build Coastguard Worker     int err = tzload(name, sp, true);
1446*8d67ca89SAndroid Build Coastguard Worker     if (err != 0 && name && name[0] != ':' && tzparse(name, sp, NULL))
1447*8d67ca89SAndroid Build Coastguard Worker       err = 0;
1448*8d67ca89SAndroid Build Coastguard Worker     if (err == 0)
1449*8d67ca89SAndroid Build Coastguard Worker       err = scrub_abbrs(sp);
1450*8d67ca89SAndroid Build Coastguard Worker     return err;
1451*8d67ca89SAndroid Build Coastguard Worker   }
1452*8d67ca89SAndroid Build Coastguard Worker }
1453*8d67ca89SAndroid Build Coastguard Worker 
1454*8d67ca89SAndroid Build Coastguard Worker void
tzsetlcl(char const * name)1455*8d67ca89SAndroid Build Coastguard Worker tzsetlcl(char const *name)
1456*8d67ca89SAndroid Build Coastguard Worker {
1457*8d67ca89SAndroid Build Coastguard Worker   struct state *sp = lclptr;
1458*8d67ca89SAndroid Build Coastguard Worker   int lcl = name ? strlen(name) < sizeof lcl_TZname : -1;
1459*8d67ca89SAndroid Build Coastguard Worker   if (lcl < 0
1460*8d67ca89SAndroid Build Coastguard Worker       ? lcl_is_set < 0
1461*8d67ca89SAndroid Build Coastguard Worker       : 0 < lcl_is_set && strcmp(lcl_TZname, name) == 0)
1462*8d67ca89SAndroid Build Coastguard Worker     return;
1463*8d67ca89SAndroid Build Coastguard Worker #ifdef ALL_STATE
1464*8d67ca89SAndroid Build Coastguard Worker   if (! sp)
1465*8d67ca89SAndroid Build Coastguard Worker     lclptr = sp = malloc(sizeof *lclptr);
1466*8d67ca89SAndroid Build Coastguard Worker #endif /* defined ALL_STATE */
1467*8d67ca89SAndroid Build Coastguard Worker   if (sp) {
1468*8d67ca89SAndroid Build Coastguard Worker     if (zoneinit(sp, name) != 0)
1469*8d67ca89SAndroid Build Coastguard Worker       zoneinit(sp, "");
1470*8d67ca89SAndroid Build Coastguard Worker     if (0 < lcl)
1471*8d67ca89SAndroid Build Coastguard Worker       strcpy(lcl_TZname, name);
1472*8d67ca89SAndroid Build Coastguard Worker   }
1473*8d67ca89SAndroid Build Coastguard Worker   settzname();
1474*8d67ca89SAndroid Build Coastguard Worker   lcl_is_set = lcl;
1475*8d67ca89SAndroid Build Coastguard Worker }
1476*8d67ca89SAndroid Build Coastguard Worker 
1477*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
1478*8d67ca89SAndroid Build Coastguard Worker extern void tzset_unlocked(void);
1479*8d67ca89SAndroid Build Coastguard Worker #else
1480*8d67ca89SAndroid Build Coastguard Worker static void
tzset_unlocked(void)1481*8d67ca89SAndroid Build Coastguard Worker tzset_unlocked(void)
1482*8d67ca89SAndroid Build Coastguard Worker {
1483*8d67ca89SAndroid Build Coastguard Worker   tzsetlcl(getenv("TZ"));
1484*8d67ca89SAndroid Build Coastguard Worker }
1485*8d67ca89SAndroid Build Coastguard Worker #endif
1486*8d67ca89SAndroid Build Coastguard Worker 
1487*8d67ca89SAndroid Build Coastguard Worker void
tzset(void)1488*8d67ca89SAndroid Build Coastguard Worker tzset(void)
1489*8d67ca89SAndroid Build Coastguard Worker {
1490*8d67ca89SAndroid Build Coastguard Worker   if (lock() != 0)
1491*8d67ca89SAndroid Build Coastguard Worker     return;
1492*8d67ca89SAndroid Build Coastguard Worker   tzset_unlocked();
1493*8d67ca89SAndroid Build Coastguard Worker   unlock();
1494*8d67ca89SAndroid Build Coastguard Worker }
1495*8d67ca89SAndroid Build Coastguard Worker 
1496*8d67ca89SAndroid Build Coastguard Worker static void
gmtcheck(void)1497*8d67ca89SAndroid Build Coastguard Worker gmtcheck(void)
1498*8d67ca89SAndroid Build Coastguard Worker {
1499*8d67ca89SAndroid Build Coastguard Worker   static bool gmt_is_set;
1500*8d67ca89SAndroid Build Coastguard Worker   if (lock() != 0)
1501*8d67ca89SAndroid Build Coastguard Worker     return;
1502*8d67ca89SAndroid Build Coastguard Worker   if (! gmt_is_set) {
1503*8d67ca89SAndroid Build Coastguard Worker #ifdef ALL_STATE
1504*8d67ca89SAndroid Build Coastguard Worker     gmtptr = malloc(sizeof *gmtptr);
1505*8d67ca89SAndroid Build Coastguard Worker #endif
1506*8d67ca89SAndroid Build Coastguard Worker     if (gmtptr)
1507*8d67ca89SAndroid Build Coastguard Worker       gmtload(gmtptr);
1508*8d67ca89SAndroid Build Coastguard Worker     gmt_is_set = true;
1509*8d67ca89SAndroid Build Coastguard Worker   }
1510*8d67ca89SAndroid Build Coastguard Worker   unlock();
1511*8d67ca89SAndroid Build Coastguard Worker }
1512*8d67ca89SAndroid Build Coastguard Worker 
1513*8d67ca89SAndroid Build Coastguard Worker #if NETBSD_INSPIRED
1514*8d67ca89SAndroid Build Coastguard Worker 
1515*8d67ca89SAndroid Build Coastguard Worker timezone_t
tzalloc(char const * name)1516*8d67ca89SAndroid Build Coastguard Worker tzalloc(char const *name)
1517*8d67ca89SAndroid Build Coastguard Worker {
1518*8d67ca89SAndroid Build Coastguard Worker   timezone_t sp = malloc(sizeof *sp);
1519*8d67ca89SAndroid Build Coastguard Worker   if (sp) {
1520*8d67ca89SAndroid Build Coastguard Worker     int err = zoneinit(sp, name);
1521*8d67ca89SAndroid Build Coastguard Worker     if (err != 0) {
1522*8d67ca89SAndroid Build Coastguard Worker       free(sp);
1523*8d67ca89SAndroid Build Coastguard Worker       errno = err;
1524*8d67ca89SAndroid Build Coastguard Worker       return NULL;
1525*8d67ca89SAndroid Build Coastguard Worker     }
1526*8d67ca89SAndroid Build Coastguard Worker   } else if (!HAVE_MALLOC_ERRNO)
1527*8d67ca89SAndroid Build Coastguard Worker     errno = ENOMEM;
1528*8d67ca89SAndroid Build Coastguard Worker   return sp;
1529*8d67ca89SAndroid Build Coastguard Worker }
1530*8d67ca89SAndroid Build Coastguard Worker 
1531*8d67ca89SAndroid Build Coastguard Worker void
tzfree(timezone_t sp)1532*8d67ca89SAndroid Build Coastguard Worker tzfree(timezone_t sp)
1533*8d67ca89SAndroid Build Coastguard Worker {
1534*8d67ca89SAndroid Build Coastguard Worker   free(sp);
1535*8d67ca89SAndroid Build Coastguard Worker }
1536*8d67ca89SAndroid Build Coastguard Worker 
1537*8d67ca89SAndroid Build Coastguard Worker /*
1538*8d67ca89SAndroid Build Coastguard Worker ** NetBSD 6.1.4 has ctime_rz, but omit it because POSIX says ctime and
1539*8d67ca89SAndroid Build Coastguard Worker ** ctime_r are obsolescent and have potential security problems that
1540*8d67ca89SAndroid Build Coastguard Worker ** ctime_rz would share.  Callers can instead use localtime_rz + strftime.
1541*8d67ca89SAndroid Build Coastguard Worker **
1542*8d67ca89SAndroid Build Coastguard Worker ** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work
1543*8d67ca89SAndroid Build Coastguard Worker ** in zones with three or more time zone abbreviations.
1544*8d67ca89SAndroid Build Coastguard Worker ** Callers can instead use localtime_rz + strftime.
1545*8d67ca89SAndroid Build Coastguard Worker */
1546*8d67ca89SAndroid Build Coastguard Worker 
1547*8d67ca89SAndroid Build Coastguard Worker #endif
1548*8d67ca89SAndroid Build Coastguard Worker 
1549*8d67ca89SAndroid Build Coastguard Worker /*
1550*8d67ca89SAndroid Build Coastguard Worker ** The easy way to behave "as if no library function calls" localtime
1551*8d67ca89SAndroid Build Coastguard Worker ** is to not call it, so we drop its guts into "localsub", which can be
1552*8d67ca89SAndroid Build Coastguard Worker ** freely called. (And no, the PANS doesn't require the above behavior,
1553*8d67ca89SAndroid Build Coastguard Worker ** but it *is* desirable.)
1554*8d67ca89SAndroid Build Coastguard Worker **
1555*8d67ca89SAndroid Build Coastguard Worker ** If successful and SETNAME is nonzero,
1556*8d67ca89SAndroid Build Coastguard Worker ** set the applicable parts of tzname, timezone and altzone;
1557*8d67ca89SAndroid Build Coastguard Worker ** however, it's OK to omit this step if the timezone is POSIX-compatible,
1558*8d67ca89SAndroid Build Coastguard Worker ** since in that case tzset should have already done this step correctly.
1559*8d67ca89SAndroid Build Coastguard Worker ** SETNAME's type is int_fast32_t for compatibility with gmtsub,
1560*8d67ca89SAndroid Build Coastguard Worker ** but it is actually a boolean and its value should be 0 or 1.
1561*8d67ca89SAndroid Build Coastguard Worker */
1562*8d67ca89SAndroid Build Coastguard Worker 
1563*8d67ca89SAndroid Build Coastguard Worker /*ARGSUSED*/
1564*8d67ca89SAndroid Build Coastguard Worker static struct tm *
localsub(struct state const * sp,time_t const * timep,int_fast32_t setname,struct tm * const tmp)1565*8d67ca89SAndroid Build Coastguard Worker localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
1566*8d67ca89SAndroid Build Coastguard Worker 	 struct tm *const tmp)
1567*8d67ca89SAndroid Build Coastguard Worker {
1568*8d67ca89SAndroid Build Coastguard Worker 	register const struct ttinfo *	ttisp;
1569*8d67ca89SAndroid Build Coastguard Worker 	register int			i;
1570*8d67ca89SAndroid Build Coastguard Worker 	register struct tm *		result;
1571*8d67ca89SAndroid Build Coastguard Worker 	const time_t			t = *timep;
1572*8d67ca89SAndroid Build Coastguard Worker 
1573*8d67ca89SAndroid Build Coastguard Worker 	if (sp == NULL) {
1574*8d67ca89SAndroid Build Coastguard Worker 	  /* Don't bother to set tzname etc.; tzset has already done it.  */
1575*8d67ca89SAndroid Build Coastguard Worker 	  return gmtsub(gmtptr, timep, 0, tmp);
1576*8d67ca89SAndroid Build Coastguard Worker 	}
1577*8d67ca89SAndroid Build Coastguard Worker 	if ((sp->goback && t < sp->ats[0]) ||
1578*8d67ca89SAndroid Build Coastguard Worker 		(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1579*8d67ca89SAndroid Build Coastguard Worker 			time_t newt;
1580*8d67ca89SAndroid Build Coastguard Worker 			register time_t		seconds;
1581*8d67ca89SAndroid Build Coastguard Worker 			register time_t		years;
1582*8d67ca89SAndroid Build Coastguard Worker 
1583*8d67ca89SAndroid Build Coastguard Worker 			if (t < sp->ats[0])
1584*8d67ca89SAndroid Build Coastguard Worker 				seconds = sp->ats[0] - t;
1585*8d67ca89SAndroid Build Coastguard Worker 			else	seconds = t - sp->ats[sp->timecnt - 1];
1586*8d67ca89SAndroid Build Coastguard Worker 			--seconds;
1587*8d67ca89SAndroid Build Coastguard Worker 
1588*8d67ca89SAndroid Build Coastguard Worker 			/* Beware integer overflow, as SECONDS might
1589*8d67ca89SAndroid Build Coastguard Worker 			   be close to the maximum time_t.  */
1590*8d67ca89SAndroid Build Coastguard Worker 			years = seconds / SECSPERREPEAT * YEARSPERREPEAT;
1591*8d67ca89SAndroid Build Coastguard Worker 			seconds = years * AVGSECSPERYEAR;
1592*8d67ca89SAndroid Build Coastguard Worker 			years += YEARSPERREPEAT;
1593*8d67ca89SAndroid Build Coastguard Worker 			if (t < sp->ats[0])
1594*8d67ca89SAndroid Build Coastguard Worker 			  newt = t + seconds + SECSPERREPEAT;
1595*8d67ca89SAndroid Build Coastguard Worker 			else
1596*8d67ca89SAndroid Build Coastguard Worker 			  newt = t - seconds - SECSPERREPEAT;
1597*8d67ca89SAndroid Build Coastguard Worker 
1598*8d67ca89SAndroid Build Coastguard Worker 			if (newt < sp->ats[0] ||
1599*8d67ca89SAndroid Build Coastguard Worker 				newt > sp->ats[sp->timecnt - 1])
1600*8d67ca89SAndroid Build Coastguard Worker 					return NULL;	/* "cannot happen" */
1601*8d67ca89SAndroid Build Coastguard Worker 			result = localsub(sp, &newt, setname, tmp);
1602*8d67ca89SAndroid Build Coastguard Worker 			if (result) {
1603*8d67ca89SAndroid Build Coastguard Worker #if defined ckd_add && defined ckd_sub
1604*8d67ca89SAndroid Build Coastguard Worker 				if (t < sp->ats[0]
1605*8d67ca89SAndroid Build Coastguard Worker 				    ? ckd_sub(&result->tm_year,
1606*8d67ca89SAndroid Build Coastguard Worker 					      result->tm_year, years)
1607*8d67ca89SAndroid Build Coastguard Worker 				    : ckd_add(&result->tm_year,
1608*8d67ca89SAndroid Build Coastguard Worker 					      result->tm_year, years))
1609*8d67ca89SAndroid Build Coastguard Worker 				  return NULL;
1610*8d67ca89SAndroid Build Coastguard Worker #else
1611*8d67ca89SAndroid Build Coastguard Worker 				register int_fast64_t newy;
1612*8d67ca89SAndroid Build Coastguard Worker 
1613*8d67ca89SAndroid Build Coastguard Worker 				newy = result->tm_year;
1614*8d67ca89SAndroid Build Coastguard Worker 				if (t < sp->ats[0])
1615*8d67ca89SAndroid Build Coastguard Worker 					newy -= years;
1616*8d67ca89SAndroid Build Coastguard Worker 				else	newy += years;
1617*8d67ca89SAndroid Build Coastguard Worker 				if (! (INT_MIN <= newy && newy <= INT_MAX))
1618*8d67ca89SAndroid Build Coastguard Worker 					return NULL;
1619*8d67ca89SAndroid Build Coastguard Worker 				result->tm_year = newy;
1620*8d67ca89SAndroid Build Coastguard Worker #endif
1621*8d67ca89SAndroid Build Coastguard Worker 			}
1622*8d67ca89SAndroid Build Coastguard Worker 			return result;
1623*8d67ca89SAndroid Build Coastguard Worker 	}
1624*8d67ca89SAndroid Build Coastguard Worker 	if (sp->timecnt == 0 || t < sp->ats[0]) {
1625*8d67ca89SAndroid Build Coastguard Worker 		i = sp->defaulttype;
1626*8d67ca89SAndroid Build Coastguard Worker 	} else {
1627*8d67ca89SAndroid Build Coastguard Worker 		register int	lo = 1;
1628*8d67ca89SAndroid Build Coastguard Worker 		register int	hi = sp->timecnt;
1629*8d67ca89SAndroid Build Coastguard Worker 
1630*8d67ca89SAndroid Build Coastguard Worker 		while (lo < hi) {
1631*8d67ca89SAndroid Build Coastguard Worker 			register int	mid = (lo + hi) >> 1;
1632*8d67ca89SAndroid Build Coastguard Worker 
1633*8d67ca89SAndroid Build Coastguard Worker 			if (t < sp->ats[mid])
1634*8d67ca89SAndroid Build Coastguard Worker 				hi = mid;
1635*8d67ca89SAndroid Build Coastguard Worker 			else	lo = mid + 1;
1636*8d67ca89SAndroid Build Coastguard Worker 		}
1637*8d67ca89SAndroid Build Coastguard Worker 		i = sp->types[lo - 1];
1638*8d67ca89SAndroid Build Coastguard Worker 	}
1639*8d67ca89SAndroid Build Coastguard Worker 	ttisp = &sp->ttis[i];
1640*8d67ca89SAndroid Build Coastguard Worker 	/*
1641*8d67ca89SAndroid Build Coastguard Worker 	** To get (wrong) behavior that's compatible with System V Release 2.0
1642*8d67ca89SAndroid Build Coastguard Worker 	** you'd replace the statement below with
1643*8d67ca89SAndroid Build Coastguard Worker 	**	t += ttisp->tt_utoff;
1644*8d67ca89SAndroid Build Coastguard Worker 	**	timesub(&t, 0L, sp, tmp);
1645*8d67ca89SAndroid Build Coastguard Worker 	*/
1646*8d67ca89SAndroid Build Coastguard Worker 	result = timesub(&t, ttisp->tt_utoff, sp, tmp);
1647*8d67ca89SAndroid Build Coastguard Worker 	if (result) {
1648*8d67ca89SAndroid Build Coastguard Worker 	  result->tm_isdst = ttisp->tt_isdst;
1649*8d67ca89SAndroid Build Coastguard Worker #ifdef TM_ZONE
1650*8d67ca89SAndroid Build Coastguard Worker 	  result->TM_ZONE = (char *) &sp->chars[ttisp->tt_desigidx];
1651*8d67ca89SAndroid Build Coastguard Worker #endif /* defined TM_ZONE */
1652*8d67ca89SAndroid Build Coastguard Worker 	  if (setname)
1653*8d67ca89SAndroid Build Coastguard Worker 	    update_tzname_etc(sp, ttisp);
1654*8d67ca89SAndroid Build Coastguard Worker 	}
1655*8d67ca89SAndroid Build Coastguard Worker 	return result;
1656*8d67ca89SAndroid Build Coastguard Worker }
1657*8d67ca89SAndroid Build Coastguard Worker 
1658*8d67ca89SAndroid Build Coastguard Worker #if NETBSD_INSPIRED
1659*8d67ca89SAndroid Build Coastguard Worker 
1660*8d67ca89SAndroid Build Coastguard Worker struct tm *
localtime_rz(struct state * restrict sp,time_t const * restrict timep,struct tm * restrict tmp)1661*8d67ca89SAndroid Build Coastguard Worker localtime_rz(struct state *restrict sp, time_t const *restrict timep,
1662*8d67ca89SAndroid Build Coastguard Worker 	     struct tm *restrict tmp)
1663*8d67ca89SAndroid Build Coastguard Worker {
1664*8d67ca89SAndroid Build Coastguard Worker   return localsub(sp, timep, 0, tmp);
1665*8d67ca89SAndroid Build Coastguard Worker }
1666*8d67ca89SAndroid Build Coastguard Worker 
1667*8d67ca89SAndroid Build Coastguard Worker #endif
1668*8d67ca89SAndroid Build Coastguard Worker 
1669*8d67ca89SAndroid Build Coastguard Worker static struct tm *
localtime_tzset(time_t const * timep,struct tm * tmp)1670*8d67ca89SAndroid Build Coastguard Worker localtime_tzset(time_t const *timep, struct tm *tmp)
1671*8d67ca89SAndroid Build Coastguard Worker {
1672*8d67ca89SAndroid Build Coastguard Worker   int err = lock();
1673*8d67ca89SAndroid Build Coastguard Worker   if (err) {
1674*8d67ca89SAndroid Build Coastguard Worker     errno = err;
1675*8d67ca89SAndroid Build Coastguard Worker     return NULL;
1676*8d67ca89SAndroid Build Coastguard Worker   }
1677*8d67ca89SAndroid Build Coastguard Worker 
1678*8d67ca89SAndroid Build Coastguard Worker   // http://b/31339449: POSIX says localtime(3) acts as if it called tzset(3), but upstream
1679*8d67ca89SAndroid Build Coastguard Worker   // and glibc both think it's okay for localtime_r(3) to not do so (presumably because of
1680*8d67ca89SAndroid Build Coastguard Worker   // the "not required to set tzname" clause). It's unclear that POSIX actually intended this,
1681*8d67ca89SAndroid Build Coastguard Worker   // the BSDs disagree with glibc, and it's confusing to developers to have localtime_r(3)
1682*8d67ca89SAndroid Build Coastguard Worker   // behave differently than other time zone-sensitive functions in <time.h>.
1683*8d67ca89SAndroid Build Coastguard Worker   tzset_unlocked();
1684*8d67ca89SAndroid Build Coastguard Worker 
1685*8d67ca89SAndroid Build Coastguard Worker   tmp = localsub(lclptr, timep, true, tmp);
1686*8d67ca89SAndroid Build Coastguard Worker   unlock();
1687*8d67ca89SAndroid Build Coastguard Worker   return tmp;
1688*8d67ca89SAndroid Build Coastguard Worker }
1689*8d67ca89SAndroid Build Coastguard Worker 
1690*8d67ca89SAndroid Build Coastguard Worker struct tm *
localtime(const time_t * timep)1691*8d67ca89SAndroid Build Coastguard Worker localtime(const time_t *timep)
1692*8d67ca89SAndroid Build Coastguard Worker {
1693*8d67ca89SAndroid Build Coastguard Worker #if !SUPPORT_C89
1694*8d67ca89SAndroid Build Coastguard Worker   static struct tm tm;
1695*8d67ca89SAndroid Build Coastguard Worker #endif
1696*8d67ca89SAndroid Build Coastguard Worker   return localtime_tzset(timep, &tm);
1697*8d67ca89SAndroid Build Coastguard Worker }
1698*8d67ca89SAndroid Build Coastguard Worker 
1699*8d67ca89SAndroid Build Coastguard Worker struct tm *
localtime_r(const time_t * restrict timep,struct tm * restrict tmp)1700*8d67ca89SAndroid Build Coastguard Worker localtime_r(const time_t *restrict timep, struct tm *restrict tmp)
1701*8d67ca89SAndroid Build Coastguard Worker {
1702*8d67ca89SAndroid Build Coastguard Worker   return localtime_tzset(timep, tmp);
1703*8d67ca89SAndroid Build Coastguard Worker }
1704*8d67ca89SAndroid Build Coastguard Worker 
1705*8d67ca89SAndroid Build Coastguard Worker /*
1706*8d67ca89SAndroid Build Coastguard Worker ** gmtsub is to gmtime as localsub is to localtime.
1707*8d67ca89SAndroid Build Coastguard Worker */
1708*8d67ca89SAndroid Build Coastguard Worker 
1709*8d67ca89SAndroid Build Coastguard Worker static struct tm *
gmtsub(ATTRIBUTE_MAYBE_UNUSED struct state const * sp,time_t const * timep,int_fast32_t offset,struct tm * tmp)1710*8d67ca89SAndroid Build Coastguard Worker gmtsub(ATTRIBUTE_MAYBE_UNUSED struct state const *sp, time_t const *timep,
1711*8d67ca89SAndroid Build Coastguard Worker        int_fast32_t offset, struct tm *tmp)
1712*8d67ca89SAndroid Build Coastguard Worker {
1713*8d67ca89SAndroid Build Coastguard Worker 	register struct tm *	result;
1714*8d67ca89SAndroid Build Coastguard Worker 
1715*8d67ca89SAndroid Build Coastguard Worker 	result = timesub(timep, offset, gmtptr, tmp);
1716*8d67ca89SAndroid Build Coastguard Worker #ifdef TM_ZONE
1717*8d67ca89SAndroid Build Coastguard Worker 	/*
1718*8d67ca89SAndroid Build Coastguard Worker 	** Could get fancy here and deliver something such as
1719*8d67ca89SAndroid Build Coastguard Worker 	** "+xx" or "-xx" if offset is non-zero,
1720*8d67ca89SAndroid Build Coastguard Worker 	** but this is no time for a treasure hunt.
1721*8d67ca89SAndroid Build Coastguard Worker 	*/
1722*8d67ca89SAndroid Build Coastguard Worker 	tmp->TM_ZONE = ((char *)
1723*8d67ca89SAndroid Build Coastguard Worker 			(offset ? wildabbr : gmtptr ? gmtptr->chars : utc));
1724*8d67ca89SAndroid Build Coastguard Worker #endif /* defined TM_ZONE */
1725*8d67ca89SAndroid Build Coastguard Worker 	return result;
1726*8d67ca89SAndroid Build Coastguard Worker }
1727*8d67ca89SAndroid Build Coastguard Worker 
1728*8d67ca89SAndroid Build Coastguard Worker /*
1729*8d67ca89SAndroid Build Coastguard Worker * Re-entrant version of gmtime.
1730*8d67ca89SAndroid Build Coastguard Worker */
1731*8d67ca89SAndroid Build Coastguard Worker 
1732*8d67ca89SAndroid Build Coastguard Worker struct tm *
gmtime_r(time_t const * restrict timep,struct tm * restrict tmp)1733*8d67ca89SAndroid Build Coastguard Worker gmtime_r(time_t const *restrict timep, struct tm *restrict tmp)
1734*8d67ca89SAndroid Build Coastguard Worker {
1735*8d67ca89SAndroid Build Coastguard Worker   gmtcheck();
1736*8d67ca89SAndroid Build Coastguard Worker   return gmtsub(gmtptr, timep, 0, tmp);
1737*8d67ca89SAndroid Build Coastguard Worker }
1738*8d67ca89SAndroid Build Coastguard Worker 
1739*8d67ca89SAndroid Build Coastguard Worker struct tm *
gmtime(const time_t * timep)1740*8d67ca89SAndroid Build Coastguard Worker gmtime(const time_t *timep)
1741*8d67ca89SAndroid Build Coastguard Worker {
1742*8d67ca89SAndroid Build Coastguard Worker #if !SUPPORT_C89
1743*8d67ca89SAndroid Build Coastguard Worker   static struct tm tm;
1744*8d67ca89SAndroid Build Coastguard Worker #endif
1745*8d67ca89SAndroid Build Coastguard Worker   return gmtime_r(timep, &tm);
1746*8d67ca89SAndroid Build Coastguard Worker }
1747*8d67ca89SAndroid Build Coastguard Worker 
1748*8d67ca89SAndroid Build Coastguard Worker #if STD_INSPIRED
1749*8d67ca89SAndroid Build Coastguard Worker 
1750*8d67ca89SAndroid Build Coastguard Worker struct tm *
offtime(const time_t * timep,long offset)1751*8d67ca89SAndroid Build Coastguard Worker offtime(const time_t *timep, long offset)
1752*8d67ca89SAndroid Build Coastguard Worker {
1753*8d67ca89SAndroid Build Coastguard Worker   gmtcheck();
1754*8d67ca89SAndroid Build Coastguard Worker 
1755*8d67ca89SAndroid Build Coastguard Worker #if !SUPPORT_C89
1756*8d67ca89SAndroid Build Coastguard Worker   static struct tm tm;
1757*8d67ca89SAndroid Build Coastguard Worker #endif
1758*8d67ca89SAndroid Build Coastguard Worker   return gmtsub(gmtptr, timep, offset, &tm);
1759*8d67ca89SAndroid Build Coastguard Worker }
1760*8d67ca89SAndroid Build Coastguard Worker 
1761*8d67ca89SAndroid Build Coastguard Worker #endif
1762*8d67ca89SAndroid Build Coastguard Worker 
1763*8d67ca89SAndroid Build Coastguard Worker /*
1764*8d67ca89SAndroid Build Coastguard Worker ** Return the number of leap years through the end of the given year
1765*8d67ca89SAndroid Build Coastguard Worker ** where, to make the math easy, the answer for year zero is defined as zero.
1766*8d67ca89SAndroid Build Coastguard Worker */
1767*8d67ca89SAndroid Build Coastguard Worker 
1768*8d67ca89SAndroid Build Coastguard Worker static time_t
leaps_thru_end_of_nonneg(time_t y)1769*8d67ca89SAndroid Build Coastguard Worker leaps_thru_end_of_nonneg(time_t y)
1770*8d67ca89SAndroid Build Coastguard Worker {
1771*8d67ca89SAndroid Build Coastguard Worker   return y / 4 - y / 100 + y / 400;
1772*8d67ca89SAndroid Build Coastguard Worker }
1773*8d67ca89SAndroid Build Coastguard Worker 
1774*8d67ca89SAndroid Build Coastguard Worker static time_t
leaps_thru_end_of(time_t y)1775*8d67ca89SAndroid Build Coastguard Worker leaps_thru_end_of(time_t y)
1776*8d67ca89SAndroid Build Coastguard Worker {
1777*8d67ca89SAndroid Build Coastguard Worker   return (y < 0
1778*8d67ca89SAndroid Build Coastguard Worker 	  ? -1 - leaps_thru_end_of_nonneg(-1 - y)
1779*8d67ca89SAndroid Build Coastguard Worker 	  : leaps_thru_end_of_nonneg(y));
1780*8d67ca89SAndroid Build Coastguard Worker }
1781*8d67ca89SAndroid Build Coastguard Worker 
1782*8d67ca89SAndroid Build Coastguard Worker static struct tm *
timesub(const time_t * timep,int_fast32_t offset,const struct state * sp,struct tm * tmp)1783*8d67ca89SAndroid Build Coastguard Worker timesub(const time_t *timep, int_fast32_t offset,
1784*8d67ca89SAndroid Build Coastguard Worker 	const struct state *sp, struct tm *tmp)
1785*8d67ca89SAndroid Build Coastguard Worker {
1786*8d67ca89SAndroid Build Coastguard Worker 	register const struct lsinfo *	lp;
1787*8d67ca89SAndroid Build Coastguard Worker 	register time_t			tdays;
1788*8d67ca89SAndroid Build Coastguard Worker 	register const int *		ip;
1789*8d67ca89SAndroid Build Coastguard Worker 	register int_fast32_t		corr;
1790*8d67ca89SAndroid Build Coastguard Worker 	register int			i;
1791*8d67ca89SAndroid Build Coastguard Worker 	int_fast32_t idays, rem, dayoff, dayrem;
1792*8d67ca89SAndroid Build Coastguard Worker 	time_t y;
1793*8d67ca89SAndroid Build Coastguard Worker 
1794*8d67ca89SAndroid Build Coastguard Worker 	/* If less than SECSPERMIN, the number of seconds since the
1795*8d67ca89SAndroid Build Coastguard Worker 	   most recent positive leap second; otherwise, do not add 1
1796*8d67ca89SAndroid Build Coastguard Worker 	   to localtime tm_sec because of leap seconds.  */
1797*8d67ca89SAndroid Build Coastguard Worker 	time_t secs_since_posleap = SECSPERMIN;
1798*8d67ca89SAndroid Build Coastguard Worker 
1799*8d67ca89SAndroid Build Coastguard Worker 	corr = 0;
1800*8d67ca89SAndroid Build Coastguard Worker 	i = (sp == NULL) ? 0 : sp->leapcnt;
1801*8d67ca89SAndroid Build Coastguard Worker 	while (--i >= 0) {
1802*8d67ca89SAndroid Build Coastguard Worker 		lp = &sp->lsis[i];
1803*8d67ca89SAndroid Build Coastguard Worker 		if (*timep >= lp->ls_trans) {
1804*8d67ca89SAndroid Build Coastguard Worker 			corr = lp->ls_corr;
1805*8d67ca89SAndroid Build Coastguard Worker 			if ((i == 0 ? 0 : lp[-1].ls_corr) < corr)
1806*8d67ca89SAndroid Build Coastguard Worker 			  secs_since_posleap = *timep - lp->ls_trans;
1807*8d67ca89SAndroid Build Coastguard Worker 			break;
1808*8d67ca89SAndroid Build Coastguard Worker 		}
1809*8d67ca89SAndroid Build Coastguard Worker 	}
1810*8d67ca89SAndroid Build Coastguard Worker 
1811*8d67ca89SAndroid Build Coastguard Worker 	/* Calculate the year, avoiding integer overflow even if
1812*8d67ca89SAndroid Build Coastguard Worker 	   time_t is unsigned.  */
1813*8d67ca89SAndroid Build Coastguard Worker 	tdays = *timep / SECSPERDAY;
1814*8d67ca89SAndroid Build Coastguard Worker 	rem = *timep % SECSPERDAY;
1815*8d67ca89SAndroid Build Coastguard Worker 	rem += offset % SECSPERDAY - corr % SECSPERDAY + 3 * SECSPERDAY;
1816*8d67ca89SAndroid Build Coastguard Worker 	dayoff = offset / SECSPERDAY - corr / SECSPERDAY + rem / SECSPERDAY - 3;
1817*8d67ca89SAndroid Build Coastguard Worker 	rem %= SECSPERDAY;
1818*8d67ca89SAndroid Build Coastguard Worker 	/* y = (EPOCH_YEAR
1819*8d67ca89SAndroid Build Coastguard Worker 	        + floor((tdays + dayoff) / DAYSPERREPEAT) * YEARSPERREPEAT),
1820*8d67ca89SAndroid Build Coastguard Worker 	   sans overflow.  But calculate against 1570 (EPOCH_YEAR -
1821*8d67ca89SAndroid Build Coastguard Worker 	   YEARSPERREPEAT) instead of against 1970 so that things work
1822*8d67ca89SAndroid Build Coastguard Worker 	   for localtime values before 1970 when time_t is unsigned.  */
1823*8d67ca89SAndroid Build Coastguard Worker 	dayrem = tdays % DAYSPERREPEAT;
1824*8d67ca89SAndroid Build Coastguard Worker 	dayrem += dayoff % DAYSPERREPEAT;
1825*8d67ca89SAndroid Build Coastguard Worker 	y = (EPOCH_YEAR - YEARSPERREPEAT
1826*8d67ca89SAndroid Build Coastguard Worker 	     + ((1 + dayoff / DAYSPERREPEAT + dayrem / DAYSPERREPEAT
1827*8d67ca89SAndroid Build Coastguard Worker 		 - ((dayrem % DAYSPERREPEAT) < 0)
1828*8d67ca89SAndroid Build Coastguard Worker 		 + tdays / DAYSPERREPEAT)
1829*8d67ca89SAndroid Build Coastguard Worker 		* YEARSPERREPEAT));
1830*8d67ca89SAndroid Build Coastguard Worker 	/* idays = (tdays + dayoff) mod DAYSPERREPEAT, sans overflow.  */
1831*8d67ca89SAndroid Build Coastguard Worker 	idays = tdays % DAYSPERREPEAT;
1832*8d67ca89SAndroid Build Coastguard Worker 	idays += dayoff % DAYSPERREPEAT + 2 * DAYSPERREPEAT;
1833*8d67ca89SAndroid Build Coastguard Worker 	idays %= DAYSPERREPEAT;
1834*8d67ca89SAndroid Build Coastguard Worker 	/* Increase Y and decrease IDAYS until IDAYS is in range for Y.  */
1835*8d67ca89SAndroid Build Coastguard Worker 	while (year_lengths[isleap(y)] <= idays) {
1836*8d67ca89SAndroid Build Coastguard Worker 		int tdelta = idays / DAYSPERLYEAR;
1837*8d67ca89SAndroid Build Coastguard Worker 		int_fast32_t ydelta = tdelta + !tdelta;
1838*8d67ca89SAndroid Build Coastguard Worker 		time_t newy = y + ydelta;
1839*8d67ca89SAndroid Build Coastguard Worker 		register int	leapdays;
1840*8d67ca89SAndroid Build Coastguard Worker 		leapdays = leaps_thru_end_of(newy - 1) -
1841*8d67ca89SAndroid Build Coastguard Worker 			leaps_thru_end_of(y - 1);
1842*8d67ca89SAndroid Build Coastguard Worker 		idays -= ydelta * DAYSPERNYEAR;
1843*8d67ca89SAndroid Build Coastguard Worker 		idays -= leapdays;
1844*8d67ca89SAndroid Build Coastguard Worker 		y = newy;
1845*8d67ca89SAndroid Build Coastguard Worker 	}
1846*8d67ca89SAndroid Build Coastguard Worker 
1847*8d67ca89SAndroid Build Coastguard Worker #ifdef ckd_add
1848*8d67ca89SAndroid Build Coastguard Worker 	if (ckd_add(&tmp->tm_year, y, -TM_YEAR_BASE)) {
1849*8d67ca89SAndroid Build Coastguard Worker 	  errno = EOVERFLOW;
1850*8d67ca89SAndroid Build Coastguard Worker 	  return NULL;
1851*8d67ca89SAndroid Build Coastguard Worker 	}
1852*8d67ca89SAndroid Build Coastguard Worker #else
1853*8d67ca89SAndroid Build Coastguard Worker 	if (!TYPE_SIGNED(time_t) && y < TM_YEAR_BASE) {
1854*8d67ca89SAndroid Build Coastguard Worker 	  int signed_y = y;
1855*8d67ca89SAndroid Build Coastguard Worker 	  tmp->tm_year = signed_y - TM_YEAR_BASE;
1856*8d67ca89SAndroid Build Coastguard Worker 	} else if ((!TYPE_SIGNED(time_t) || INT_MIN + TM_YEAR_BASE <= y)
1857*8d67ca89SAndroid Build Coastguard Worker 		   && y - TM_YEAR_BASE <= INT_MAX)
1858*8d67ca89SAndroid Build Coastguard Worker 	  tmp->tm_year = y - TM_YEAR_BASE;
1859*8d67ca89SAndroid Build Coastguard Worker 	else {
1860*8d67ca89SAndroid Build Coastguard Worker 	  errno = EOVERFLOW;
1861*8d67ca89SAndroid Build Coastguard Worker 	  return NULL;
1862*8d67ca89SAndroid Build Coastguard Worker 	}
1863*8d67ca89SAndroid Build Coastguard Worker #endif
1864*8d67ca89SAndroid Build Coastguard Worker 	tmp->tm_yday = idays;
1865*8d67ca89SAndroid Build Coastguard Worker 	/*
1866*8d67ca89SAndroid Build Coastguard Worker 	** The "extra" mods below avoid overflow problems.
1867*8d67ca89SAndroid Build Coastguard Worker 	*/
1868*8d67ca89SAndroid Build Coastguard Worker 	tmp->tm_wday = (TM_WDAY_BASE
1869*8d67ca89SAndroid Build Coastguard Worker 			+ ((tmp->tm_year % DAYSPERWEEK)
1870*8d67ca89SAndroid Build Coastguard Worker 			   * (DAYSPERNYEAR % DAYSPERWEEK))
1871*8d67ca89SAndroid Build Coastguard Worker 			+ leaps_thru_end_of(y - 1)
1872*8d67ca89SAndroid Build Coastguard Worker 			- leaps_thru_end_of(TM_YEAR_BASE - 1)
1873*8d67ca89SAndroid Build Coastguard Worker 			+ idays);
1874*8d67ca89SAndroid Build Coastguard Worker 	tmp->tm_wday %= DAYSPERWEEK;
1875*8d67ca89SAndroid Build Coastguard Worker 	if (tmp->tm_wday < 0)
1876*8d67ca89SAndroid Build Coastguard Worker 		tmp->tm_wday += DAYSPERWEEK;
1877*8d67ca89SAndroid Build Coastguard Worker 	tmp->tm_hour = rem / SECSPERHOUR;
1878*8d67ca89SAndroid Build Coastguard Worker 	rem %= SECSPERHOUR;
1879*8d67ca89SAndroid Build Coastguard Worker 	tmp->tm_min = rem / SECSPERMIN;
1880*8d67ca89SAndroid Build Coastguard Worker 	tmp->tm_sec = rem % SECSPERMIN;
1881*8d67ca89SAndroid Build Coastguard Worker 
1882*8d67ca89SAndroid Build Coastguard Worker 	/* Use "... ??:??:60" at the end of the localtime minute containing
1883*8d67ca89SAndroid Build Coastguard Worker 	   the second just before the positive leap second.  */
1884*8d67ca89SAndroid Build Coastguard Worker 	tmp->tm_sec += secs_since_posleap <= tmp->tm_sec;
1885*8d67ca89SAndroid Build Coastguard Worker 
1886*8d67ca89SAndroid Build Coastguard Worker 	ip = mon_lengths[isleap(y)];
1887*8d67ca89SAndroid Build Coastguard Worker 	for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1888*8d67ca89SAndroid Build Coastguard Worker 		idays -= ip[tmp->tm_mon];
1889*8d67ca89SAndroid Build Coastguard Worker 	tmp->tm_mday = idays + 1;
1890*8d67ca89SAndroid Build Coastguard Worker 	tmp->tm_isdst = 0;
1891*8d67ca89SAndroid Build Coastguard Worker #ifdef TM_GMTOFF
1892*8d67ca89SAndroid Build Coastguard Worker 	tmp->TM_GMTOFF = offset;
1893*8d67ca89SAndroid Build Coastguard Worker #endif /* defined TM_GMTOFF */
1894*8d67ca89SAndroid Build Coastguard Worker 	return tmp;
1895*8d67ca89SAndroid Build Coastguard Worker }
1896*8d67ca89SAndroid Build Coastguard Worker 
1897*8d67ca89SAndroid Build Coastguard Worker /*
1898*8d67ca89SAndroid Build Coastguard Worker ** Adapted from code provided by Robert Elz, who writes:
1899*8d67ca89SAndroid Build Coastguard Worker **	The "best" way to do mktime I think is based on an idea of Bob
1900*8d67ca89SAndroid Build Coastguard Worker **	Kridle's (so its said...) from a long time ago.
1901*8d67ca89SAndroid Build Coastguard Worker **	It does a binary search of the time_t space. Since time_t's are
1902*8d67ca89SAndroid Build Coastguard Worker **	just 32 bits, its a max of 32 iterations (even at 64 bits it
1903*8d67ca89SAndroid Build Coastguard Worker **	would still be very reasonable).
1904*8d67ca89SAndroid Build Coastguard Worker */
1905*8d67ca89SAndroid Build Coastguard Worker 
1906*8d67ca89SAndroid Build Coastguard Worker #ifndef WRONG
1907*8d67ca89SAndroid Build Coastguard Worker # define WRONG (-1)
1908*8d67ca89SAndroid Build Coastguard Worker #endif /* !defined WRONG */
1909*8d67ca89SAndroid Build Coastguard Worker 
1910*8d67ca89SAndroid Build Coastguard Worker /*
1911*8d67ca89SAndroid Build Coastguard Worker ** Normalize logic courtesy Paul Eggert.
1912*8d67ca89SAndroid Build Coastguard Worker */
1913*8d67ca89SAndroid Build Coastguard Worker 
1914*8d67ca89SAndroid Build Coastguard Worker static bool
increment_overflow(int * ip,int j)1915*8d67ca89SAndroid Build Coastguard Worker increment_overflow(int *ip, int j)
1916*8d67ca89SAndroid Build Coastguard Worker {
1917*8d67ca89SAndroid Build Coastguard Worker #ifdef ckd_add
1918*8d67ca89SAndroid Build Coastguard Worker 	return ckd_add(ip, *ip, j);
1919*8d67ca89SAndroid Build Coastguard Worker #else
1920*8d67ca89SAndroid Build Coastguard Worker 	register int const	i = *ip;
1921*8d67ca89SAndroid Build Coastguard Worker 
1922*8d67ca89SAndroid Build Coastguard Worker 	/*
1923*8d67ca89SAndroid Build Coastguard Worker 	** If i >= 0 there can only be overflow if i + j > INT_MAX
1924*8d67ca89SAndroid Build Coastguard Worker 	** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1925*8d67ca89SAndroid Build Coastguard Worker 	** If i < 0 there can only be overflow if i + j < INT_MIN
1926*8d67ca89SAndroid Build Coastguard Worker 	** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1927*8d67ca89SAndroid Build Coastguard Worker 	*/
1928*8d67ca89SAndroid Build Coastguard Worker 	if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
1929*8d67ca89SAndroid Build Coastguard Worker 		return true;
1930*8d67ca89SAndroid Build Coastguard Worker 	*ip += j;
1931*8d67ca89SAndroid Build Coastguard Worker 	return false;
1932*8d67ca89SAndroid Build Coastguard Worker #endif
1933*8d67ca89SAndroid Build Coastguard Worker }
1934*8d67ca89SAndroid Build Coastguard Worker 
1935*8d67ca89SAndroid Build Coastguard Worker static bool
increment_overflow32(int_fast32_t * const lp,int const m)1936*8d67ca89SAndroid Build Coastguard Worker increment_overflow32(int_fast32_t *const lp, int const m)
1937*8d67ca89SAndroid Build Coastguard Worker {
1938*8d67ca89SAndroid Build Coastguard Worker #ifdef ckd_add
1939*8d67ca89SAndroid Build Coastguard Worker 	return ckd_add(lp, *lp, m);
1940*8d67ca89SAndroid Build Coastguard Worker #else
1941*8d67ca89SAndroid Build Coastguard Worker 	register int_fast32_t const	l = *lp;
1942*8d67ca89SAndroid Build Coastguard Worker 
1943*8d67ca89SAndroid Build Coastguard Worker 	if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
1944*8d67ca89SAndroid Build Coastguard Worker 		return true;
1945*8d67ca89SAndroid Build Coastguard Worker 	*lp += m;
1946*8d67ca89SAndroid Build Coastguard Worker 	return false;
1947*8d67ca89SAndroid Build Coastguard Worker #endif
1948*8d67ca89SAndroid Build Coastguard Worker }
1949*8d67ca89SAndroid Build Coastguard Worker 
1950*8d67ca89SAndroid Build Coastguard Worker static bool
increment_overflow_time(time_t * tp,int_fast32_t j)1951*8d67ca89SAndroid Build Coastguard Worker increment_overflow_time(time_t *tp, int_fast32_t j)
1952*8d67ca89SAndroid Build Coastguard Worker {
1953*8d67ca89SAndroid Build Coastguard Worker #ifdef ckd_add
1954*8d67ca89SAndroid Build Coastguard Worker 	return ckd_add(tp, *tp, j);
1955*8d67ca89SAndroid Build Coastguard Worker #else
1956*8d67ca89SAndroid Build Coastguard Worker 	/*
1957*8d67ca89SAndroid Build Coastguard Worker 	** This is like
1958*8d67ca89SAndroid Build Coastguard Worker 	** 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
1959*8d67ca89SAndroid Build Coastguard Worker 	** except that it does the right thing even if *tp + j would overflow.
1960*8d67ca89SAndroid Build Coastguard Worker 	*/
1961*8d67ca89SAndroid Build Coastguard Worker 	if (! (j < 0
1962*8d67ca89SAndroid Build Coastguard Worker 	       ? (TYPE_SIGNED(time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
1963*8d67ca89SAndroid Build Coastguard Worker 	       : *tp <= TIME_T_MAX - j))
1964*8d67ca89SAndroid Build Coastguard Worker 		return true;
1965*8d67ca89SAndroid Build Coastguard Worker 	*tp += j;
1966*8d67ca89SAndroid Build Coastguard Worker 	return false;
1967*8d67ca89SAndroid Build Coastguard Worker #endif
1968*8d67ca89SAndroid Build Coastguard Worker }
1969*8d67ca89SAndroid Build Coastguard Worker 
1970*8d67ca89SAndroid Build Coastguard Worker static bool
normalize_overflow(int * const tensptr,int * const unitsptr,const int base)1971*8d67ca89SAndroid Build Coastguard Worker normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
1972*8d67ca89SAndroid Build Coastguard Worker {
1973*8d67ca89SAndroid Build Coastguard Worker 	register int	tensdelta;
1974*8d67ca89SAndroid Build Coastguard Worker 
1975*8d67ca89SAndroid Build Coastguard Worker 	tensdelta = (*unitsptr >= 0) ?
1976*8d67ca89SAndroid Build Coastguard Worker 		(*unitsptr / base) :
1977*8d67ca89SAndroid Build Coastguard Worker 		(-1 - (-1 - *unitsptr) / base);
1978*8d67ca89SAndroid Build Coastguard Worker 	*unitsptr -= tensdelta * base;
1979*8d67ca89SAndroid Build Coastguard Worker 	return increment_overflow(tensptr, tensdelta);
1980*8d67ca89SAndroid Build Coastguard Worker }
1981*8d67ca89SAndroid Build Coastguard Worker 
1982*8d67ca89SAndroid Build Coastguard Worker static bool
normalize_overflow32(int_fast32_t * tensptr,int * unitsptr,int base)1983*8d67ca89SAndroid Build Coastguard Worker normalize_overflow32(int_fast32_t *tensptr, int *unitsptr, int base)
1984*8d67ca89SAndroid Build Coastguard Worker {
1985*8d67ca89SAndroid Build Coastguard Worker 	register int	tensdelta;
1986*8d67ca89SAndroid Build Coastguard Worker 
1987*8d67ca89SAndroid Build Coastguard Worker 	tensdelta = (*unitsptr >= 0) ?
1988*8d67ca89SAndroid Build Coastguard Worker 		(*unitsptr / base) :
1989*8d67ca89SAndroid Build Coastguard Worker 		(-1 - (-1 - *unitsptr) / base);
1990*8d67ca89SAndroid Build Coastguard Worker 	*unitsptr -= tensdelta * base;
1991*8d67ca89SAndroid Build Coastguard Worker 	return increment_overflow32(tensptr, tensdelta);
1992*8d67ca89SAndroid Build Coastguard Worker }
1993*8d67ca89SAndroid Build Coastguard Worker 
1994*8d67ca89SAndroid Build Coastguard Worker static int
tmcomp(register const struct tm * const atmp,register const struct tm * const btmp)1995*8d67ca89SAndroid Build Coastguard Worker tmcomp(register const struct tm *const atmp,
1996*8d67ca89SAndroid Build Coastguard Worker        register const struct tm *const btmp)
1997*8d67ca89SAndroid Build Coastguard Worker {
1998*8d67ca89SAndroid Build Coastguard Worker 	register int	result;
1999*8d67ca89SAndroid Build Coastguard Worker 
2000*8d67ca89SAndroid Build Coastguard Worker 	if (atmp->tm_year != btmp->tm_year)
2001*8d67ca89SAndroid Build Coastguard Worker 		return atmp->tm_year < btmp->tm_year ? -1 : 1;
2002*8d67ca89SAndroid Build Coastguard Worker 	if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
2003*8d67ca89SAndroid Build Coastguard Worker 		(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
2004*8d67ca89SAndroid Build Coastguard Worker 		(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
2005*8d67ca89SAndroid Build Coastguard Worker 		(result = (atmp->tm_min - btmp->tm_min)) == 0)
2006*8d67ca89SAndroid Build Coastguard Worker 			result = atmp->tm_sec - btmp->tm_sec;
2007*8d67ca89SAndroid Build Coastguard Worker 	return result;
2008*8d67ca89SAndroid Build Coastguard Worker }
2009*8d67ca89SAndroid Build Coastguard Worker 
2010*8d67ca89SAndroid Build Coastguard Worker /* Copy to *DEST from *SRC.  Copy only the members needed for mktime,
2011*8d67ca89SAndroid Build Coastguard Worker    as other members might not be initialized.  */
2012*8d67ca89SAndroid Build Coastguard Worker static void
mktmcpy(struct tm * dest,struct tm const * src)2013*8d67ca89SAndroid Build Coastguard Worker mktmcpy(struct tm *dest, struct tm const *src)
2014*8d67ca89SAndroid Build Coastguard Worker {
2015*8d67ca89SAndroid Build Coastguard Worker   dest->tm_sec = src->tm_sec;
2016*8d67ca89SAndroid Build Coastguard Worker   dest->tm_min = src->tm_min;
2017*8d67ca89SAndroid Build Coastguard Worker   dest->tm_hour = src->tm_hour;
2018*8d67ca89SAndroid Build Coastguard Worker   dest->tm_mday = src->tm_mday;
2019*8d67ca89SAndroid Build Coastguard Worker   dest->tm_mon = src->tm_mon;
2020*8d67ca89SAndroid Build Coastguard Worker   dest->tm_year = src->tm_year;
2021*8d67ca89SAndroid Build Coastguard Worker   dest->tm_isdst = src->tm_isdst;
2022*8d67ca89SAndroid Build Coastguard Worker #if defined TM_GMTOFF && ! UNINIT_TRAP
2023*8d67ca89SAndroid Build Coastguard Worker   dest->TM_GMTOFF = src->TM_GMTOFF;
2024*8d67ca89SAndroid Build Coastguard Worker #endif
2025*8d67ca89SAndroid Build Coastguard Worker }
2026*8d67ca89SAndroid Build Coastguard Worker 
2027*8d67ca89SAndroid Build Coastguard Worker static time_t
time2sub(struct tm * const tmp,struct tm * (* funcp)(struct state const *,time_t const *,int_fast32_t,struct tm *),struct state const * sp,const int_fast32_t offset,bool * okayp,bool do_norm_secs)2028*8d67ca89SAndroid Build Coastguard Worker time2sub(struct tm *const tmp,
2029*8d67ca89SAndroid Build Coastguard Worker 	 struct tm *(*funcp)(struct state const *, time_t const *,
2030*8d67ca89SAndroid Build Coastguard Worker 			     int_fast32_t, struct tm *),
2031*8d67ca89SAndroid Build Coastguard Worker 	 struct state const *sp,
2032*8d67ca89SAndroid Build Coastguard Worker 	 const int_fast32_t offset,
2033*8d67ca89SAndroid Build Coastguard Worker 	 bool *okayp,
2034*8d67ca89SAndroid Build Coastguard Worker 	 bool do_norm_secs)
2035*8d67ca89SAndroid Build Coastguard Worker {
2036*8d67ca89SAndroid Build Coastguard Worker 	register int			dir;
2037*8d67ca89SAndroid Build Coastguard Worker 	register int			i, j;
2038*8d67ca89SAndroid Build Coastguard Worker 	register int			saved_seconds;
2039*8d67ca89SAndroid Build Coastguard Worker 	register int_fast32_t		li;
2040*8d67ca89SAndroid Build Coastguard Worker 	register time_t			lo;
2041*8d67ca89SAndroid Build Coastguard Worker 	register time_t			hi;
2042*8d67ca89SAndroid Build Coastguard Worker 	int_fast32_t			y;
2043*8d67ca89SAndroid Build Coastguard Worker 	time_t				newt;
2044*8d67ca89SAndroid Build Coastguard Worker 	time_t				t;
2045*8d67ca89SAndroid Build Coastguard Worker 	struct tm			yourtm, mytm;
2046*8d67ca89SAndroid Build Coastguard Worker 
2047*8d67ca89SAndroid Build Coastguard Worker 	*okayp = false;
2048*8d67ca89SAndroid Build Coastguard Worker 	mktmcpy(&yourtm, tmp);
2049*8d67ca89SAndroid Build Coastguard Worker 
2050*8d67ca89SAndroid Build Coastguard Worker 	if (do_norm_secs) {
2051*8d67ca89SAndroid Build Coastguard Worker 		if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
2052*8d67ca89SAndroid Build Coastguard Worker 			SECSPERMIN))
2053*8d67ca89SAndroid Build Coastguard Worker 				return WRONG;
2054*8d67ca89SAndroid Build Coastguard Worker 	}
2055*8d67ca89SAndroid Build Coastguard Worker 	if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
2056*8d67ca89SAndroid Build Coastguard Worker 		return WRONG;
2057*8d67ca89SAndroid Build Coastguard Worker 	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
2058*8d67ca89SAndroid Build Coastguard Worker 		return WRONG;
2059*8d67ca89SAndroid Build Coastguard Worker 	y = yourtm.tm_year;
2060*8d67ca89SAndroid Build Coastguard Worker 	if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
2061*8d67ca89SAndroid Build Coastguard Worker 		return WRONG;
2062*8d67ca89SAndroid Build Coastguard Worker 	/*
2063*8d67ca89SAndroid Build Coastguard Worker 	** Turn y into an actual year number for now.
2064*8d67ca89SAndroid Build Coastguard Worker 	** It is converted back to an offset from TM_YEAR_BASE later.
2065*8d67ca89SAndroid Build Coastguard Worker 	*/
2066*8d67ca89SAndroid Build Coastguard Worker 	if (increment_overflow32(&y, TM_YEAR_BASE))
2067*8d67ca89SAndroid Build Coastguard Worker 		return WRONG;
2068*8d67ca89SAndroid Build Coastguard Worker 	while (yourtm.tm_mday <= 0) {
2069*8d67ca89SAndroid Build Coastguard Worker 		if (increment_overflow32(&y, -1))
2070*8d67ca89SAndroid Build Coastguard Worker 			return WRONG;
2071*8d67ca89SAndroid Build Coastguard Worker 		li = y + (1 < yourtm.tm_mon);
2072*8d67ca89SAndroid Build Coastguard Worker 		yourtm.tm_mday += year_lengths[isleap(li)];
2073*8d67ca89SAndroid Build Coastguard Worker 	}
2074*8d67ca89SAndroid Build Coastguard Worker 	while (yourtm.tm_mday > DAYSPERLYEAR) {
2075*8d67ca89SAndroid Build Coastguard Worker 		li = y + (1 < yourtm.tm_mon);
2076*8d67ca89SAndroid Build Coastguard Worker 		yourtm.tm_mday -= year_lengths[isleap(li)];
2077*8d67ca89SAndroid Build Coastguard Worker 		if (increment_overflow32(&y, 1))
2078*8d67ca89SAndroid Build Coastguard Worker 			return WRONG;
2079*8d67ca89SAndroid Build Coastguard Worker 	}
2080*8d67ca89SAndroid Build Coastguard Worker 	for ( ; ; ) {
2081*8d67ca89SAndroid Build Coastguard Worker 		i = mon_lengths[isleap(y)][yourtm.tm_mon];
2082*8d67ca89SAndroid Build Coastguard Worker 		if (yourtm.tm_mday <= i)
2083*8d67ca89SAndroid Build Coastguard Worker 			break;
2084*8d67ca89SAndroid Build Coastguard Worker 		yourtm.tm_mday -= i;
2085*8d67ca89SAndroid Build Coastguard Worker 		if (++yourtm.tm_mon >= MONSPERYEAR) {
2086*8d67ca89SAndroid Build Coastguard Worker 			yourtm.tm_mon = 0;
2087*8d67ca89SAndroid Build Coastguard Worker 			if (increment_overflow32(&y, 1))
2088*8d67ca89SAndroid Build Coastguard Worker 				return WRONG;
2089*8d67ca89SAndroid Build Coastguard Worker 		}
2090*8d67ca89SAndroid Build Coastguard Worker 	}
2091*8d67ca89SAndroid Build Coastguard Worker #ifdef ckd_add
2092*8d67ca89SAndroid Build Coastguard Worker 	if (ckd_add(&yourtm.tm_year, y, -TM_YEAR_BASE))
2093*8d67ca89SAndroid Build Coastguard Worker 	  return WRONG;
2094*8d67ca89SAndroid Build Coastguard Worker #else
2095*8d67ca89SAndroid Build Coastguard Worker 	if (increment_overflow32(&y, -TM_YEAR_BASE))
2096*8d67ca89SAndroid Build Coastguard Worker 		return WRONG;
2097*8d67ca89SAndroid Build Coastguard Worker 	if (! (INT_MIN <= y && y <= INT_MAX))
2098*8d67ca89SAndroid Build Coastguard Worker 		return WRONG;
2099*8d67ca89SAndroid Build Coastguard Worker 	yourtm.tm_year = y;
2100*8d67ca89SAndroid Build Coastguard Worker #endif
2101*8d67ca89SAndroid Build Coastguard Worker 	if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
2102*8d67ca89SAndroid Build Coastguard Worker 		saved_seconds = 0;
2103*8d67ca89SAndroid Build Coastguard Worker 	else if (yourtm.tm_year < EPOCH_YEAR - TM_YEAR_BASE) {
2104*8d67ca89SAndroid Build Coastguard Worker 		/*
2105*8d67ca89SAndroid Build Coastguard Worker 		** We can't set tm_sec to 0, because that might push the
2106*8d67ca89SAndroid Build Coastguard Worker 		** time below the minimum representable time.
2107*8d67ca89SAndroid Build Coastguard Worker 		** Set tm_sec to 59 instead.
2108*8d67ca89SAndroid Build Coastguard Worker 		** This assumes that the minimum representable time is
2109*8d67ca89SAndroid Build Coastguard Worker 		** not in the same minute that a leap second was deleted from,
2110*8d67ca89SAndroid Build Coastguard Worker 		** which is a safer assumption than using 58 would be.
2111*8d67ca89SAndroid Build Coastguard Worker 		*/
2112*8d67ca89SAndroid Build Coastguard Worker 		if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
2113*8d67ca89SAndroid Build Coastguard Worker 			return WRONG;
2114*8d67ca89SAndroid Build Coastguard Worker 		saved_seconds = yourtm.tm_sec;
2115*8d67ca89SAndroid Build Coastguard Worker 		yourtm.tm_sec = SECSPERMIN - 1;
2116*8d67ca89SAndroid Build Coastguard Worker 	} else {
2117*8d67ca89SAndroid Build Coastguard Worker 		saved_seconds = yourtm.tm_sec;
2118*8d67ca89SAndroid Build Coastguard Worker 		yourtm.tm_sec = 0;
2119*8d67ca89SAndroid Build Coastguard Worker 	}
2120*8d67ca89SAndroid Build Coastguard Worker 	/*
2121*8d67ca89SAndroid Build Coastguard Worker 	** Do a binary search (this works whatever time_t's type is).
2122*8d67ca89SAndroid Build Coastguard Worker 	*/
2123*8d67ca89SAndroid Build Coastguard Worker 	lo = TIME_T_MIN;
2124*8d67ca89SAndroid Build Coastguard Worker 	hi = TIME_T_MAX;
2125*8d67ca89SAndroid Build Coastguard Worker 	for ( ; ; ) {
2126*8d67ca89SAndroid Build Coastguard Worker 		t = lo / 2 + hi / 2;
2127*8d67ca89SAndroid Build Coastguard Worker 		if (t < lo)
2128*8d67ca89SAndroid Build Coastguard Worker 			t = lo;
2129*8d67ca89SAndroid Build Coastguard Worker 		else if (t > hi)
2130*8d67ca89SAndroid Build Coastguard Worker 			t = hi;
2131*8d67ca89SAndroid Build Coastguard Worker 		if (! funcp(sp, &t, offset, &mytm)) {
2132*8d67ca89SAndroid Build Coastguard Worker 			/*
2133*8d67ca89SAndroid Build Coastguard Worker 			** Assume that t is too extreme to be represented in
2134*8d67ca89SAndroid Build Coastguard Worker 			** a struct tm; arrange things so that it is less
2135*8d67ca89SAndroid Build Coastguard Worker 			** extreme on the next pass.
2136*8d67ca89SAndroid Build Coastguard Worker 			*/
2137*8d67ca89SAndroid Build Coastguard Worker 			dir = (t > 0) ? 1 : -1;
2138*8d67ca89SAndroid Build Coastguard Worker 		} else	dir = tmcomp(&mytm, &yourtm);
2139*8d67ca89SAndroid Build Coastguard Worker 		if (dir != 0) {
2140*8d67ca89SAndroid Build Coastguard Worker 			if (t == lo) {
2141*8d67ca89SAndroid Build Coastguard Worker 				if (t == TIME_T_MAX)
2142*8d67ca89SAndroid Build Coastguard Worker 					return WRONG;
2143*8d67ca89SAndroid Build Coastguard Worker 				++t;
2144*8d67ca89SAndroid Build Coastguard Worker 				++lo;
2145*8d67ca89SAndroid Build Coastguard Worker 			} else if (t == hi) {
2146*8d67ca89SAndroid Build Coastguard Worker 				if (t == TIME_T_MIN)
2147*8d67ca89SAndroid Build Coastguard Worker 					return WRONG;
2148*8d67ca89SAndroid Build Coastguard Worker 				--t;
2149*8d67ca89SAndroid Build Coastguard Worker 				--hi;
2150*8d67ca89SAndroid Build Coastguard Worker 			}
2151*8d67ca89SAndroid Build Coastguard Worker 			if (lo > hi)
2152*8d67ca89SAndroid Build Coastguard Worker 				return WRONG;
2153*8d67ca89SAndroid Build Coastguard Worker 			if (dir > 0)
2154*8d67ca89SAndroid Build Coastguard Worker 				hi = t;
2155*8d67ca89SAndroid Build Coastguard Worker 			else	lo = t;
2156*8d67ca89SAndroid Build Coastguard Worker 			continue;
2157*8d67ca89SAndroid Build Coastguard Worker 		}
2158*8d67ca89SAndroid Build Coastguard Worker #if defined TM_GMTOFF && ! UNINIT_TRAP
2159*8d67ca89SAndroid Build Coastguard Worker 		if (mytm.TM_GMTOFF != yourtm.TM_GMTOFF
2160*8d67ca89SAndroid Build Coastguard Worker 		    && (yourtm.TM_GMTOFF < 0
2161*8d67ca89SAndroid Build Coastguard Worker 			? (-SECSPERDAY <= yourtm.TM_GMTOFF
2162*8d67ca89SAndroid Build Coastguard Worker 			   && (mytm.TM_GMTOFF <=
2163*8d67ca89SAndroid Build Coastguard Worker 			       (min(INT_FAST32_MAX, LONG_MAX)
2164*8d67ca89SAndroid Build Coastguard Worker 				+ yourtm.TM_GMTOFF)))
2165*8d67ca89SAndroid Build Coastguard Worker 			: (yourtm.TM_GMTOFF <= SECSPERDAY
2166*8d67ca89SAndroid Build Coastguard Worker 			   && ((max(INT_FAST32_MIN, LONG_MIN)
2167*8d67ca89SAndroid Build Coastguard Worker 				+ yourtm.TM_GMTOFF)
2168*8d67ca89SAndroid Build Coastguard Worker 			       <= mytm.TM_GMTOFF)))) {
2169*8d67ca89SAndroid Build Coastguard Worker 		  /* MYTM matches YOURTM except with the wrong UT offset.
2170*8d67ca89SAndroid Build Coastguard Worker 		     YOURTM.TM_GMTOFF is plausible, so try it instead.
2171*8d67ca89SAndroid Build Coastguard Worker 		     It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
2172*8d67ca89SAndroid Build Coastguard Worker 		     since the guess gets checked.  */
2173*8d67ca89SAndroid Build Coastguard Worker 		  time_t altt = t;
2174*8d67ca89SAndroid Build Coastguard Worker 		  int_fast32_t diff = mytm.TM_GMTOFF - yourtm.TM_GMTOFF;
2175*8d67ca89SAndroid Build Coastguard Worker 		  if (!increment_overflow_time(&altt, diff)) {
2176*8d67ca89SAndroid Build Coastguard Worker 		    struct tm alttm;
2177*8d67ca89SAndroid Build Coastguard Worker 		    if (funcp(sp, &altt, offset, &alttm)
2178*8d67ca89SAndroid Build Coastguard Worker 			&& alttm.tm_isdst == mytm.tm_isdst
2179*8d67ca89SAndroid Build Coastguard Worker 			&& alttm.TM_GMTOFF == yourtm.TM_GMTOFF
2180*8d67ca89SAndroid Build Coastguard Worker 			&& tmcomp(&alttm, &yourtm) == 0) {
2181*8d67ca89SAndroid Build Coastguard Worker 		      t = altt;
2182*8d67ca89SAndroid Build Coastguard Worker 		      mytm = alttm;
2183*8d67ca89SAndroid Build Coastguard Worker 		    }
2184*8d67ca89SAndroid Build Coastguard Worker 		  }
2185*8d67ca89SAndroid Build Coastguard Worker 		}
2186*8d67ca89SAndroid Build Coastguard Worker #endif
2187*8d67ca89SAndroid Build Coastguard Worker 		if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
2188*8d67ca89SAndroid Build Coastguard Worker 			break;
2189*8d67ca89SAndroid Build Coastguard Worker 		/*
2190*8d67ca89SAndroid Build Coastguard Worker 		** Right time, wrong type.
2191*8d67ca89SAndroid Build Coastguard Worker 		** Hunt for right time, right type.
2192*8d67ca89SAndroid Build Coastguard Worker 		** It's okay to guess wrong since the guess
2193*8d67ca89SAndroid Build Coastguard Worker 		** gets checked.
2194*8d67ca89SAndroid Build Coastguard Worker 		*/
2195*8d67ca89SAndroid Build Coastguard Worker 		if (sp == NULL)
2196*8d67ca89SAndroid Build Coastguard Worker 			return WRONG;
2197*8d67ca89SAndroid Build Coastguard Worker 		for (i = sp->typecnt - 1; i >= 0; --i) {
2198*8d67ca89SAndroid Build Coastguard Worker 			if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
2199*8d67ca89SAndroid Build Coastguard Worker 				continue;
2200*8d67ca89SAndroid Build Coastguard Worker 			for (j = sp->typecnt - 1; j >= 0; --j) {
2201*8d67ca89SAndroid Build Coastguard Worker 				if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
2202*8d67ca89SAndroid Build Coastguard Worker 					continue;
2203*8d67ca89SAndroid Build Coastguard Worker 				if (ttunspecified(sp, j))
2204*8d67ca89SAndroid Build Coastguard Worker 				  continue;
2205*8d67ca89SAndroid Build Coastguard Worker 				newt = (t + sp->ttis[j].tt_utoff
2206*8d67ca89SAndroid Build Coastguard Worker 					- sp->ttis[i].tt_utoff);
2207*8d67ca89SAndroid Build Coastguard Worker 				if (! funcp(sp, &newt, offset, &mytm))
2208*8d67ca89SAndroid Build Coastguard Worker 					continue;
2209*8d67ca89SAndroid Build Coastguard Worker 				if (tmcomp(&mytm, &yourtm) != 0)
2210*8d67ca89SAndroid Build Coastguard Worker 					continue;
2211*8d67ca89SAndroid Build Coastguard Worker 				if (mytm.tm_isdst != yourtm.tm_isdst)
2212*8d67ca89SAndroid Build Coastguard Worker 					continue;
2213*8d67ca89SAndroid Build Coastguard Worker 				/*
2214*8d67ca89SAndroid Build Coastguard Worker 				** We have a match.
2215*8d67ca89SAndroid Build Coastguard Worker 				*/
2216*8d67ca89SAndroid Build Coastguard Worker 				t = newt;
2217*8d67ca89SAndroid Build Coastguard Worker 				goto label;
2218*8d67ca89SAndroid Build Coastguard Worker 			}
2219*8d67ca89SAndroid Build Coastguard Worker 		}
2220*8d67ca89SAndroid Build Coastguard Worker 		return WRONG;
2221*8d67ca89SAndroid Build Coastguard Worker 	}
2222*8d67ca89SAndroid Build Coastguard Worker label:
2223*8d67ca89SAndroid Build Coastguard Worker 	newt = t + saved_seconds;
2224*8d67ca89SAndroid Build Coastguard Worker 	if ((newt < t) != (saved_seconds < 0))
2225*8d67ca89SAndroid Build Coastguard Worker 		return WRONG;
2226*8d67ca89SAndroid Build Coastguard Worker 	t = newt;
2227*8d67ca89SAndroid Build Coastguard Worker 	if (funcp(sp, &t, offset, tmp))
2228*8d67ca89SAndroid Build Coastguard Worker 		*okayp = true;
2229*8d67ca89SAndroid Build Coastguard Worker 	return t;
2230*8d67ca89SAndroid Build Coastguard Worker }
2231*8d67ca89SAndroid Build Coastguard Worker 
2232*8d67ca89SAndroid Build Coastguard Worker static time_t
time2(struct tm * const tmp,struct tm * (* funcp)(struct state const *,time_t const *,int_fast32_t,struct tm *),struct state const * sp,const int_fast32_t offset,bool * okayp)2233*8d67ca89SAndroid Build Coastguard Worker time2(struct tm * const	tmp,
2234*8d67ca89SAndroid Build Coastguard Worker       struct tm *(*funcp)(struct state const *, time_t const *,
2235*8d67ca89SAndroid Build Coastguard Worker 			  int_fast32_t, struct tm *),
2236*8d67ca89SAndroid Build Coastguard Worker       struct state const *sp,
2237*8d67ca89SAndroid Build Coastguard Worker       const int_fast32_t offset,
2238*8d67ca89SAndroid Build Coastguard Worker       bool *okayp)
2239*8d67ca89SAndroid Build Coastguard Worker {
2240*8d67ca89SAndroid Build Coastguard Worker 	time_t	t;
2241*8d67ca89SAndroid Build Coastguard Worker 
2242*8d67ca89SAndroid Build Coastguard Worker 	/*
2243*8d67ca89SAndroid Build Coastguard Worker 	** First try without normalization of seconds
2244*8d67ca89SAndroid Build Coastguard Worker 	** (in case tm_sec contains a value associated with a leap second).
2245*8d67ca89SAndroid Build Coastguard Worker 	** If that fails, try with normalization of seconds.
2246*8d67ca89SAndroid Build Coastguard Worker 	*/
2247*8d67ca89SAndroid Build Coastguard Worker 	t = time2sub(tmp, funcp, sp, offset, okayp, false);
2248*8d67ca89SAndroid Build Coastguard Worker 	return *okayp ? t : time2sub(tmp, funcp, sp, offset, okayp, true);
2249*8d67ca89SAndroid Build Coastguard Worker }
2250*8d67ca89SAndroid Build Coastguard Worker 
2251*8d67ca89SAndroid Build Coastguard Worker static time_t
time1(struct tm * const tmp,struct tm * (* funcp)(struct state const *,time_t const *,int_fast32_t,struct tm *),struct state const * sp,const int_fast32_t offset)2252*8d67ca89SAndroid Build Coastguard Worker time1(struct tm *const tmp,
2253*8d67ca89SAndroid Build Coastguard Worker       struct tm *(*funcp)(struct state const *, time_t const *,
2254*8d67ca89SAndroid Build Coastguard Worker 			  int_fast32_t, struct tm *),
2255*8d67ca89SAndroid Build Coastguard Worker       struct state const *sp,
2256*8d67ca89SAndroid Build Coastguard Worker       const int_fast32_t offset)
2257*8d67ca89SAndroid Build Coastguard Worker {
2258*8d67ca89SAndroid Build Coastguard Worker 	register time_t			t;
2259*8d67ca89SAndroid Build Coastguard Worker 	register int			samei, otheri;
2260*8d67ca89SAndroid Build Coastguard Worker 	register int			sameind, otherind;
2261*8d67ca89SAndroid Build Coastguard Worker 	register int			i;
2262*8d67ca89SAndroid Build Coastguard Worker 	register int			nseen;
2263*8d67ca89SAndroid Build Coastguard Worker 	char				seen[TZ_MAX_TYPES];
2264*8d67ca89SAndroid Build Coastguard Worker 	unsigned char			types[TZ_MAX_TYPES];
2265*8d67ca89SAndroid Build Coastguard Worker 	bool				okay;
2266*8d67ca89SAndroid Build Coastguard Worker 
2267*8d67ca89SAndroid Build Coastguard Worker 	if (tmp == NULL) {
2268*8d67ca89SAndroid Build Coastguard Worker 		errno = EINVAL;
2269*8d67ca89SAndroid Build Coastguard Worker 		return WRONG;
2270*8d67ca89SAndroid Build Coastguard Worker 	}
2271*8d67ca89SAndroid Build Coastguard Worker 	if (tmp->tm_isdst > 1)
2272*8d67ca89SAndroid Build Coastguard Worker 		tmp->tm_isdst = 1;
2273*8d67ca89SAndroid Build Coastguard Worker 	t = time2(tmp, funcp, sp, offset, &okay);
2274*8d67ca89SAndroid Build Coastguard Worker 	if (okay)
2275*8d67ca89SAndroid Build Coastguard Worker 		return t;
2276*8d67ca89SAndroid Build Coastguard Worker 	if (tmp->tm_isdst < 0)
2277*8d67ca89SAndroid Build Coastguard Worker #ifdef PCTS
2278*8d67ca89SAndroid Build Coastguard Worker 		/*
2279*8d67ca89SAndroid Build Coastguard Worker 		** POSIX Conformance Test Suite code courtesy Grant Sullivan.
2280*8d67ca89SAndroid Build Coastguard Worker 		*/
2281*8d67ca89SAndroid Build Coastguard Worker 		tmp->tm_isdst = 0;	/* reset to std and try again */
2282*8d67ca89SAndroid Build Coastguard Worker #else
2283*8d67ca89SAndroid Build Coastguard Worker 		return t;
2284*8d67ca89SAndroid Build Coastguard Worker #endif /* !defined PCTS */
2285*8d67ca89SAndroid Build Coastguard Worker 	/*
2286*8d67ca89SAndroid Build Coastguard Worker 	** We're supposed to assume that somebody took a time of one type
2287*8d67ca89SAndroid Build Coastguard Worker 	** and did some math on it that yielded a "struct tm" that's bad.
2288*8d67ca89SAndroid Build Coastguard Worker 	** We try to divine the type they started from and adjust to the
2289*8d67ca89SAndroid Build Coastguard Worker 	** type they need.
2290*8d67ca89SAndroid Build Coastguard Worker 	*/
2291*8d67ca89SAndroid Build Coastguard Worker 	if (sp == NULL)
2292*8d67ca89SAndroid Build Coastguard Worker 		return WRONG;
2293*8d67ca89SAndroid Build Coastguard Worker 	for (i = 0; i < sp->typecnt; ++i)
2294*8d67ca89SAndroid Build Coastguard Worker 		seen[i] = false;
2295*8d67ca89SAndroid Build Coastguard Worker 	nseen = 0;
2296*8d67ca89SAndroid Build Coastguard Worker 	for (i = sp->timecnt - 1; i >= 0; --i)
2297*8d67ca89SAndroid Build Coastguard Worker 		if (!seen[sp->types[i]] && !ttunspecified(sp, sp->types[i])) {
2298*8d67ca89SAndroid Build Coastguard Worker 			seen[sp->types[i]] = true;
2299*8d67ca89SAndroid Build Coastguard Worker 			types[nseen++] = sp->types[i];
2300*8d67ca89SAndroid Build Coastguard Worker 		}
2301*8d67ca89SAndroid Build Coastguard Worker 	for (sameind = 0; sameind < nseen; ++sameind) {
2302*8d67ca89SAndroid Build Coastguard Worker 		samei = types[sameind];
2303*8d67ca89SAndroid Build Coastguard Worker 		if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2304*8d67ca89SAndroid Build Coastguard Worker 			continue;
2305*8d67ca89SAndroid Build Coastguard Worker 		for (otherind = 0; otherind < nseen; ++otherind) {
2306*8d67ca89SAndroid Build Coastguard Worker 			otheri = types[otherind];
2307*8d67ca89SAndroid Build Coastguard Worker 			if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2308*8d67ca89SAndroid Build Coastguard Worker 				continue;
2309*8d67ca89SAndroid Build Coastguard Worker 			tmp->tm_sec += (sp->ttis[otheri].tt_utoff
2310*8d67ca89SAndroid Build Coastguard Worker 					- sp->ttis[samei].tt_utoff);
2311*8d67ca89SAndroid Build Coastguard Worker 			tmp->tm_isdst = !tmp->tm_isdst;
2312*8d67ca89SAndroid Build Coastguard Worker 			t = time2(tmp, funcp, sp, offset, &okay);
2313*8d67ca89SAndroid Build Coastguard Worker 			if (okay)
2314*8d67ca89SAndroid Build Coastguard Worker 				return t;
2315*8d67ca89SAndroid Build Coastguard Worker 			tmp->tm_sec -= (sp->ttis[otheri].tt_utoff
2316*8d67ca89SAndroid Build Coastguard Worker 					- sp->ttis[samei].tt_utoff);
2317*8d67ca89SAndroid Build Coastguard Worker 			tmp->tm_isdst = !tmp->tm_isdst;
2318*8d67ca89SAndroid Build Coastguard Worker 		}
2319*8d67ca89SAndroid Build Coastguard Worker 	}
2320*8d67ca89SAndroid Build Coastguard Worker 	return WRONG;
2321*8d67ca89SAndroid Build Coastguard Worker }
2322*8d67ca89SAndroid Build Coastguard Worker 
2323*8d67ca89SAndroid Build Coastguard Worker static time_t
mktime_tzname(struct state * sp,struct tm * tmp,bool setname)2324*8d67ca89SAndroid Build Coastguard Worker mktime_tzname(struct state *sp, struct tm *tmp, bool setname)
2325*8d67ca89SAndroid Build Coastguard Worker {
2326*8d67ca89SAndroid Build Coastguard Worker   if (sp)
2327*8d67ca89SAndroid Build Coastguard Worker     return time1(tmp, localsub, sp, setname);
2328*8d67ca89SAndroid Build Coastguard Worker   else {
2329*8d67ca89SAndroid Build Coastguard Worker     gmtcheck();
2330*8d67ca89SAndroid Build Coastguard Worker     return time1(tmp, gmtsub, gmtptr, 0);
2331*8d67ca89SAndroid Build Coastguard Worker   }
2332*8d67ca89SAndroid Build Coastguard Worker }
2333*8d67ca89SAndroid Build Coastguard Worker 
2334*8d67ca89SAndroid Build Coastguard Worker #if NETBSD_INSPIRED
2335*8d67ca89SAndroid Build Coastguard Worker 
2336*8d67ca89SAndroid Build Coastguard Worker time_t
mktime_z(struct state * restrict sp,struct tm * restrict tmp)2337*8d67ca89SAndroid Build Coastguard Worker mktime_z(struct state *restrict sp, struct tm *restrict tmp)
2338*8d67ca89SAndroid Build Coastguard Worker {
2339*8d67ca89SAndroid Build Coastguard Worker   return mktime_tzname(sp, tmp, false);
2340*8d67ca89SAndroid Build Coastguard Worker }
2341*8d67ca89SAndroid Build Coastguard Worker 
2342*8d67ca89SAndroid Build Coastguard Worker #endif
2343*8d67ca89SAndroid Build Coastguard Worker 
2344*8d67ca89SAndroid Build Coastguard Worker time_t
mktime(struct tm * tmp)2345*8d67ca89SAndroid Build Coastguard Worker mktime(struct tm *tmp)
2346*8d67ca89SAndroid Build Coastguard Worker {
2347*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
2348*8d67ca89SAndroid Build Coastguard Worker   int saved_errno = errno;
2349*8d67ca89SAndroid Build Coastguard Worker #endif
2350*8d67ca89SAndroid Build Coastguard Worker 
2351*8d67ca89SAndroid Build Coastguard Worker   time_t t;
2352*8d67ca89SAndroid Build Coastguard Worker   int err = lock();
2353*8d67ca89SAndroid Build Coastguard Worker   if (err) {
2354*8d67ca89SAndroid Build Coastguard Worker     errno = err;
2355*8d67ca89SAndroid Build Coastguard Worker     return -1;
2356*8d67ca89SAndroid Build Coastguard Worker   }
2357*8d67ca89SAndroid Build Coastguard Worker   tzset_unlocked();
2358*8d67ca89SAndroid Build Coastguard Worker   t = mktime_tzname(lclptr, tmp, true);
2359*8d67ca89SAndroid Build Coastguard Worker   unlock();
2360*8d67ca89SAndroid Build Coastguard Worker 
2361*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
2362*8d67ca89SAndroid Build Coastguard Worker   errno = (t == -1) ? EOVERFLOW : saved_errno;
2363*8d67ca89SAndroid Build Coastguard Worker #endif
2364*8d67ca89SAndroid Build Coastguard Worker   return t;
2365*8d67ca89SAndroid Build Coastguard Worker }
2366*8d67ca89SAndroid Build Coastguard Worker 
2367*8d67ca89SAndroid Build Coastguard Worker #if STD_INSPIRED
2368*8d67ca89SAndroid Build Coastguard Worker time_t
timelocal(struct tm * tmp)2369*8d67ca89SAndroid Build Coastguard Worker timelocal(struct tm *tmp)
2370*8d67ca89SAndroid Build Coastguard Worker {
2371*8d67ca89SAndroid Build Coastguard Worker 	if (tmp != NULL)
2372*8d67ca89SAndroid Build Coastguard Worker 		tmp->tm_isdst = -1;	/* in case it wasn't initialized */
2373*8d67ca89SAndroid Build Coastguard Worker 	return mktime(tmp);
2374*8d67ca89SAndroid Build Coastguard Worker }
2375*8d67ca89SAndroid Build Coastguard Worker #else
2376*8d67ca89SAndroid Build Coastguard Worker static
2377*8d67ca89SAndroid Build Coastguard Worker #endif
2378*8d67ca89SAndroid Build Coastguard Worker time_t
timeoff(struct tm * tmp,long offset)2379*8d67ca89SAndroid Build Coastguard Worker timeoff(struct tm *tmp, long offset)
2380*8d67ca89SAndroid Build Coastguard Worker {
2381*8d67ca89SAndroid Build Coastguard Worker   if (tmp)
2382*8d67ca89SAndroid Build Coastguard Worker     tmp->tm_isdst = 0;
2383*8d67ca89SAndroid Build Coastguard Worker   gmtcheck();
2384*8d67ca89SAndroid Build Coastguard Worker   return time1(tmp, gmtsub, gmtptr, offset);
2385*8d67ca89SAndroid Build Coastguard Worker }
2386*8d67ca89SAndroid Build Coastguard Worker 
2387*8d67ca89SAndroid Build Coastguard Worker time_t
timegm(struct tm * tmp)2388*8d67ca89SAndroid Build Coastguard Worker timegm(struct tm *tmp)
2389*8d67ca89SAndroid Build Coastguard Worker {
2390*8d67ca89SAndroid Build Coastguard Worker   time_t t;
2391*8d67ca89SAndroid Build Coastguard Worker   struct tm tmcpy;
2392*8d67ca89SAndroid Build Coastguard Worker   mktmcpy(&tmcpy, tmp);
2393*8d67ca89SAndroid Build Coastguard Worker   tmcpy.tm_wday = -1;
2394*8d67ca89SAndroid Build Coastguard Worker   t = timeoff(&tmcpy, 0);
2395*8d67ca89SAndroid Build Coastguard Worker   if (0 <= tmcpy.tm_wday)
2396*8d67ca89SAndroid Build Coastguard Worker     *tmp = tmcpy;
2397*8d67ca89SAndroid Build Coastguard Worker   return t;
2398*8d67ca89SAndroid Build Coastguard Worker }
2399*8d67ca89SAndroid Build Coastguard Worker 
2400*8d67ca89SAndroid Build Coastguard Worker static int_fast32_t
leapcorr(struct state const * sp,time_t t)2401*8d67ca89SAndroid Build Coastguard Worker leapcorr(struct state const *sp, time_t t)
2402*8d67ca89SAndroid Build Coastguard Worker {
2403*8d67ca89SAndroid Build Coastguard Worker 	register struct lsinfo const *	lp;
2404*8d67ca89SAndroid Build Coastguard Worker 	register int			i;
2405*8d67ca89SAndroid Build Coastguard Worker 
2406*8d67ca89SAndroid Build Coastguard Worker 	i = sp->leapcnt;
2407*8d67ca89SAndroid Build Coastguard Worker 	while (--i >= 0) {
2408*8d67ca89SAndroid Build Coastguard Worker 		lp = &sp->lsis[i];
2409*8d67ca89SAndroid Build Coastguard Worker 		if (t >= lp->ls_trans)
2410*8d67ca89SAndroid Build Coastguard Worker 			return lp->ls_corr;
2411*8d67ca89SAndroid Build Coastguard Worker 	}
2412*8d67ca89SAndroid Build Coastguard Worker 	return 0;
2413*8d67ca89SAndroid Build Coastguard Worker }
2414*8d67ca89SAndroid Build Coastguard Worker 
2415*8d67ca89SAndroid Build Coastguard Worker /*
2416*8d67ca89SAndroid Build Coastguard Worker ** XXX--is the below the right way to conditionalize??
2417*8d67ca89SAndroid Build Coastguard Worker */
2418*8d67ca89SAndroid Build Coastguard Worker 
2419*8d67ca89SAndroid Build Coastguard Worker #if STD_INSPIRED
2420*8d67ca89SAndroid Build Coastguard Worker 
2421*8d67ca89SAndroid Build Coastguard Worker /* NETBSD_INSPIRED_EXTERN functions are exported to callers if
2422*8d67ca89SAndroid Build Coastguard Worker    NETBSD_INSPIRED is defined, and are private otherwise.  */
2423*8d67ca89SAndroid Build Coastguard Worker # if NETBSD_INSPIRED
2424*8d67ca89SAndroid Build Coastguard Worker #  define NETBSD_INSPIRED_EXTERN
2425*8d67ca89SAndroid Build Coastguard Worker # else
2426*8d67ca89SAndroid Build Coastguard Worker #  define NETBSD_INSPIRED_EXTERN static
2427*8d67ca89SAndroid Build Coastguard Worker # endif
2428*8d67ca89SAndroid Build Coastguard Worker 
2429*8d67ca89SAndroid Build Coastguard Worker /*
2430*8d67ca89SAndroid Build Coastguard Worker ** IEEE Std 1003.1 (POSIX) says that 536457599
2431*8d67ca89SAndroid Build Coastguard Worker ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2432*8d67ca89SAndroid Build Coastguard Worker ** is not the case if we are accounting for leap seconds.
2433*8d67ca89SAndroid Build Coastguard Worker ** So, we provide the following conversion routines for use
2434*8d67ca89SAndroid Build Coastguard Worker ** when exchanging timestamps with POSIX conforming systems.
2435*8d67ca89SAndroid Build Coastguard Worker */
2436*8d67ca89SAndroid Build Coastguard Worker 
2437*8d67ca89SAndroid Build Coastguard Worker NETBSD_INSPIRED_EXTERN time_t
time2posix_z(struct state * sp,time_t t)2438*8d67ca89SAndroid Build Coastguard Worker time2posix_z(struct state *sp, time_t t)
2439*8d67ca89SAndroid Build Coastguard Worker {
2440*8d67ca89SAndroid Build Coastguard Worker   return t - leapcorr(sp, t);
2441*8d67ca89SAndroid Build Coastguard Worker }
2442*8d67ca89SAndroid Build Coastguard Worker 
2443*8d67ca89SAndroid Build Coastguard Worker time_t
time2posix(time_t t)2444*8d67ca89SAndroid Build Coastguard Worker time2posix(time_t t)
2445*8d67ca89SAndroid Build Coastguard Worker {
2446*8d67ca89SAndroid Build Coastguard Worker   int err = lock();
2447*8d67ca89SAndroid Build Coastguard Worker   if (err) {
2448*8d67ca89SAndroid Build Coastguard Worker     errno = err;
2449*8d67ca89SAndroid Build Coastguard Worker     return -1;
2450*8d67ca89SAndroid Build Coastguard Worker   }
2451*8d67ca89SAndroid Build Coastguard Worker   if (!lcl_is_set)
2452*8d67ca89SAndroid Build Coastguard Worker     tzset_unlocked();
2453*8d67ca89SAndroid Build Coastguard Worker   if (lclptr)
2454*8d67ca89SAndroid Build Coastguard Worker     t = time2posix_z(lclptr, t);
2455*8d67ca89SAndroid Build Coastguard Worker   unlock();
2456*8d67ca89SAndroid Build Coastguard Worker   return t;
2457*8d67ca89SAndroid Build Coastguard Worker }
2458*8d67ca89SAndroid Build Coastguard Worker 
2459*8d67ca89SAndroid Build Coastguard Worker NETBSD_INSPIRED_EXTERN time_t
posix2time_z(struct state * sp,time_t t)2460*8d67ca89SAndroid Build Coastguard Worker posix2time_z(struct state *sp, time_t t)
2461*8d67ca89SAndroid Build Coastguard Worker {
2462*8d67ca89SAndroid Build Coastguard Worker 	time_t	x;
2463*8d67ca89SAndroid Build Coastguard Worker 	time_t	y;
2464*8d67ca89SAndroid Build Coastguard Worker 	/*
2465*8d67ca89SAndroid Build Coastguard Worker 	** For a positive leap second hit, the result
2466*8d67ca89SAndroid Build Coastguard Worker 	** is not unique. For a negative leap second
2467*8d67ca89SAndroid Build Coastguard Worker 	** hit, the corresponding time doesn't exist,
2468*8d67ca89SAndroid Build Coastguard Worker 	** so we return an adjacent second.
2469*8d67ca89SAndroid Build Coastguard Worker 	*/
2470*8d67ca89SAndroid Build Coastguard Worker 	x = t + leapcorr(sp, t);
2471*8d67ca89SAndroid Build Coastguard Worker 	y = x - leapcorr(sp, x);
2472*8d67ca89SAndroid Build Coastguard Worker 	if (y < t) {
2473*8d67ca89SAndroid Build Coastguard Worker 		do {
2474*8d67ca89SAndroid Build Coastguard Worker 			x++;
2475*8d67ca89SAndroid Build Coastguard Worker 			y = x - leapcorr(sp, x);
2476*8d67ca89SAndroid Build Coastguard Worker 		} while (y < t);
2477*8d67ca89SAndroid Build Coastguard Worker 		x -= y != t;
2478*8d67ca89SAndroid Build Coastguard Worker 	} else if (y > t) {
2479*8d67ca89SAndroid Build Coastguard Worker 		do {
2480*8d67ca89SAndroid Build Coastguard Worker 			--x;
2481*8d67ca89SAndroid Build Coastguard Worker 			y = x - leapcorr(sp, x);
2482*8d67ca89SAndroid Build Coastguard Worker 		} while (y > t);
2483*8d67ca89SAndroid Build Coastguard Worker 		x += y != t;
2484*8d67ca89SAndroid Build Coastguard Worker 	}
2485*8d67ca89SAndroid Build Coastguard Worker 	return x;
2486*8d67ca89SAndroid Build Coastguard Worker }
2487*8d67ca89SAndroid Build Coastguard Worker 
2488*8d67ca89SAndroid Build Coastguard Worker time_t
posix2time(time_t t)2489*8d67ca89SAndroid Build Coastguard Worker posix2time(time_t t)
2490*8d67ca89SAndroid Build Coastguard Worker {
2491*8d67ca89SAndroid Build Coastguard Worker   int err = lock();
2492*8d67ca89SAndroid Build Coastguard Worker   if (err) {
2493*8d67ca89SAndroid Build Coastguard Worker     errno = err;
2494*8d67ca89SAndroid Build Coastguard Worker     return -1;
2495*8d67ca89SAndroid Build Coastguard Worker   }
2496*8d67ca89SAndroid Build Coastguard Worker   if (!lcl_is_set)
2497*8d67ca89SAndroid Build Coastguard Worker     tzset_unlocked();
2498*8d67ca89SAndroid Build Coastguard Worker   if (lclptr)
2499*8d67ca89SAndroid Build Coastguard Worker     t = posix2time_z(lclptr, t);
2500*8d67ca89SAndroid Build Coastguard Worker   unlock();
2501*8d67ca89SAndroid Build Coastguard Worker   return t;
2502*8d67ca89SAndroid Build Coastguard Worker }
2503*8d67ca89SAndroid Build Coastguard Worker 
2504*8d67ca89SAndroid Build Coastguard Worker #endif /* STD_INSPIRED */
2505*8d67ca89SAndroid Build Coastguard Worker 
2506*8d67ca89SAndroid Build Coastguard Worker #if TZ_TIME_T
2507*8d67ca89SAndroid Build Coastguard Worker 
2508*8d67ca89SAndroid Build Coastguard Worker # if !USG_COMPAT
2509*8d67ca89SAndroid Build Coastguard Worker #  define daylight 0
2510*8d67ca89SAndroid Build Coastguard Worker #  define timezone 0
2511*8d67ca89SAndroid Build Coastguard Worker # endif
2512*8d67ca89SAndroid Build Coastguard Worker # if !ALTZONE
2513*8d67ca89SAndroid Build Coastguard Worker #  define altzone 0
2514*8d67ca89SAndroid Build Coastguard Worker # endif
2515*8d67ca89SAndroid Build Coastguard Worker 
2516*8d67ca89SAndroid Build Coastguard Worker /* Convert from the underlying system's time_t to the ersatz time_tz,
2517*8d67ca89SAndroid Build Coastguard Worker    which is called 'time_t' in this file.  Typically, this merely
2518*8d67ca89SAndroid Build Coastguard Worker    converts the time's integer width.  On some platforms, the system
2519*8d67ca89SAndroid Build Coastguard Worker    time is local time not UT, or uses some epoch other than the POSIX
2520*8d67ca89SAndroid Build Coastguard Worker    epoch.
2521*8d67ca89SAndroid Build Coastguard Worker 
2522*8d67ca89SAndroid Build Coastguard Worker    Although this code appears to define a function named 'time' that
2523*8d67ca89SAndroid Build Coastguard Worker    returns time_t, the macros in private.h cause this code to actually
2524*8d67ca89SAndroid Build Coastguard Worker    define a function named 'tz_time' that returns tz_time_t.  The call
2525*8d67ca89SAndroid Build Coastguard Worker    to sys_time invokes the underlying system's 'time' function.  */
2526*8d67ca89SAndroid Build Coastguard Worker 
2527*8d67ca89SAndroid Build Coastguard Worker time_t
time(time_t * p)2528*8d67ca89SAndroid Build Coastguard Worker time(time_t *p)
2529*8d67ca89SAndroid Build Coastguard Worker {
2530*8d67ca89SAndroid Build Coastguard Worker   time_t r = sys_time(0);
2531*8d67ca89SAndroid Build Coastguard Worker   if (r != (time_t) -1) {
2532*8d67ca89SAndroid Build Coastguard Worker     int_fast32_t offset = EPOCH_LOCAL ? (daylight ? timezone : altzone) : 0;
2533*8d67ca89SAndroid Build Coastguard Worker     if (increment_overflow32(&offset, -EPOCH_OFFSET)
2534*8d67ca89SAndroid Build Coastguard Worker 	|| increment_overflow_time(&r, offset)) {
2535*8d67ca89SAndroid Build Coastguard Worker       errno = EOVERFLOW;
2536*8d67ca89SAndroid Build Coastguard Worker       r = -1;
2537*8d67ca89SAndroid Build Coastguard Worker     }
2538*8d67ca89SAndroid Build Coastguard Worker   }
2539*8d67ca89SAndroid Build Coastguard Worker   if (p)
2540*8d67ca89SAndroid Build Coastguard Worker     *p = r;
2541*8d67ca89SAndroid Build Coastguard Worker   return r;
2542*8d67ca89SAndroid Build Coastguard Worker }
2543*8d67ca89SAndroid Build Coastguard Worker 
2544*8d67ca89SAndroid Build Coastguard Worker #endif
2545