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