localtime.c revision 1.114 1 /* $NetBSD: localtime.c,v 1.114 2019/01/01 03:04:56 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.114 2019/01/01 03:04:56 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 #include "reentrant.h"
34
35 #if NETBSD_INSPIRED
36 # define NETBSD_INSPIRED_EXTERN
37 #else
38 # define NETBSD_INSPIRED_EXTERN static
39 #endif
40
41 #if defined(__weak_alias)
42 __weak_alias(daylight,_daylight)
43 __weak_alias(tzname,_tzname)
44 #endif
45
46 #ifndef TZ_ABBR_MAX_LEN
47 #define TZ_ABBR_MAX_LEN 16
48 #endif /* !defined TZ_ABBR_MAX_LEN */
49
50 #ifndef TZ_ABBR_CHAR_SET
51 #define TZ_ABBR_CHAR_SET \
52 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
53 #endif /* !defined TZ_ABBR_CHAR_SET */
54
55 #ifndef TZ_ABBR_ERR_CHAR
56 #define TZ_ABBR_ERR_CHAR '_'
57 #endif /* !defined TZ_ABBR_ERR_CHAR */
58
59 /*
60 ** SunOS 4.1.1 headers lack O_BINARY.
61 */
62
63 #ifdef O_BINARY
64 #define OPEN_MODE (O_RDONLY | O_BINARY | O_CLOEXEC)
65 #endif /* defined O_BINARY */
66 #ifndef O_BINARY
67 #define OPEN_MODE (O_RDONLY | O_CLOEXEC)
68 #endif /* !defined O_BINARY */
69
70 #ifndef WILDABBR
71 /*
72 ** Someone might make incorrect use of a time zone abbreviation:
73 ** 1. They might reference tzname[0] before calling tzset (explicitly
74 ** or implicitly).
75 ** 2. They might reference tzname[1] before calling tzset (explicitly
76 ** or implicitly).
77 ** 3. They might reference tzname[1] after setting to a time zone
78 ** in which Daylight Saving Time is never observed.
79 ** 4. They might reference tzname[0] after setting to a time zone
80 ** in which Standard Time is never observed.
81 ** 5. They might reference tm.TM_ZONE after calling offtime.
82 ** What's best to do in the above cases is open to debate;
83 ** for now, we just set things up so that in any of the five cases
84 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
85 ** string "tzname[0] used before set", and similarly for the other cases.
86 ** And another: initialize tzname[0] to "ERA", with an explanation in the
87 ** manual page of what this "time zone abbreviation" means (doing this so
88 ** that tzname[0] has the "normal" length of three characters).
89 */
90 #define WILDABBR " "
91 #endif /* !defined WILDABBR */
92
93 static const char wildabbr[] = WILDABBR;
94
95 static const char gmt[] = "GMT";
96
97 /*
98 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
99 ** Default to US rules as of 2017-05-07.
100 ** POSIX does not specify the default DST rules;
101 ** for historical reasons, US rules are a common default.
102 */
103 #ifndef TZDEFRULESTRING
104 #define TZDEFRULESTRING ",M3.2.0,M11.1.0"
105 #endif
106
107 struct ttinfo { /* time type information */
108 int_fast32_t tt_gmtoff; /* UT offset in seconds */
109 bool tt_isdst; /* used to set tm_isdst */
110 int tt_abbrind; /* abbreviation list index */
111 bool tt_ttisstd; /* transition is std time */
112 bool tt_ttisgmt; /* transition is UT */
113 };
114
115 struct lsinfo { /* leap second information */
116 time_t ls_trans; /* transition time */
117 int_fast64_t ls_corr; /* correction to apply */
118 };
119
120 #define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
121 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
122
123 #ifdef TZNAME_MAX
124 #define MY_TZNAME_MAX TZNAME_MAX
125 #endif /* defined TZNAME_MAX */
126 #ifndef TZNAME_MAX
127 #define MY_TZNAME_MAX 255
128 #endif /* !defined TZNAME_MAX */
129
130 #define state __state
131 struct state {
132 int leapcnt;
133 int timecnt;
134 int typecnt;
135 int charcnt;
136 bool goback;
137 bool goahead;
138 time_t ats[TZ_MAX_TIMES];
139 unsigned char types[TZ_MAX_TIMES];
140 struct ttinfo ttis[TZ_MAX_TYPES];
141 char chars[/*CONSTCOND*/BIGGEST(BIGGEST(TZ_MAX_CHARS + 1,
142 sizeof gmt), (2 * (MY_TZNAME_MAX + 1)))];
143 struct lsinfo lsis[TZ_MAX_LEAPS];
144
145 /* The time type to use for early times or if no transitions.
146 It is always zero for recent tzdb releases.
147 It might be nonzero for data from tzdb 2018e or earlier. */
148 int defaulttype;
149 };
150
151 enum r_type {
152 JULIAN_DAY, /* Jn = Julian day */
153 DAY_OF_YEAR, /* n = day of year */
154 MONTH_NTH_DAY_OF_WEEK /* Mm.n.d = month, week, day of week */
155 };
156
157 struct rule {
158 enum r_type r_type; /* type of rule */
159 int r_day; /* day number of rule */
160 int r_week; /* week number of rule */
161 int r_mon; /* month number of rule */
162 int_fast32_t r_time; /* transition time of rule */
163 };
164
165 static struct tm *gmtsub(struct state const *, time_t const *, int_fast32_t,
166 struct tm *);
167 static bool increment_overflow(int *, int);
168 static bool increment_overflow_time(time_t *, int_fast32_t);
169 static bool normalize_overflow32(int_fast32_t *, int *, int);
170 static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
171 struct tm *);
172 static bool typesequiv(struct state const *, int, int);
173 static bool tzparse(char const *, struct state *, bool);
174
175 static timezone_t lclptr;
176 static timezone_t gmtptr;
177
178 #ifndef TZ_STRLEN_MAX
179 #define TZ_STRLEN_MAX 255
180 #endif /* !defined TZ_STRLEN_MAX */
181
182 static char lcl_TZname[TZ_STRLEN_MAX + 1];
183 static int lcl_is_set;
184
185
186 #ifdef _REENTRANT
187 static rwlock_t lcl_lock = RWLOCK_INITIALIZER;
188 #endif
189
190 /*
191 ** Section 4.12.3 of X3.159-1989 requires that
192 ** Except for the strftime function, these functions [asctime,
193 ** ctime, gmtime, localtime] return values in one of two static
194 ** objects: a broken-down time structure and an array of char.
195 ** Thanks to Paul Eggert for noting this.
196 */
197
198 static struct tm tm;
199
200 #if !HAVE_POSIX_DECLS || TZ_TIME_T || defined(__NetBSD__)
201 # if !defined(__LIBC12_SOURCE__)
202
203 __aconst char * tzname[2] = {
204 (__aconst char *)__UNCONST(wildabbr),
205 (__aconst char *)__UNCONST(wildabbr)
206 };
207
208 # else
209
210 extern __aconst char * tzname[2];
211
212 # endif /* __LIBC12_SOURCE__ */
213
214 # if USG_COMPAT
215 # if !defined(__LIBC12_SOURCE__)
216 long timezone = 0;
217 int daylight = 0;
218 # else
219 extern int daylight;
220 extern long timezone __RENAME(__timezone13);
221 # endif /* __LIBC12_SOURCE__ */
222 # endif /* defined USG_COMPAT */
223
224 # ifdef ALTZONE
225 long altzone = 0;
226 # endif /* defined ALTZONE */
227 #endif /* !HAVE_POSIX_DECLS */
228
229 /* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND. */
230 static void
231 init_ttinfo(struct ttinfo *s, int_fast32_t gmtoff, bool isdst, int abbrind)
232 {
233 s->tt_gmtoff = gmtoff;
234 s->tt_isdst = isdst;
235 s->tt_abbrind = abbrind;
236 s->tt_ttisstd = false;
237 s->tt_ttisgmt = false;
238 }
239
240 static int_fast32_t
241 detzcode(const char *const codep)
242 {
243 int_fast32_t result;
244 int i;
245 int_fast32_t one = 1;
246 int_fast32_t halfmaxval = one << (32 - 2);
247 int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
248 int_fast32_t minval = -1 - maxval;
249
250 result = codep[0] & 0x7f;
251 for (i = 1; i < 4; ++i)
252 result = (result << 8) | (codep[i] & 0xff);
253
254 if (codep[0] & 0x80) {
255 /* Do two's-complement negation even on non-two's-complement machines.
256 If the result would be minval - 1, return minval. */
257 result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
258 result += minval;
259 }
260 return result;
261 }
262
263 static int_fast64_t
264 detzcode64(const char *const codep)
265 {
266 int_fast64_t result;
267 int i;
268 int_fast64_t one = 1;
269 int_fast64_t halfmaxval = one << (64 - 2);
270 int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
271 int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
272
273 result = codep[0] & 0x7f;
274 for (i = 1; i < 8; ++i)
275 result = (result << 8) | (codep[i] & 0xff);
276
277 if (codep[0] & 0x80) {
278 /* Do two's-complement negation even on non-two's-complement machines.
279 If the result would be minval - 1, return minval. */
280 result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
281 result += minval;
282 }
283 return result;
284 }
285
286 const char *
287 tzgetname(const timezone_t sp, int isdst)
288 {
289 int i;
290 for (i = 0; i < sp->typecnt; ++i) {
291 const struct ttinfo *const ttisp = &sp->ttis[sp->types[i]];
292
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, '.')); 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 = 0;
1395 sp->charcnt = 0;
1396 sp->goback = sp->goahead = false;
1397 init_ttinfo(&sp->ttis[0], 0, false, 0);
1398 strcpy(sp->chars, gmt);
1399 sp->defaulttype = 0;
1400 return 0;
1401 } else {
1402 int err = tzload(name, sp, true);
1403 if (err != 0 && name && name[0] != ':' &&
1404 tzparse(name, sp, false))
1405 err = 0;
1406 if (err == 0)
1407 scrub_abbrs(sp);
1408 return err;
1409 }
1410 }
1411
1412 static void
1413 tzsetlcl(char const *name)
1414 {
1415 struct state *sp = lclptr;
1416 int lcl = name ? strlen(name) < sizeof lcl_TZname : -1;
1417 if (lcl < 0 ? lcl_is_set < 0
1418 : 0 < lcl_is_set && strcmp(lcl_TZname, name) == 0)
1419 return;
1420
1421 if (! sp)
1422 lclptr = sp = malloc(sizeof *lclptr);
1423 if (sp) {
1424 if (zoneinit(sp, name) != 0)
1425 zoneinit(sp, "");
1426 if (0 < lcl)
1427 strcpy(lcl_TZname, name);
1428 }
1429 settzname();
1430 lcl_is_set = lcl;
1431 }
1432
1433 #ifdef STD_INSPIRED
1434 void
1435 tzsetwall(void)
1436 {
1437 rwlock_wrlock(&lcl_lock);
1438 tzsetlcl(NULL);
1439 rwlock_unlock(&lcl_lock);
1440 }
1441 #endif
1442
1443 static void
1444 tzset_unlocked(void)
1445 {
1446 tzsetlcl(getenv("TZ"));
1447 }
1448
1449 void
1450 tzset(void)
1451 {
1452 rwlock_wrlock(&lcl_lock);
1453 tzset_unlocked();
1454 rwlock_unlock(&lcl_lock);
1455 }
1456
1457 static void
1458 gmtcheck(void)
1459 {
1460 static bool gmt_is_set;
1461 rwlock_wrlock(&lcl_lock);
1462 if (! gmt_is_set) {
1463 gmtptr = malloc(sizeof *gmtptr);
1464 if (gmtptr)
1465 gmtload(gmtptr);
1466 gmt_is_set = true;
1467 }
1468 rwlock_unlock(&lcl_lock);
1469 }
1470
1471 #if NETBSD_INSPIRED
1472
1473 timezone_t
1474 tzalloc(const char *name)
1475 {
1476 timezone_t sp = malloc(sizeof *sp);
1477 if (sp) {
1478 int err = zoneinit(sp, name);
1479 if (err != 0) {
1480 free(sp);
1481 errno = err;
1482 return NULL;
1483 }
1484 }
1485 return sp;
1486 }
1487
1488 void
1489 tzfree(timezone_t sp)
1490 {
1491 free(sp);
1492 }
1493
1494 /*
1495 ** NetBSD 6.1.4 has ctime_rz, but omit it because POSIX says ctime and
1496 ** ctime_r are obsolescent and have potential security problems that
1497 ** ctime_rz would share. Callers can instead use localtime_rz + strftime.
1498 **
1499 ** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work
1500 ** in zones with three or more time zone abbreviations.
1501 ** Callers can instead use localtime_rz + strftime.
1502 */
1503
1504 #endif
1505
1506 /*
1507 ** The easy way to behave "as if no library function calls" localtime
1508 ** is to not call it, so we drop its guts into "localsub", which can be
1509 ** freely called. (And no, the PANS doesn't require the above behavior,
1510 ** but it *is* desirable.)
1511 **
1512 ** If successful and SETNAME is nonzero,
1513 ** set the applicable parts of tzname, timezone and altzone;
1514 ** however, it's OK to omit this step if the timezone is POSIX-compatible,
1515 ** since in that case tzset should have already done this step correctly.
1516 ** SETNAME's type is intfast32_t for compatibility with gmtsub,
1517 ** but it is actually a boolean and its value should be 0 or 1.
1518 */
1519
1520 /*ARGSUSED*/
1521 static struct tm *
1522 localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
1523 struct tm *const tmp)
1524 {
1525 const struct ttinfo * ttisp;
1526 int i;
1527 struct tm * result;
1528 const time_t t = *timep;
1529
1530 if (sp == NULL) {
1531 /* Don't bother to set tzname etc.; tzset has already done it. */
1532 return gmtsub(gmtptr, timep, 0, tmp);
1533 }
1534 if ((sp->goback && t < sp->ats[0]) ||
1535 (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1536 time_t newt = t;
1537 time_t seconds;
1538 time_t years;
1539
1540 if (t < sp->ats[0])
1541 seconds = sp->ats[0] - t;
1542 else seconds = t - sp->ats[sp->timecnt - 1];
1543 --seconds;
1544 years = (time_t)((seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT);
1545 seconds = (time_t)(years * AVGSECSPERYEAR);
1546 if (t < sp->ats[0])
1547 newt += seconds;
1548 else newt -= seconds;
1549 if (newt < sp->ats[0] ||
1550 newt > sp->ats[sp->timecnt - 1]) {
1551 errno = EINVAL;
1552 return NULL; /* "cannot happen" */
1553 }
1554 result = localsub(sp, &newt, setname, tmp);
1555 if (result) {
1556 int_fast64_t newy;
1557
1558 newy = result->tm_year;
1559 if (t < sp->ats[0])
1560 newy -= years;
1561 else newy += years;
1562 if (! (INT_MIN <= newy && newy <= INT_MAX)) {
1563 errno = EOVERFLOW;
1564 return NULL;
1565 }
1566 result->tm_year = (int)newy;
1567 }
1568 return result;
1569 }
1570 if (sp->timecnt == 0 || t < sp->ats[0]) {
1571 i = sp->defaulttype;
1572 } else {
1573 int lo = 1;
1574 int hi = sp->timecnt;
1575
1576 while (lo < hi) {
1577 int mid = (lo + hi) / 2;
1578
1579 if (t < sp->ats[mid])
1580 hi = mid;
1581 else lo = mid + 1;
1582 }
1583 i = (int) sp->types[lo - 1];
1584 }
1585 ttisp = &sp->ttis[i];
1586 /*
1587 ** To get (wrong) behavior that's compatible with System V Release 2.0
1588 ** you'd replace the statement below with
1589 ** t += ttisp->tt_gmtoff;
1590 ** timesub(&t, 0L, sp, tmp);
1591 */
1592 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1593 if (result) {
1594 result->tm_isdst = ttisp->tt_isdst;
1595 #ifdef TM_ZONE
1596 result->TM_ZONE = __UNCONST(&sp->chars[ttisp->tt_abbrind]);
1597 #endif /* defined TM_ZONE */
1598 if (setname)
1599 update_tzname_etc(sp, ttisp);
1600 }
1601 return result;
1602 }
1603
1604 #if NETBSD_INSPIRED
1605
1606 struct tm *
1607 localtime_rz(timezone_t sp, time_t const *timep, struct tm *tmp)
1608 {
1609 return localsub(sp, timep, 0, tmp);
1610 }
1611
1612 #endif
1613
1614 static struct tm *
1615 localtime_tzset(time_t const *timep, struct tm *tmp, bool setname)
1616 {
1617 rwlock_wrlock(&lcl_lock);
1618 if (setname || !lcl_is_set)
1619 tzset_unlocked();
1620 tmp = localsub(lclptr, timep, setname, tmp);
1621 rwlock_unlock(&lcl_lock);
1622 return tmp;
1623 }
1624
1625 struct tm *
1626 localtime(const time_t *timep)
1627 {
1628 return localtime_tzset(timep, &tm, true);
1629 }
1630
1631 struct tm *
1632 localtime_r(const time_t * __restrict timep, struct tm *tmp)
1633 {
1634 return localtime_tzset(timep, tmp, true);
1635 }
1636
1637 /*
1638 ** gmtsub is to gmtime as localsub is to localtime.
1639 */
1640
1641 static struct tm *
1642 gmtsub(struct state const *sp, const time_t *timep, int_fast32_t offset,
1643 struct tm *tmp)
1644 {
1645 struct tm * result;
1646
1647 result = timesub(timep, offset, gmtptr, tmp);
1648 #ifdef TM_ZONE
1649 /*
1650 ** Could get fancy here and deliver something such as
1651 ** "+xx" or "-xx" if offset is non-zero,
1652 ** but this is no time for a treasure hunt.
1653 */
1654 if (result)
1655 result->TM_ZONE = offset ? __UNCONST(wildabbr) : gmtptr ?
1656 gmtptr->chars : __UNCONST(gmt);
1657 #endif /* defined TM_ZONE */
1658 return result;
1659 }
1660
1661
1662 /*
1663 ** Re-entrant version of gmtime.
1664 */
1665
1666 struct tm *
1667 gmtime_r(const time_t *timep, struct tm *tmp)
1668 {
1669 gmtcheck();
1670 return gmtsub(NULL, timep, 0, tmp);
1671 }
1672
1673 struct tm *
1674 gmtime(const time_t *timep)
1675 {
1676 return gmtime_r(timep, &tm);
1677 }
1678 #ifdef STD_INSPIRED
1679
1680 struct tm *
1681 offtime(const time_t *timep, long offset)
1682 {
1683 gmtcheck();
1684 return gmtsub(gmtptr, timep, (int_fast32_t)offset, &tm);
1685 }
1686
1687 struct tm *
1688 offtime_r(const time_t *timep, long offset, struct tm *tmp)
1689 {
1690 gmtcheck();
1691 return gmtsub(NULL, timep, (int_fast32_t)offset, tmp);
1692 }
1693
1694 #endif /* defined STD_INSPIRED */
1695
1696 #if TZ_TIME_T
1697
1698 # if USG_COMPAT
1699 # define daylight 0
1700 # define timezone 0
1701 # endif
1702 # ifndef ALTZONE
1703 # define altzone 0
1704 # endif
1705
1706 /* Convert from the underlying system's time_t to the ersatz time_tz,
1707 which is called 'time_t' in this file. Typically, this merely
1708 converts the time's integer width. On some platforms, the system
1709 time is local time not UT, or uses some epoch other than the POSIX
1710 epoch.
1711
1712 Although this code appears to define a function named 'time' that
1713 returns time_t, the macros in private.h cause this code to actually
1714 define a function named 'tz_time' that returns tz_time_t. The call
1715 to sys_time invokes the underlying system's 'time' function. */
1716
1717 time_t
1718 time(time_t *p)
1719 {
1720 time_t r = sys_time(0);
1721 if (r != (time_t) -1) {
1722 int_fast32_t offset = EPOCH_LOCAL ? (daylight ? timezone : altzone) : 0;
1723 if (increment_overflow32(&offset, -EPOCH_OFFSET)
1724 || increment_overflow_time (&r, offset)) {
1725 errno = EOVERFLOW;
1726 r = -1;
1727 }
1728 }
1729 if (p)
1730 *p = r;
1731 return r;
1732 }
1733 #endif
1734
1735 /*
1736 ** Return the number of leap years through the end of the given year
1737 ** where, to make the math easy, the answer for year zero is defined as zero.
1738 */
1739 static int
1740 leaps_thru_end_of_nonneg(int y)
1741 {
1742 return y / 4 - y / 100 + y / 400;
1743 }
1744
1745 static int ATTRIBUTE_PURE
1746 leaps_thru_end_of(const int y)
1747 {
1748 return (y < 0
1749 ? -1 - leaps_thru_end_of_nonneg(-1 - y)
1750 : leaps_thru_end_of_nonneg(y));
1751 }
1752
1753 static struct tm *
1754 timesub(const time_t *timep, int_fast32_t offset,
1755 const struct state *sp, struct tm *tmp)
1756 {
1757 const struct lsinfo * lp;
1758 time_t tdays;
1759 int idays; /* unsigned would be so 2003 */
1760 int_fast64_t rem;
1761 int y;
1762 const int * ip;
1763 int_fast64_t corr;
1764 int hit;
1765 int i;
1766
1767 corr = 0;
1768 hit = false;
1769 i = (sp == NULL) ? 0 : sp->leapcnt;
1770 while (--i >= 0) {
1771 lp = &sp->lsis[i];
1772 if (*timep >= lp->ls_trans) {
1773 corr = lp->ls_corr;
1774 hit = (*timep == lp->ls_trans
1775 && (i == 0 ? 0 : lp[-1].ls_corr) < corr);
1776 break;
1777 }
1778 }
1779 y = EPOCH_YEAR;
1780 tdays = (time_t)(*timep / SECSPERDAY);
1781 rem = *timep % SECSPERDAY;
1782 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
1783 int newy;
1784 time_t tdelta;
1785 int idelta;
1786 int leapdays;
1787
1788 tdelta = tdays / DAYSPERLYEAR;
1789 if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
1790 && tdelta <= INT_MAX))
1791 goto out_of_range;
1792 _DIAGASSERT(__type_fit(int, tdelta));
1793 idelta = (int)tdelta;
1794 if (idelta == 0)
1795 idelta = (tdays < 0) ? -1 : 1;
1796 newy = y;
1797 if (increment_overflow(&newy, idelta))
1798 goto out_of_range;
1799 leapdays = leaps_thru_end_of(newy - 1) -
1800 leaps_thru_end_of(y - 1);
1801 tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
1802 tdays -= leapdays;
1803 y = newy;
1804 }
1805 /*
1806 ** Given the range, we can now fearlessly cast...
1807 */
1808 idays = (int) tdays;
1809 rem += offset - corr;
1810 while (rem < 0) {
1811 rem += SECSPERDAY;
1812 --idays;
1813 }
1814 while (rem >= SECSPERDAY) {
1815 rem -= SECSPERDAY;
1816 ++idays;
1817 }
1818 while (idays < 0) {
1819 if (increment_overflow(&y, -1))
1820 goto out_of_range;
1821 idays += year_lengths[isleap(y)];
1822 }
1823 while (idays >= year_lengths[isleap(y)]) {
1824 idays -= year_lengths[isleap(y)];
1825 if (increment_overflow(&y, 1))
1826 goto out_of_range;
1827 }
1828 tmp->tm_year = y;
1829 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
1830 goto out_of_range;
1831 tmp->tm_yday = idays;
1832 /*
1833 ** The "extra" mods below avoid overflow problems.
1834 */
1835 tmp->tm_wday = EPOCH_WDAY +
1836 ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1837 (DAYSPERNYEAR % DAYSPERWEEK) +
1838 leaps_thru_end_of(y - 1) -
1839 leaps_thru_end_of(EPOCH_YEAR - 1) +
1840 idays;
1841 tmp->tm_wday %= DAYSPERWEEK;
1842 if (tmp->tm_wday < 0)
1843 tmp->tm_wday += DAYSPERWEEK;
1844 tmp->tm_hour = (int) (rem / SECSPERHOUR);
1845 rem %= SECSPERHOUR;
1846 tmp->tm_min = (int) (rem / SECSPERMIN);
1847 /*
1848 ** A positive leap second requires a special
1849 ** representation. This uses "... ??:59:60" et seq.
1850 */
1851 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1852 ip = mon_lengths[isleap(y)];
1853 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1854 idays -= ip[tmp->tm_mon];
1855 tmp->tm_mday = (int) (idays + 1);
1856 tmp->tm_isdst = 0;
1857 #ifdef TM_GMTOFF
1858 tmp->TM_GMTOFF = offset;
1859 #endif /* defined TM_GMTOFF */
1860 return tmp;
1861 out_of_range:
1862 errno = EOVERFLOW;
1863 return NULL;
1864 }
1865
1866 char *
1867 ctime(const time_t *timep)
1868 {
1869 /*
1870 ** Section 4.12.3.2 of X3.159-1989 requires that
1871 ** The ctime function converts the calendar time pointed to by timer
1872 ** to local time in the form of a string. It is equivalent to
1873 ** asctime(localtime(timer))
1874 */
1875 struct tm *tmp = localtime(timep);
1876 return tmp ? asctime(tmp) : NULL;
1877 }
1878
1879 char *
1880 ctime_r(const time_t *timep, char *buf)
1881 {
1882 struct tm mytm;
1883 struct tm *tmp = localtime_r(timep, &mytm);
1884 return tmp ? asctime_r(tmp, buf) : NULL;
1885 }
1886
1887 char *
1888 ctime_rz(const timezone_t sp, const time_t * timep, char *buf)
1889 {
1890 struct tm mytm, *rtm;
1891
1892 rtm = localtime_rz(sp, timep, &mytm);
1893 if (rtm == NULL)
1894 return NULL;
1895 return asctime_r(rtm, buf);
1896 }
1897
1898 /*
1899 ** Adapted from code provided by Robert Elz, who writes:
1900 ** The "best" way to do mktime I think is based on an idea of Bob
1901 ** Kridle's (so its said...) from a long time ago.
1902 ** It does a binary search of the time_t space. Since time_t's are
1903 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1904 ** would still be very reasonable).
1905 */
1906
1907 #ifndef WRONG
1908 #define WRONG ((time_t)-1)
1909 #endif /* !defined WRONG */
1910
1911 /*
1912 ** Normalize logic courtesy Paul Eggert.
1913 */
1914
1915 static bool
1916 increment_overflow(int *ip, int j)
1917 {
1918 int const i = *ip;
1919
1920 /*
1921 ** If i >= 0 there can only be overflow if i + j > INT_MAX
1922 ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1923 ** If i < 0 there can only be overflow if i + j < INT_MIN
1924 ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1925 */
1926 if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
1927 return true;
1928 *ip += j;
1929 return false;
1930 }
1931
1932 static bool
1933 increment_overflow32(int_fast32_t *const lp, int const m)
1934 {
1935 int_fast32_t const l = *lp;
1936
1937 if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
1938 return true;
1939 *lp += m;
1940 return false;
1941 }
1942
1943 static bool
1944 increment_overflow_time(time_t *tp, int_fast32_t j)
1945 {
1946 /*
1947 ** This is like
1948 ** 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
1949 ** except that it does the right thing even if *tp + j would overflow.
1950 */
1951 if (! (j < 0
1952 ? (TYPE_SIGNED(time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
1953 : *tp <= TIME_T_MAX - j))
1954 return true;
1955 *tp += j;
1956 return false;
1957 }
1958
1959 static bool
1960 normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
1961 {
1962 int tensdelta;
1963
1964 tensdelta = (*unitsptr >= 0) ?
1965 (*unitsptr / base) :
1966 (-1 - (-1 - *unitsptr) / base);
1967 *unitsptr -= tensdelta * base;
1968 return increment_overflow(tensptr, tensdelta);
1969 }
1970
1971 static bool
1972 normalize_overflow32(int_fast32_t *tensptr, int *unitsptr, int base)
1973 {
1974 int tensdelta;
1975
1976 tensdelta = (*unitsptr >= 0) ?
1977 (*unitsptr / base) :
1978 (-1 - (-1 - *unitsptr) / base);
1979 *unitsptr -= tensdelta * base;
1980 return increment_overflow32(tensptr, tensdelta);
1981 }
1982
1983 static int
1984 tmcomp(const struct tm *const atmp,
1985 const struct tm *const btmp)
1986 {
1987 int result;
1988
1989 if (atmp->tm_year != btmp->tm_year)
1990 return atmp->tm_year < btmp->tm_year ? -1 : 1;
1991 if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1992 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1993 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1994 (result = (atmp->tm_min - btmp->tm_min)) == 0)
1995 result = atmp->tm_sec - btmp->tm_sec;
1996 return result;
1997 }
1998
1999 static time_t
2000 time2sub(struct tm *const tmp,
2001 struct tm *(*funcp)(struct state const *, time_t const *,
2002 int_fast32_t, struct tm *),
2003 struct state const *sp,
2004 const int_fast32_t offset,
2005 bool *okayp,
2006 bool do_norm_secs)
2007 {
2008 int dir;
2009 int i, j;
2010 int saved_seconds;
2011 int_fast32_t li;
2012 time_t lo;
2013 time_t hi;
2014 #ifdef NO_ERROR_IN_DST_GAP
2015 time_t ilo;
2016 #endif
2017 int_fast32_t y;
2018 time_t newt;
2019 time_t t;
2020 struct tm yourtm, mytm;
2021
2022 *okayp = false;
2023 yourtm = *tmp;
2024 #ifdef NO_ERROR_IN_DST_GAP
2025 again:
2026 #endif
2027 if (do_norm_secs) {
2028 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
2029 SECSPERMIN))
2030 goto out_of_range;
2031 }
2032 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
2033 goto out_of_range;
2034 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
2035 goto out_of_range;
2036 y = yourtm.tm_year;
2037 if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
2038 goto out_of_range;
2039 /*
2040 ** Turn y into an actual year number for now.
2041 ** It is converted back to an offset from TM_YEAR_BASE later.
2042 */
2043 if (increment_overflow32(&y, TM_YEAR_BASE))
2044 goto out_of_range;
2045 while (yourtm.tm_mday <= 0) {
2046 if (increment_overflow32(&y, -1))
2047 goto out_of_range;
2048 li = y + (1 < yourtm.tm_mon);
2049 yourtm.tm_mday += year_lengths[isleap(li)];
2050 }
2051 while (yourtm.tm_mday > DAYSPERLYEAR) {
2052 li = y + (1 < yourtm.tm_mon);
2053 yourtm.tm_mday -= year_lengths[isleap(li)];
2054 if (increment_overflow32(&y, 1))
2055 goto out_of_range;
2056 }
2057 for ( ; ; ) {
2058 i = mon_lengths[isleap(y)][yourtm.tm_mon];
2059 if (yourtm.tm_mday <= i)
2060 break;
2061 yourtm.tm_mday -= i;
2062 if (++yourtm.tm_mon >= MONSPERYEAR) {
2063 yourtm.tm_mon = 0;
2064 if (increment_overflow32(&y, 1))
2065 goto out_of_range;
2066 }
2067 }
2068 if (increment_overflow32(&y, -TM_YEAR_BASE))
2069 goto out_of_range;
2070 if (! (INT_MIN <= y && y <= INT_MAX))
2071 goto out_of_range;
2072 yourtm.tm_year = (int)y;
2073 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
2074 saved_seconds = 0;
2075 else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
2076 /*
2077 ** We can't set tm_sec to 0, because that might push the
2078 ** time below the minimum representable time.
2079 ** Set tm_sec to 59 instead.
2080 ** This assumes that the minimum representable time is
2081 ** not in the same minute that a leap second was deleted from,
2082 ** which is a safer assumption than using 58 would be.
2083 */
2084 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
2085 goto out_of_range;
2086 saved_seconds = yourtm.tm_sec;
2087 yourtm.tm_sec = SECSPERMIN - 1;
2088 } else {
2089 saved_seconds = yourtm.tm_sec;
2090 yourtm.tm_sec = 0;
2091 }
2092 /*
2093 ** Do a binary search (this works whatever time_t's type is).
2094 */
2095 lo = TIME_T_MIN;
2096 hi = TIME_T_MAX;
2097 #ifdef NO_ERROR_IN_DST_GAP
2098 ilo = lo;
2099 #endif
2100 for ( ; ; ) {
2101 t = lo / 2 + hi / 2;
2102 if (t < lo)
2103 t = lo;
2104 else if (t > hi)
2105 t = hi;
2106 if (! funcp(sp, &t, offset, &mytm)) {
2107 /*
2108 ** Assume that t is too extreme to be represented in
2109 ** a struct tm; arrange things so that it is less
2110 ** extreme on the next pass.
2111 */
2112 dir = (t > 0) ? 1 : -1;
2113 } else dir = tmcomp(&mytm, &yourtm);
2114 if (dir != 0) {
2115 if (t == lo) {
2116 if (t == TIME_T_MAX)
2117 goto out_of_range;
2118 ++t;
2119 ++lo;
2120 } else if (t == hi) {
2121 if (t == TIME_T_MIN)
2122 goto out_of_range;
2123 --t;
2124 --hi;
2125 }
2126 #ifdef NO_ERROR_IN_DST_GAP
2127 if (ilo != lo && lo - 1 == hi && yourtm.tm_isdst < 0 &&
2128 do_norm_secs) {
2129 for (i = sp->typecnt - 1; i >= 0; --i) {
2130 for (j = sp->typecnt - 1; j >= 0; --j) {
2131 time_t off;
2132 if (sp->ttis[j].tt_isdst ==
2133 sp->ttis[i].tt_isdst)
2134 continue;
2135 off = sp->ttis[j].tt_gmtoff -
2136 sp->ttis[i].tt_gmtoff;
2137 yourtm.tm_sec += off < 0 ?
2138 -off : off;
2139 goto again;
2140 }
2141 }
2142 }
2143 #endif
2144 if (lo > hi)
2145 goto invalid;
2146 if (dir > 0)
2147 hi = t;
2148 else lo = t;
2149 continue;
2150 }
2151 #if defined TM_GMTOFF && ! UNINIT_TRAP
2152 if (mytm.TM_GMTOFF != yourtm.TM_GMTOFF
2153 && (yourtm.TM_GMTOFF < 0
2154 ? (-SECSPERDAY <= yourtm.TM_GMTOFF
2155 && (mytm.TM_GMTOFF <=
2156 (/*CONSTCOND*/SMALLEST (INT_FAST32_MAX, LONG_MAX)
2157 + yourtm.TM_GMTOFF)))
2158 : (yourtm.TM_GMTOFF <= SECSPERDAY
2159 && ((/*CONSTCOND*/BIGGEST (INT_FAST32_MIN, LONG_MIN)
2160 + yourtm.TM_GMTOFF)
2161 <= mytm.TM_GMTOFF)))) {
2162 /* MYTM matches YOURTM except with the wrong UT offset.
2163 YOURTM.TM_GMTOFF is plausible, so try it instead.
2164 It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
2165 since the guess gets checked. */
2166 time_t altt = t;
2167 int_fast32_t diff = (int_fast32_t)
2168 (mytm.TM_GMTOFF - yourtm.TM_GMTOFF);
2169 if (!increment_overflow_time(&altt, diff)) {
2170 struct tm alttm;
2171 if (! funcp(sp, &altt, offset, &alttm)
2172 && alttm.tm_isdst == mytm.tm_isdst
2173 && alttm.TM_GMTOFF == yourtm.TM_GMTOFF
2174 && tmcomp(&alttm, &yourtm)) {
2175 t = altt;
2176 mytm = alttm;
2177 }
2178 }
2179 }
2180 #endif
2181 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
2182 break;
2183 /*
2184 ** Right time, wrong type.
2185 ** Hunt for right time, right type.
2186 ** It's okay to guess wrong since the guess
2187 ** gets checked.
2188 */
2189 if (sp == NULL)
2190 goto invalid;
2191 for (i = sp->typecnt - 1; i >= 0; --i) {
2192 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
2193 continue;
2194 for (j = sp->typecnt - 1; j >= 0; --j) {
2195 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
2196 continue;
2197 newt = (time_t)(t + sp->ttis[j].tt_gmtoff -
2198 sp->ttis[i].tt_gmtoff);
2199 if (! funcp(sp, &newt, offset, &mytm))
2200 continue;
2201 if (tmcomp(&mytm, &yourtm) != 0)
2202 continue;
2203 if (mytm.tm_isdst != yourtm.tm_isdst)
2204 continue;
2205 /*
2206 ** We have a match.
2207 */
2208 t = newt;
2209 goto label;
2210 }
2211 }
2212 goto invalid;
2213 }
2214 label:
2215 newt = t + saved_seconds;
2216 if ((newt < t) != (saved_seconds < 0))
2217 goto out_of_range;
2218 t = newt;
2219 if (funcp(sp, &t, offset, tmp)) {
2220 *okayp = true;
2221 return t;
2222 }
2223 out_of_range:
2224 errno = EOVERFLOW;
2225 return WRONG;
2226 invalid:
2227 errno = EINVAL;
2228 return WRONG;
2229 }
2230
2231 static time_t
2232 time2(struct tm * const tmp,
2233 struct tm *(*funcp)(struct state const *, time_t const *,
2234 int_fast32_t, struct tm *),
2235 struct state const *sp,
2236 const int_fast32_t offset,
2237 bool *okayp)
2238 {
2239 time_t t;
2240
2241 /*
2242 ** First try without normalization of seconds
2243 ** (in case tm_sec contains a value associated with a leap second).
2244 ** If that fails, try with normalization of seconds.
2245 */
2246 t = time2sub(tmp, funcp, sp, offset, okayp, false);
2247 return *okayp ? t : time2sub(tmp, funcp, sp, offset, okayp, true);
2248 }
2249
2250 static time_t
2251 time1(struct tm *const tmp,
2252 struct tm *(*funcp) (struct state const *, time_t const *,
2253 int_fast32_t, struct tm *),
2254 struct state const *sp,
2255 const int_fast32_t offset)
2256 {
2257 time_t t;
2258 int samei, otheri;
2259 int sameind, otherind;
2260 int i;
2261 int nseen;
2262 int save_errno;
2263 char seen[TZ_MAX_TYPES];
2264 unsigned char types[TZ_MAX_TYPES];
2265 bool okay;
2266
2267 if (tmp == NULL) {
2268 errno = EINVAL;
2269 return WRONG;
2270 }
2271 if (tmp->tm_isdst > 1)
2272 tmp->tm_isdst = 1;
2273 save_errno = errno;
2274 t = time2(tmp, funcp, sp, offset, &okay);
2275 if (okay) {
2276 errno = save_errno;
2277 return t;
2278 }
2279 if (tmp->tm_isdst < 0)
2280 #ifdef PCTS
2281 /*
2282 ** POSIX Conformance Test Suite code courtesy Grant Sullivan.
2283 */
2284 tmp->tm_isdst = 0; /* reset to std and try again */
2285 #else
2286 return t;
2287 #endif /* !defined PCTS */
2288 /*
2289 ** We're supposed to assume that somebody took a time of one type
2290 ** and did some math on it that yielded a "struct tm" that's bad.
2291 ** We try to divine the type they started from and adjust to the
2292 ** type they need.
2293 */
2294 if (sp == NULL) {
2295 errno = EINVAL;
2296 return WRONG;
2297 }
2298 for (i = 0; i < sp->typecnt; ++i)
2299 seen[i] = false;
2300 nseen = 0;
2301 for (i = sp->timecnt - 1; i >= 0; --i)
2302 if (!seen[sp->types[i]]) {
2303 seen[sp->types[i]] = true;
2304 types[nseen++] = sp->types[i];
2305 }
2306 for (sameind = 0; sameind < nseen; ++sameind) {
2307 samei = types[sameind];
2308 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2309 continue;
2310 for (otherind = 0; otherind < nseen; ++otherind) {
2311 otheri = types[otherind];
2312 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2313 continue;
2314 tmp->tm_sec += (int)(sp->ttis[otheri].tt_gmtoff -
2315 sp->ttis[samei].tt_gmtoff);
2316 tmp->tm_isdst = !tmp->tm_isdst;
2317 t = time2(tmp, funcp, sp, offset, &okay);
2318 if (okay) {
2319 errno = save_errno;
2320 return t;
2321 }
2322 tmp->tm_sec -= (int)(sp->ttis[otheri].tt_gmtoff -
2323 sp->ttis[samei].tt_gmtoff);
2324 tmp->tm_isdst = !tmp->tm_isdst;
2325 }
2326 }
2327 errno = EOVERFLOW;
2328 return WRONG;
2329 }
2330
2331 static time_t
2332 mktime_tzname(timezone_t sp, struct tm *tmp, bool setname)
2333 {
2334 if (sp)
2335 return time1(tmp, localsub, sp, setname);
2336 else {
2337 gmtcheck();
2338 return time1(tmp, gmtsub, gmtptr, 0);
2339 }
2340 }
2341
2342 #if NETBSD_INSPIRED
2343
2344 time_t
2345 mktime_z(timezone_t sp, struct tm *const tmp)
2346 {
2347 return mktime_tzname(sp, tmp, false);
2348 }
2349
2350 #endif
2351
2352 time_t
2353 mktime(struct tm *tmp)
2354 {
2355 time_t t;
2356
2357 rwlock_wrlock(&lcl_lock);
2358 tzset_unlocked();
2359 t = mktime_tzname(lclptr, tmp, true);
2360 rwlock_unlock(&lcl_lock);
2361 return t;
2362 }
2363
2364 #ifdef STD_INSPIRED
2365
2366 time_t
2367 timelocal_z(const timezone_t sp, struct tm *const tmp)
2368 {
2369 if (tmp != NULL)
2370 tmp->tm_isdst = -1; /* in case it wasn't initialized */
2371 return mktime_z(sp, tmp);
2372 }
2373
2374 time_t
2375 timelocal(struct tm *tmp)
2376 {
2377 if (tmp != NULL)
2378 tmp->tm_isdst = -1; /* in case it wasn't initialized */
2379 return mktime(tmp);
2380 }
2381
2382 time_t
2383 timegm(struct tm *tmp)
2384 {
2385
2386 return timeoff(tmp, 0);
2387 }
2388
2389 time_t
2390 timeoff(struct tm *tmp, long offset)
2391 {
2392 if (tmp)
2393 tmp->tm_isdst = 0;
2394 gmtcheck();
2395 return time1(tmp, gmtsub, gmtptr, (int_fast32_t)offset);
2396 }
2397
2398 #endif /* defined STD_INSPIRED */
2399
2400 /*
2401 ** XXX--is the below the right way to conditionalize??
2402 */
2403
2404 #ifdef STD_INSPIRED
2405
2406 /*
2407 ** IEEE Std 1003.1 (POSIX) says that 536457599
2408 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2409 ** is not the case if we are accounting for leap seconds.
2410 ** So, we provide the following conversion routines for use
2411 ** when exchanging timestamps with POSIX conforming systems.
2412 */
2413
2414 static int_fast64_t
2415 leapcorr(const timezone_t sp, time_t t)
2416 {
2417 struct lsinfo const * lp;
2418 int i;
2419
2420 i = sp->leapcnt;
2421 while (--i >= 0) {
2422 lp = &sp->lsis[i];
2423 if (t >= lp->ls_trans)
2424 return lp->ls_corr;
2425 }
2426 return 0;
2427 }
2428
2429 NETBSD_INSPIRED_EXTERN time_t
2430 time2posix_z(timezone_t sp, time_t t)
2431 {
2432 return (time_t)(t - leapcorr(sp, t));
2433 }
2434
2435 time_t
2436 time2posix(time_t t)
2437 {
2438 rwlock_wrlock(&lcl_lock);
2439 if (!lcl_is_set)
2440 tzset_unlocked();
2441 if (lclptr)
2442 t = (time_t)(t - leapcorr(lclptr, t));
2443 rwlock_unlock(&lcl_lock);
2444 return t;
2445 }
2446
2447 NETBSD_INSPIRED_EXTERN time_t
2448 posix2time_z(timezone_t sp, time_t t)
2449 {
2450 time_t x;
2451 time_t y;
2452
2453 /*
2454 ** For a positive leap second hit, the result
2455 ** is not unique. For a negative leap second
2456 ** hit, the corresponding time doesn't exist,
2457 ** so we return an adjacent second.
2458 */
2459 x = (time_t)(t + leapcorr(sp, t));
2460 y = (time_t)(x - leapcorr(sp, x));
2461 if (y < t) {
2462 do {
2463 x++;
2464 y = (time_t)(x - leapcorr(sp, x));
2465 } while (y < t);
2466 x -= y != t;
2467 } else if (y > t) {
2468 do {
2469 --x;
2470 y = (time_t)(x - leapcorr(sp, x));
2471 } while (y > t);
2472 x += y != t;
2473 }
2474 return x;
2475 }
2476
2477 time_t
2478 posix2time(time_t t)
2479 {
2480 rwlock_wrlock(&lcl_lock);
2481 if (!lcl_is_set)
2482 tzset_unlocked();
2483 if (lclptr)
2484 t = posix2time_z(lclptr, t);
2485 rwlock_unlock(&lcl_lock);
2486 return t;
2487 }
2488
2489 #endif /* defined STD_INSPIRED */
2490