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