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