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