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