Cygwin: add newgrp release notes
[newlib-cygwin.git] / winsup / cygwin / tzcode / localtime.c
bloba4d02a4c7d88afc6da0b0100666d9e77988b6ed6
1 /* $NetBSD: localtime.c,v 1.122 2019/07/03 15:50:16 christos Exp $ */
3 /* Convert timestamp from time_t to struct tm. */
5 /*
6 ** This file is in the public domain, so clarified as of
7 ** 1996-06-05 by Arthur David Olson.
8 */
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.122 2019/07/03 15:50:16 christos Exp $");
16 #endif
17 #endif /* LIBC_SCCS and not lint */
20 ** Leap second handling from Bradley White.
21 ** POSIX-style TZ environment variable handling from Guy Harris.
24 /*LINTLIBRARY*/
26 #include "namespace.h"
27 #include <assert.h>
28 #define LOCALTIME_IMPLEMENTATION
29 #include "private.h"
31 #include "tzfile.h"
32 #include <fcntl.h>
34 #if NETBSD_INSPIRED
35 # define NETBSD_INSPIRED_EXTERN
36 #else
37 # define NETBSD_INSPIRED_EXTERN static
38 #endif
40 #if defined(__weak_alias)
41 __weak_alias(daylight,_daylight)
42 __weak_alias(tzname,_tzname)
43 #endif
45 #ifndef TZ_ABBR_MAX_LEN
46 #define TZ_ABBR_MAX_LEN 16
47 #endif /* !defined TZ_ABBR_MAX_LEN */
49 #ifndef TZ_ABBR_CHAR_SET
50 #define TZ_ABBR_CHAR_SET \
51 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
52 #endif /* !defined TZ_ABBR_CHAR_SET */
54 #ifndef TZ_ABBR_ERR_CHAR
55 #define TZ_ABBR_ERR_CHAR '_'
56 #endif /* !defined TZ_ABBR_ERR_CHAR */
59 ** SunOS 4.1.1 headers lack O_BINARY.
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 */
69 #ifndef WILDABBR
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).
89 #define WILDABBR " "
90 #endif /* !defined WILDABBR */
92 static const char wildabbr[] = WILDABBR;
94 static const char gmt[] = "GMT";
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.
102 #ifndef TZDEFRULESTRING
103 #define TZDEFRULESTRING ",M3.2.0,M11.1.0"
104 #endif
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 */
114 struct lsinfo { /* leap second information */
115 time_t ls_trans; /* transition time */
116 int_fast64_t ls_corr; /* correction to apply */
119 #define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
120 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
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 */
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];
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;
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 */
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 */
164 static struct tm *gmtsub(struct state const *, time_t const *, int_fast32_t,
165 struct tm *);
166 static bool increment_overflow(int *, int);
167 static bool increment_overflow_time(time_t *, int_fast32_t);
168 static bool normalize_overflow32(int_fast32_t *, int *, int);
169 static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
170 struct tm *);
171 static bool typesequiv(struct state const *, int, int);
172 static bool tzparse(char const *, struct state *, bool);
174 static timezone_t gmtptr;
176 #ifndef TZ_STRLEN_MAX
177 #define TZ_STRLEN_MAX 255
178 #endif /* !defined TZ_STRLEN_MAX */
180 static char lcl_TZname[TZ_STRLEN_MAX + 1];
181 static int lcl_is_set;
184 #if !defined(__LIBC12_SOURCE__)
185 timezone_t __lclptr;
186 #ifdef _REENTRANT
187 rwlock_t __lcl_lock = RWLOCK_INITIALIZER;
188 #endif
189 #endif
192 ** Section 4.12.3 of X3.159-1989 requires that
193 ** Except for the strftime function, these functions [asctime,
194 ** ctime, gmtime, localtime] return values in one of two static
195 ** objects: a broken-down time structure and an array of char.
196 ** Thanks to Paul Eggert for noting this.
199 static struct tm tm;
201 #if !HAVE_POSIX_DECLS || TZ_TIME_T || defined(__NetBSD__)
202 # if !defined(__LIBC12_SOURCE__)
204 __aconst char * tzname[2] = {
205 (__aconst char *)__UNCONST(wildabbr),
206 (__aconst char *)__UNCONST(wildabbr)
209 # else
211 extern __aconst char * tzname[2];
213 # endif /* __LIBC12_SOURCE__ */
215 # if USG_COMPAT
216 # if !defined(__LIBC12_SOURCE__)
217 long timezone = 0;
218 int daylight = 0;
219 # else
220 extern int daylight;
221 extern long timezone __RENAME(__timezone13);
222 # endif /* __LIBC12_SOURCE__ */
223 # endif /* defined USG_COMPAT */
225 # ifdef ALTZONE
226 long altzone = 0;
227 # endif /* defined ALTZONE */
228 #endif /* !HAVE_POSIX_DECLS */
230 /* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX. */
231 static void
232 init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
234 s->tt_utoff = utoff;
235 s->tt_isdst = isdst;
236 s->tt_desigidx = desigidx;
237 s->tt_ttisstd = false;
238 s->tt_ttisut = false;
241 static int_fast32_t
242 detzcode(const char *const codep)
244 int_fast32_t result;
245 int i;
246 int_fast32_t one = 1;
247 int_fast32_t halfmaxval = one << (32 - 2);
248 int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
249 int_fast32_t minval = -1 - maxval;
251 result = codep[0] & 0x7f;
252 for (i = 1; i < 4; ++i)
253 result = (result << 8) | (codep[i] & 0xff);
255 if (codep[0] & 0x80) {
256 /* Do two's-complement negation even on non-two's-complement machines.
257 If the result would be minval - 1, return minval. */
258 result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
259 result += minval;
261 return result;
264 static int_fast64_t
265 detzcode64(const char *const codep)
267 int_fast64_t result;
268 int i;
269 int_fast64_t one = 1;
270 int_fast64_t halfmaxval = one << (64 - 2);
271 int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
272 int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
274 result = codep[0] & 0x7f;
275 for (i = 1; i < 8; ++i)
276 result = (result << 8) | (codep[i] & 0xff);
278 if (codep[0] & 0x80) {
279 /* Do two's-complement negation even on non-two's-complement machines.
280 If the result would be minval - 1, return minval. */
281 result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
282 result += minval;
284 return result;
287 #include <stdio.h>
289 const char *
290 tzgetname(const timezone_t sp, int isdst)
292 int i;
293 const char *name = NULL;
294 for (i = 0; i < sp->typecnt; ++i) {
295 const struct ttinfo *const ttisp = &sp->ttis[i];
296 if (ttisp->tt_isdst == isdst)
297 name = &sp->chars[ttisp->tt_desigidx];
299 if (name != NULL)
300 return name;
301 errno = ESRCH;
302 return NULL;
305 long
306 tzgetgmtoff(const timezone_t sp, int isdst)
308 int i;
309 long l = -1;
310 for (i = 0; i < sp->typecnt; ++i) {
311 const struct ttinfo *const ttisp = &sp->ttis[i];
313 if (ttisp->tt_isdst == isdst) {
314 l = ttisp->tt_utoff;
317 if (l == -1)
318 errno = ESRCH;
319 return l;
322 static void
323 scrub_abbrs(struct state *sp)
325 int i;
328 ** First, replace bogus characters.
330 for (i = 0; i < sp->charcnt; ++i)
331 if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
332 sp->chars[i] = TZ_ABBR_ERR_CHAR;
334 ** Second, truncate long abbreviations.
336 for (i = 0; i < sp->typecnt; ++i) {
337 const struct ttinfo * const ttisp = &sp->ttis[i];
338 char *cp = &sp->chars[ttisp->tt_desigidx];
340 if (strlen(cp) > TZ_ABBR_MAX_LEN &&
341 strcmp(cp, GRANDPARENTED) != 0)
342 *(cp + TZ_ABBR_MAX_LEN) = '\0';
346 static void
347 update_tzname_etc(const struct state *sp, const struct ttinfo *ttisp)
349 #if HAVE_TZNAME
350 tzname[ttisp->tt_isdst] = __UNCONST(&sp->chars[ttisp->tt_desigidx]);
351 #endif
352 #if USG_COMPAT
353 if (!ttisp->tt_isdst)
354 timezone = - ttisp->tt_utoff;
355 #endif
356 #ifdef ALTZONE
357 if (ttisp->tt_isdst)
358 altzone = - ttisp->tt_utoff;
359 #endif /* defined ALTZONE */
362 static void
363 settzname(void)
365 timezone_t const sp = __lclptr;
366 int i;
368 #if HAVE_TZNAME
369 tzname[0] = tzname[1] =
370 (__aconst char *) __UNCONST(sp ? wildabbr : gmt);
371 #endif
372 #if USG_COMPAT
373 daylight = 0;
374 timezone = 0;
375 #endif
376 #ifdef ALTZONE
377 altzone = 0;
378 #endif /* defined ALTZONE */
379 if (sp == NULL) {
380 return;
383 ** And to get the latest time zone abbreviations into tzname. . .
385 for (i = 0; i < sp->typecnt; ++i)
386 update_tzname_etc(sp, &sp->ttis[i]);
388 for (i = 0; i < sp->timecnt; ++i) {
389 const struct ttinfo * const ttisp = &sp->ttis[sp->types[i]];
390 update_tzname_etc(sp, ttisp);
391 #if USG_COMPAT
392 if (ttisp->tt_isdst)
393 daylight = 1;
394 #endif
398 static bool
399 differ_by_repeat(const time_t t1, const time_t t0)
401 if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
402 return 0;
403 return (int_fast64_t)t1 - (int_fast64_t)t0 == SECSPERREPEAT;
406 union input_buffer {
407 /* The first part of the buffer, interpreted as a header. */
408 struct tzhead tzhead;
410 /* The entire buffer. */
411 char buf[2 * sizeof(struct tzhead) + 2 * sizeof (struct state)
412 + 4 * TZ_MAX_TIMES];
415 /* TZDIR with a trailing '/' rather than a trailing '\0'. */
416 static char const tzdirslash[sizeof TZDIR] = TZDIR "/";
418 /* Local storage needed for 'tzloadbody'. */
419 union local_storage {
420 /* The results of analyzing the file's contents after it is opened. */
421 struct file_analysis {
422 /* The input buffer. */
423 union input_buffer u;
425 /* A temporary state used for parsing a TZ string in the file. */
426 struct state st;
427 } u;
429 /* The file name to be opened. */
430 char fullname[/*CONSTCOND*/BIGGEST(sizeof (struct file_analysis),
431 sizeof tzdirslash + 1024)];
434 /* Load tz data from the file named NAME into *SP. Read extended
435 format if DOEXTEND. Use *LSP for temporary storage. Return 0 on
436 success, an errno value on failure. */
437 static int
438 tzloadbody(char const *name, struct state *sp, bool doextend,
439 union local_storage *lsp)
441 int i;
442 int fid;
443 int stored;
444 ssize_t nread;
445 bool doaccess;
446 union input_buffer *up = &lsp->u.u;
447 size_t tzheadsize = sizeof(struct tzhead);
449 sp->goback = sp->goahead = false;
451 if (! name) {
452 name = TZDEFAULT;
453 if (! name)
454 return EINVAL;
457 if (name[0] == ':')
458 ++name;
459 #ifdef SUPPRESS_TZDIR
460 /* Do not prepend TZDIR. This is intended for specialized
461 applications only, due to its security implications. */
462 doaccess = true;
463 #else
464 doaccess = name[0] == '/';
465 #endif
466 if (!doaccess) {
467 char const *dot;
468 size_t namelen = strlen(name);
469 if (sizeof lsp->fullname - sizeof tzdirslash <= namelen)
470 return ENAMETOOLONG;
472 /* Create a string "TZDIR/NAME". Using sprintf here
473 would pull in stdio (and would fail if the
474 resulting string length exceeded INT_MAX!). */
475 memcpy(lsp->fullname, tzdirslash, sizeof tzdirslash);
476 strcpy(lsp->fullname + sizeof tzdirslash, name);
478 /* Set doaccess if NAME contains a ".." file name
479 component, as such a name could read a file outside
480 the TZDIR virtual subtree. */
481 for (dot = name; (dot = strchr(dot, '.')) != NULL; dot++)
482 if ((dot == name || dot[-1] == '/') && dot[1] == '.'
483 && (dot[2] == '/' || !dot[2])) {
484 doaccess = true;
485 break;
488 name = lsp->fullname;
490 if (doaccess && access(name, R_OK) != 0)
491 return errno;
493 fid = open(name, OPEN_MODE);
494 if (fid < 0)
495 return errno;
496 nread = read(fid, up->buf, sizeof up->buf);
497 if (nread < (ssize_t)tzheadsize) {
498 int err = nread < 0 ? errno : EINVAL;
499 close(fid);
500 return err;
502 if (close(fid) < 0)
503 return errno;
504 for (stored = 4; stored <= 8; stored *= 2) {
505 int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
506 int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
507 int_fast64_t prevtr = 0;
508 int_fast32_t prevcorr = 0;
509 int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
510 int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
511 int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
512 int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
513 char const *p = up->buf + tzheadsize;
514 /* Although tzfile(5) currently requires typecnt to be nonzero,
515 support future formats that may allow zero typecnt
516 in files that have a TZ string and no transitions. */
517 if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
518 && 0 <= typecnt && typecnt < TZ_MAX_TYPES
519 && 0 <= timecnt && timecnt < TZ_MAX_TIMES
520 && 0 <= charcnt && charcnt < TZ_MAX_CHARS
521 && (ttisstdcnt == typecnt || ttisstdcnt == 0)
522 && (ttisutcnt == typecnt || ttisutcnt == 0)))
523 return EINVAL;
524 if ((size_t)nread
525 < (tzheadsize /* struct tzhead */
526 + timecnt * stored /* ats */
527 + timecnt /* types */
528 + typecnt * 6 /* ttinfos */
529 + charcnt /* chars */
530 + leapcnt * (stored + 4) /* lsinfos */
531 + ttisstdcnt /* ttisstds */
532 + ttisutcnt)) /* ttisuts */
533 return EINVAL;
534 sp->leapcnt = leapcnt;
535 sp->timecnt = timecnt;
536 sp->typecnt = typecnt;
537 sp->charcnt = charcnt;
539 /* Read transitions, discarding those out of time_t range.
540 But pretend the last transition before TIME_T_MIN
541 occurred at TIME_T_MIN. */
542 timecnt = 0;
543 for (i = 0; i < sp->timecnt; ++i) {
544 int_fast64_t at
545 = stored == 4 ? detzcode(p) : detzcode64(p);
546 sp->types[i] = at <= TIME_T_MAX;
547 if (sp->types[i]) {
548 time_t attime
549 = ((TYPE_SIGNED(time_t) ?
550 at < TIME_T_MIN : at < 0)
551 ? TIME_T_MIN : (time_t)at);
552 if (timecnt && attime <= sp->ats[timecnt - 1]) {
553 if (attime < sp->ats[timecnt - 1])
554 return EINVAL;
555 sp->types[i - 1] = 0;
556 timecnt--;
558 sp->ats[timecnt++] = attime;
560 p += stored;
563 timecnt = 0;
564 for (i = 0; i < sp->timecnt; ++i) {
565 unsigned char typ = *p++;
566 if (sp->typecnt <= typ)
567 return EINVAL;
568 if (sp->types[i])
569 sp->types[timecnt++] = typ;
571 sp->timecnt = timecnt;
572 for (i = 0; i < sp->typecnt; ++i) {
573 struct ttinfo * ttisp;
574 unsigned char isdst, desigidx;
576 ttisp = &sp->ttis[i];
577 ttisp->tt_utoff = detzcode(p);
578 p += 4;
579 isdst = *p++;
580 if (! (isdst < 2))
581 return EINVAL;
582 ttisp->tt_isdst = isdst;
583 desigidx = *p++;
584 if (! (desigidx < sp->charcnt))
585 return EINVAL;
586 ttisp->tt_desigidx = desigidx;
588 for (i = 0; i < sp->charcnt; ++i)
589 sp->chars[i] = *p++;
590 sp->chars[i] = '\0'; /* ensure '\0' at end */
592 /* Read leap seconds, discarding those out of time_t range. */
593 leapcnt = 0;
594 for (i = 0; i < sp->leapcnt; ++i) {
595 int_fast64_t tr = stored == 4 ? detzcode(p) :
596 detzcode64(p);
597 int_fast32_t corr = detzcode(p + stored);
598 p += stored + 4;
599 /* Leap seconds cannot occur before the Epoch. */
600 if (tr < 0)
601 return EINVAL;
602 if (tr <= TIME_T_MAX) {
603 /* Leap seconds cannot occur more than once per UTC month,
604 and UTC months are at least 28 days long (minus 1
605 second for a negative leap second). Each leap second's
606 correction must differ from the previous one's by 1
607 second. */
608 if (tr - prevtr < 28 * SECSPERDAY - 1
609 || (corr != prevcorr - 1
610 && corr != prevcorr + 1))
611 return EINVAL;
613 sp->lsis[leapcnt].ls_trans =
614 (time_t)(prevtr = tr);
615 sp->lsis[leapcnt].ls_corr = prevcorr = corr;
616 leapcnt++;
619 sp->leapcnt = leapcnt;
621 for (i = 0; i < sp->typecnt; ++i) {
622 struct ttinfo * ttisp;
624 ttisp = &sp->ttis[i];
625 if (ttisstdcnt == 0)
626 ttisp->tt_ttisstd = false;
627 else {
628 if (*p != true && *p != false)
629 return EINVAL;
630 ttisp->tt_ttisstd = *p++;
633 for (i = 0; i < sp->typecnt; ++i) {
634 struct ttinfo * ttisp;
636 ttisp = &sp->ttis[i];
637 if (ttisutcnt == 0)
638 ttisp->tt_ttisut = false;
639 else {
640 if (*p != true && *p != false)
641 return EINVAL;
642 ttisp->tt_ttisut = *p++;
646 ** If this is an old file, we're done.
648 if (up->tzhead.tzh_version[0] == '\0')
649 break;
650 nread -= p - up->buf;
651 memmove(up->buf, p, (size_t)nread);
653 if (doextend && nread > 2 &&
654 up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
655 sp->typecnt + 2 <= TZ_MAX_TYPES) {
656 struct state *ts = &lsp->u.st;
658 up->buf[nread - 1] = '\0';
659 if (tzparse(&up->buf[1], ts, false)) {
661 /* Attempt to reuse existing abbreviations.
662 Without this, America/Anchorage would be right on
663 the edge after 2037 when TZ_MAX_CHARS is 50, as
664 sp->charcnt equals 40 (for LMT AST AWT APT AHST
665 AHDT YST AKDT AKST) and ts->charcnt equals 10
666 (for AKST AKDT). Reusing means sp->charcnt can
667 stay 40 in this example. */
668 int gotabbr = 0;
669 int charcnt = sp->charcnt;
670 for (i = 0; i < ts->typecnt; i++) {
671 char *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
672 int j;
673 for (j = 0; j < charcnt; j++)
674 if (strcmp(sp->chars + j, tsabbr) == 0) {
675 ts->ttis[i].tt_desigidx = j;
676 gotabbr++;
677 break;
679 if (! (j < charcnt)) {
680 size_t tsabbrlen = strlen(tsabbr);
681 if (j + tsabbrlen < TZ_MAX_CHARS) {
682 strcpy(sp->chars + j, tsabbr);
683 charcnt = (int_fast32_t)(j + tsabbrlen + 1);
684 ts->ttis[i].tt_desigidx = j;
685 gotabbr++;
689 if (gotabbr == ts->typecnt) {
690 sp->charcnt = charcnt;
692 /* Ignore any trailing, no-op transitions generated
693 by zic as they don't help here and can run afoul
694 of bugs in zic 2016j or earlier. */
695 while (1 < sp->timecnt
696 && (sp->types[sp->timecnt - 1]
697 == sp->types[sp->timecnt - 2]))
698 sp->timecnt--;
700 for (i = 0; i < ts->timecnt; i++)
701 if (sp->timecnt == 0
702 || sp->ats[sp->timecnt - 1] < ts->ats[i])
703 break;
704 while (i < ts->timecnt
705 && sp->timecnt < TZ_MAX_TIMES) {
706 sp->ats[sp->timecnt] = ts->ats[i];
707 sp->types[sp->timecnt] = (sp->typecnt
708 + ts->types[i]);
709 sp->timecnt++;
710 i++;
712 for (i = 0; i < ts->typecnt; i++)
713 sp->ttis[sp->typecnt++] = ts->ttis[i];
717 if (sp->typecnt == 0)
718 return EINVAL;
719 if (sp->timecnt > 1) {
720 for (i = 1; i < sp->timecnt; ++i)
721 if (typesequiv(sp, sp->types[i], sp->types[0]) &&
722 differ_by_repeat(sp->ats[i], sp->ats[0])) {
723 sp->goback = true;
724 break;
726 for (i = sp->timecnt - 2; i >= 0; --i)
727 if (typesequiv(sp, sp->types[sp->timecnt - 1],
728 sp->types[i]) &&
729 differ_by_repeat(sp->ats[sp->timecnt - 1],
730 sp->ats[i])) {
731 sp->goahead = true;
732 break;
736 /* Infer sp->defaulttype from the data. Although this default
737 type is always zero for data from recent tzdb releases,
738 things are trickier for data from tzdb 2018e or earlier.
740 The first set of heuristics work around bugs in 32-bit data
741 generated by tzdb 2013c or earlier. The workaround is for
742 zones like Australia/Macquarie where timestamps before the
743 first transition have a time type that is not the earliest
744 standard-time type. See:
745 https://mm.icann.org/pipermail/tz/2013-May/019368.html */
747 ** If type 0 is unused in transitions,
748 ** it's the type to use for early times.
750 for (i = 0; i < sp->timecnt; ++i)
751 if (sp->types[i] == 0)
752 break;
753 i = i < sp->timecnt ? -1 : 0;
755 ** Absent the above,
756 ** if there are transition times
757 ** and the first transition is to a daylight time
758 ** find the standard type less than and closest to
759 ** the type of the first transition.
761 if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) {
762 i = sp->types[0];
763 while (--i >= 0)
764 if (!sp->ttis[i].tt_isdst)
765 break;
767 /* The next heuristics are for data generated by tzdb 2018e or
768 earlier, for zones like EST5EDT where the first transition
769 is to DST. */
771 ** If no result yet, find the first standard type.
772 ** If there is none, punt to type zero.
774 if (i < 0) {
775 i = 0;
776 while (sp->ttis[i].tt_isdst)
777 if (++i >= sp->typecnt) {
778 i = 0;
779 break;
782 /* A simple 'sp->defaulttype = 0;' would suffice here if we
783 didn't have to worry about 2018e-or-earlier data. Even
784 simpler would be to remove the defaulttype member and just
785 use 0 in its place. */
786 sp->defaulttype = i;
788 return 0;
791 /* Load tz data from the file named NAME into *SP. Read extended
792 format if DOEXTEND. Return 0 on success, an errno value on failure. */
793 static int
794 tzload(char const *name, struct state *sp, bool doextend)
796 union local_storage *lsp = malloc(sizeof *lsp);
797 if (!lsp)
798 return errno;
799 else {
800 int err = tzloadbody(name, sp, doextend, lsp);
801 free(lsp);
802 return err;
806 static bool
807 typesequiv(const struct state *sp, int a, int b)
809 bool result;
811 if (sp == NULL ||
812 a < 0 || a >= sp->typecnt ||
813 b < 0 || b >= sp->typecnt)
814 result = false;
815 else {
816 const struct ttinfo * ap = &sp->ttis[a];
817 const struct ttinfo * bp = &sp->ttis[b];
818 result = (ap->tt_utoff == bp->tt_utoff
819 && ap->tt_isdst == bp->tt_isdst
820 && ap->tt_ttisstd == bp->tt_ttisstd
821 && ap->tt_ttisut == bp->tt_ttisut
822 && (strcmp(&sp->chars[ap->tt_desigidx],
823 &sp->chars[bp->tt_desigidx])
824 == 0));
826 return result;
829 static const int mon_lengths[2][MONSPERYEAR] = {
830 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
831 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
834 static const int year_lengths[2] = {
835 DAYSPERNYEAR, DAYSPERLYEAR
839 ** Given a pointer into a timezone string, scan until a character that is not
840 ** a valid character in a time zone abbreviation is found.
841 ** Return a pointer to that character.
844 static ATTRIBUTE_PURE const char *
845 getzname(const char *strp)
847 char c;
849 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
850 c != '+')
851 ++strp;
852 return strp;
856 ** Given a pointer into an extended timezone string, scan until the ending
857 ** delimiter of the time zone abbreviation is located.
858 ** Return a pointer to the delimiter.
860 ** As with getzname above, the legal character set is actually quite
861 ** restricted, with other characters producing undefined results.
862 ** We don't do any checking here; checking is done later in common-case code.
865 static ATTRIBUTE_PURE const char *
866 getqzname(const char *strp, const int delim)
868 int c;
870 while ((c = *strp) != '\0' && c != delim)
871 ++strp;
872 return strp;
876 ** Given a pointer into a timezone string, extract a number from that string.
877 ** Check that the number is within a specified range; if it is not, return
878 ** NULL.
879 ** Otherwise, return a pointer to the first character not part of the number.
882 static const char *
883 getnum(const char *strp, int *const nump, const int min, const int max)
885 char c;
886 int num;
888 if (strp == NULL || !is_digit(c = *strp)) {
889 errno = EINVAL;
890 return NULL;
892 num = 0;
893 do {
894 num = num * 10 + (c - '0');
895 if (num > max) {
896 errno = EOVERFLOW;
897 return NULL; /* illegal value */
899 c = *++strp;
900 } while (is_digit(c));
901 if (num < min) {
902 errno = EINVAL;
903 return NULL; /* illegal value */
905 *nump = num;
906 return strp;
910 ** Given a pointer into a timezone string, extract a number of seconds,
911 ** in hh[:mm[:ss]] form, from the string.
912 ** If any error occurs, return NULL.
913 ** Otherwise, return a pointer to the first character not part of the number
914 ** of seconds.
917 static const char *
918 getsecs(const char *strp, int_fast32_t *const secsp)
920 int num;
923 ** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
924 ** "M10.4.6/26", which does not conform to Posix,
925 ** but which specifies the equivalent of
926 ** "02:00 on the first Sunday on or after 23 Oct".
928 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
929 if (strp == NULL)
930 return NULL;
931 *secsp = num * (int_fast32_t) SECSPERHOUR;
932 if (*strp == ':') {
933 ++strp;
934 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
935 if (strp == NULL)
936 return NULL;
937 *secsp += num * SECSPERMIN;
938 if (*strp == ':') {
939 ++strp;
940 /* 'SECSPERMIN' allows for leap seconds. */
941 strp = getnum(strp, &num, 0, SECSPERMIN);
942 if (strp == NULL)
943 return NULL;
944 *secsp += num;
947 return strp;
951 ** Given a pointer into a timezone string, extract an offset, in
952 ** [+-]hh[:mm[:ss]] form, from the string.
953 ** If any error occurs, return NULL.
954 ** Otherwise, return a pointer to the first character not part of the time.
957 static const char *
958 getoffset(const char *strp, int_fast32_t *const offsetp)
960 bool neg = false;
962 if (*strp == '-') {
963 neg = true;
964 ++strp;
965 } else if (*strp == '+')
966 ++strp;
967 strp = getsecs(strp, offsetp);
968 if (strp == NULL)
969 return NULL; /* illegal time */
970 if (neg)
971 *offsetp = -*offsetp;
972 return strp;
976 ** Given a pointer into a timezone string, extract a rule in the form
977 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
978 ** If a valid rule is not found, return NULL.
979 ** Otherwise, return a pointer to the first character not part of the rule.
982 static const char *
983 getrule(const char *strp, struct rule *const rulep)
985 if (*strp == 'J') {
987 ** Julian day.
989 rulep->r_type = JULIAN_DAY;
990 ++strp;
991 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
992 } else if (*strp == 'M') {
994 ** Month, week, day.
996 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
997 ++strp;
998 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
999 if (strp == NULL)
1000 return NULL;
1001 if (*strp++ != '.')
1002 return NULL;
1003 strp = getnum(strp, &rulep->r_week, 1, 5);
1004 if (strp == NULL)
1005 return NULL;
1006 if (*strp++ != '.')
1007 return NULL;
1008 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
1009 } else if (is_digit(*strp)) {
1011 ** Day of year.
1013 rulep->r_type = DAY_OF_YEAR;
1014 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
1015 } else return NULL; /* invalid format */
1016 if (strp == NULL)
1017 return NULL;
1018 if (*strp == '/') {
1020 ** Time specified.
1022 ++strp;
1023 strp = getoffset(strp, &rulep->r_time);
1024 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
1025 return strp;
1029 ** Given a year, a rule, and the offset from UT at the time that rule takes
1030 ** effect, calculate the year-relative time that rule takes effect.
1033 static int_fast32_t
1034 transtime(const int year, const struct rule *const rulep,
1035 const int_fast32_t offset)
1037 bool leapyear;
1038 int_fast32_t value;
1039 int i;
1040 int d, m1, yy0, yy1, yy2, dow;
1042 INITIALIZE(value);
1043 leapyear = isleap(year);
1044 switch (rulep->r_type) {
1046 case JULIAN_DAY:
1048 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
1049 ** years.
1050 ** In non-leap years, or if the day number is 59 or less, just
1051 ** add SECSPERDAY times the day number-1 to the time of
1052 ** January 1, midnight, to get the day.
1054 value = (rulep->r_day - 1) * SECSPERDAY;
1055 if (leapyear && rulep->r_day >= 60)
1056 value += SECSPERDAY;
1057 break;
1059 case DAY_OF_YEAR:
1061 ** n - day of year.
1062 ** Just add SECSPERDAY times the day number to the time of
1063 ** January 1, midnight, to get the day.
1065 value = rulep->r_day * SECSPERDAY;
1066 break;
1068 case MONTH_NTH_DAY_OF_WEEK:
1070 ** Mm.n.d - nth "dth day" of month m.
1074 ** Use Zeller's Congruence to get day-of-week of first day of
1075 ** month.
1077 m1 = (rulep->r_mon + 9) % 12 + 1;
1078 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
1079 yy1 = yy0 / 100;
1080 yy2 = yy0 % 100;
1081 dow = ((26 * m1 - 2) / 10 +
1082 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1083 if (dow < 0)
1084 dow += DAYSPERWEEK;
1087 ** "dow" is the day-of-week of the first day of the month. Get
1088 ** the day-of-month (zero-origin) of the first "dow" day of the
1089 ** month.
1091 d = rulep->r_day - dow;
1092 if (d < 0)
1093 d += DAYSPERWEEK;
1094 for (i = 1; i < rulep->r_week; ++i) {
1095 if (d + DAYSPERWEEK >=
1096 mon_lengths[leapyear][rulep->r_mon - 1])
1097 break;
1098 d += DAYSPERWEEK;
1102 ** "d" is the day-of-month (zero-origin) of the day we want.
1104 value = d * SECSPERDAY;
1105 for (i = 0; i < rulep->r_mon - 1; ++i)
1106 value += mon_lengths[leapyear][i] * SECSPERDAY;
1107 break;
1111 ** "value" is the year-relative time of 00:00:00 UT on the day in
1112 ** question. To get the year-relative time of the specified local
1113 ** time on that day, add the transition time and the current offset
1114 ** from UT.
1116 return value + rulep->r_time + offset;
1120 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
1121 ** appropriate.
1124 static bool
1125 tzparse(const char *name, struct state *sp, bool lastditch)
1127 const char * stdname;
1128 const char * dstname;
1129 size_t stdlen;
1130 size_t dstlen;
1131 size_t charcnt;
1132 int_fast32_t stdoffset;
1133 int_fast32_t dstoffset;
1134 char * cp;
1135 bool load_ok;
1137 dstname = NULL; /* XXX gcc */
1138 stdname = name;
1139 if (lastditch) {
1140 stdlen = sizeof gmt - 1;
1141 name += stdlen;
1142 stdoffset = 0;
1143 } else {
1144 if (*name == '<') {
1145 name++;
1146 stdname = name;
1147 name = getqzname(name, '>');
1148 if (*name != '>')
1149 return false;
1150 stdlen = name - stdname;
1151 name++;
1152 } else {
1153 name = getzname(name);
1154 stdlen = name - stdname;
1156 if (!stdlen)
1157 return false;
1158 name = getoffset(name, &stdoffset);
1159 if (name == NULL)
1160 return false;
1162 charcnt = stdlen + 1;
1163 if (sizeof sp->chars < charcnt)
1164 return false;
1165 load_ok = tzload(TZDEFRULES, sp, false) == 0;
1166 if (!load_ok)
1167 sp->leapcnt = 0; /* so, we're off a little */
1168 if (*name != '\0') {
1169 if (*name == '<') {
1170 dstname = ++name;
1171 name = getqzname(name, '>');
1172 if (*name != '>')
1173 return false;
1174 dstlen = name - dstname;
1175 name++;
1176 } else {
1177 dstname = name;
1178 name = getzname(name);
1179 dstlen = name - dstname; /* length of DST abbr. */
1181 if (!dstlen)
1182 return false;
1183 charcnt += dstlen + 1;
1184 if (sizeof sp->chars < charcnt)
1185 return false;
1186 if (*name != '\0' && *name != ',' && *name != ';') {
1187 name = getoffset(name, &dstoffset);
1188 if (name == NULL)
1189 return false;
1190 } else dstoffset = stdoffset - SECSPERHOUR;
1191 if (*name == '\0' && !load_ok)
1192 name = TZDEFRULESTRING;
1193 if (*name == ',' || *name == ';') {
1194 struct rule start;
1195 struct rule end;
1196 int year;
1197 int yearlim;
1198 int timecnt;
1199 time_t janfirst;
1200 int_fast32_t janoffset = 0;
1201 int yearbeg;
1203 ++name;
1204 if ((name = getrule(name, &start)) == NULL)
1205 return false;
1206 if (*name++ != ',')
1207 return false;
1208 if ((name = getrule(name, &end)) == NULL)
1209 return false;
1210 if (*name != '\0')
1211 return false;
1212 sp->typecnt = 2; /* standard time and DST */
1214 ** Two transitions per year, from EPOCH_YEAR forward.
1216 init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1217 init_ttinfo(&sp->ttis[1], -dstoffset, true,
1218 (int)(stdlen + 1));
1219 sp->defaulttype = 0;
1220 timecnt = 0;
1221 janfirst = 0;
1222 yearbeg = EPOCH_YEAR;
1224 do {
1225 int_fast32_t yearsecs
1226 = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1227 yearbeg--;
1228 if (increment_overflow_time(&janfirst, -yearsecs)) {
1229 janoffset = -yearsecs;
1230 break;
1232 } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1234 yearlim = yearbeg + YEARSPERREPEAT + 1;
1235 for (year = yearbeg; year < yearlim; year++) {
1236 int_fast32_t
1237 starttime = transtime(year, &start, stdoffset),
1238 endtime = transtime(year, &end, dstoffset);
1239 int_fast32_t
1240 yearsecs = (year_lengths[isleap(year)]
1241 * SECSPERDAY);
1242 bool reversed = endtime < starttime;
1243 if (reversed) {
1244 int_fast32_t swap = starttime;
1245 starttime = endtime;
1246 endtime = swap;
1248 if (reversed
1249 || (starttime < endtime
1250 && (endtime - starttime
1251 < (yearsecs
1252 + (stdoffset - dstoffset))))) {
1253 if (TZ_MAX_TIMES - 2 < timecnt)
1254 break;
1255 sp->ats[timecnt] = janfirst;
1256 if (! increment_overflow_time
1257 (&sp->ats[timecnt],
1258 janoffset + starttime))
1259 sp->types[timecnt++] = !reversed;
1260 sp->ats[timecnt] = janfirst;
1261 if (! increment_overflow_time
1262 (&sp->ats[timecnt],
1263 janoffset + endtime)) {
1264 sp->types[timecnt++] = reversed;
1265 yearlim = year + YEARSPERREPEAT + 1;
1268 if (increment_overflow_time
1269 (&janfirst, janoffset + yearsecs))
1270 break;
1271 janoffset = 0;
1273 sp->timecnt = timecnt;
1274 if (! timecnt) {
1275 sp->ttis[0] = sp->ttis[1];
1276 sp->typecnt = 1; /* Perpetual DST. */
1277 } else if (YEARSPERREPEAT < year - yearbeg)
1278 sp->goback = sp->goahead = true;
1279 } else {
1280 int_fast32_t theirstdoffset;
1281 int_fast32_t theirdstoffset;
1282 int_fast32_t theiroffset;
1283 bool isdst;
1284 int i;
1285 int j;
1287 if (*name != '\0')
1288 return false;
1290 ** Initial values of theirstdoffset and theirdstoffset.
1292 theirstdoffset = 0;
1293 for (i = 0; i < sp->timecnt; ++i) {
1294 j = sp->types[i];
1295 if (!sp->ttis[j].tt_isdst) {
1296 theirstdoffset =
1297 - sp->ttis[j].tt_utoff;
1298 break;
1301 theirdstoffset = 0;
1302 for (i = 0; i < sp->timecnt; ++i) {
1303 j = sp->types[i];
1304 if (sp->ttis[j].tt_isdst) {
1305 theirdstoffset =
1306 - sp->ttis[j].tt_utoff;
1307 break;
1311 ** Initially we're assumed to be in standard time.
1313 isdst = false;
1314 theiroffset = theirstdoffset;
1316 ** Now juggle transition times and types
1317 ** tracking offsets as you do.
1319 for (i = 0; i < sp->timecnt; ++i) {
1320 j = sp->types[i];
1321 sp->types[i] = sp->ttis[j].tt_isdst;
1322 if (sp->ttis[j].tt_ttisut) {
1323 /* No adjustment to transition time */
1324 } else {
1326 ** If daylight saving time is in
1327 ** effect, and the transition time was
1328 ** not specified as standard time, add
1329 ** the daylight saving time offset to
1330 ** the transition time; otherwise, add
1331 ** the standard time offset to the
1332 ** transition time.
1335 ** Transitions from DST to DDST
1336 ** will effectively disappear since
1337 ** POSIX provides for only one DST
1338 ** offset.
1340 if (isdst && !sp->ttis[j].tt_ttisstd) {
1341 sp->ats[i] += (time_t)
1342 (dstoffset - theirdstoffset);
1343 } else {
1344 sp->ats[i] += (time_t)
1345 (stdoffset - theirstdoffset);
1348 theiroffset = -sp->ttis[j].tt_utoff;
1349 if (sp->ttis[j].tt_isdst)
1350 theirstdoffset = theiroffset;
1351 else theirdstoffset = theiroffset;
1354 ** Finally, fill in ttis.
1356 init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1357 init_ttinfo(&sp->ttis[1], -dstoffset, true,
1358 (int)(stdlen + 1));
1359 sp->typecnt = 2;
1360 sp->defaulttype = 0;
1362 } else {
1363 dstlen = 0;
1364 sp->typecnt = 1; /* only standard time */
1365 sp->timecnt = 0;
1366 init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1367 init_ttinfo(&sp->ttis[1], 0, false, 0);
1368 sp->defaulttype = 0;
1370 sp->charcnt = (int)charcnt;
1371 cp = sp->chars;
1372 (void) memcpy(cp, stdname, stdlen);
1373 cp += stdlen;
1374 *cp++ = '\0';
1375 if (dstlen != 0) {
1376 (void) memcpy(cp, dstname, dstlen);
1377 *(cp + dstlen) = '\0';
1379 return true;
1382 static void
1383 gmtload(struct state *const sp)
1385 if (tzload(gmt, sp, true) != 0)
1386 (void) tzparse(gmt, sp, true);
1389 static int
1390 zoneinit(struct state *sp, char const *name)
1392 if (name && ! name[0]) {
1394 ** User wants it fast rather than right.
1396 sp->leapcnt = 0; /* so, we're off a little */
1397 sp->timecnt = 0;
1398 sp->typecnt = 1;
1399 sp->charcnt = 0;
1400 sp->goback = sp->goahead = false;
1401 init_ttinfo(&sp->ttis[0], 0, false, 0);
1402 strcpy(sp->chars, gmt);
1403 sp->defaulttype = 0;
1404 return 0;
1405 } else {
1406 int err = tzload(name, sp, true);
1407 if (err != 0 && name && name[0] != ':' &&
1408 tzparse(name, sp, false))
1409 err = 0;
1410 if (err == 0)
1411 scrub_abbrs(sp);
1412 return err;
1416 static void
1417 tzsetlcl(char const *name)
1419 struct state *sp = __lclptr;
1420 int lcl = name ? strlen(name) < sizeof lcl_TZname : -1;
1421 if (lcl < 0 ? lcl_is_set < 0
1422 : 0 < lcl_is_set && strcmp(lcl_TZname, name) == 0)
1423 return;
1425 if (! sp)
1426 __lclptr = sp = malloc(sizeof *__lclptr);
1427 if (sp) {
1428 if (zoneinit(sp, name) != 0)
1429 zoneinit(sp, "");
1430 if (0 < lcl)
1431 strcpy(lcl_TZname, name);
1433 settzname();
1434 lcl_is_set = lcl;
1437 #ifdef STD_INSPIRED
1438 void
1439 tzsetwall(void)
1441 rwlock_wrlock(&__lcl_lock);
1442 tzsetlcl(NULL);
1443 rwlock_unlock(&__lcl_lock);
1445 #endif
1447 void
1448 tzset_unlocked(void)
1450 tzsetlcl(getenv("TZ"));
1453 void
1454 tzset(void)
1456 rwlock_wrlock(&__lcl_lock);
1457 tzset_unlocked();
1458 rwlock_unlock(&__lcl_lock);
1461 static void
1462 gmtcheck(void)
1464 static bool gmt_is_set;
1465 rwlock_wrlock(&__lcl_lock);
1466 if (! gmt_is_set) {
1467 gmtptr = malloc(sizeof *gmtptr);
1468 if (gmtptr)
1469 gmtload(gmtptr);
1470 gmt_is_set = true;
1472 rwlock_unlock(&__lcl_lock);
1475 #if NETBSD_INSPIRED
1477 timezone_t
1478 tzalloc(const char *name)
1480 timezone_t sp = malloc(sizeof *sp);
1481 if (sp) {
1482 int err = zoneinit(sp, name);
1483 if (err != 0) {
1484 free(sp);
1485 errno = err;
1486 return NULL;
1489 return sp;
1492 void
1493 tzfree(timezone_t sp)
1495 free(sp);
1499 ** NetBSD 6.1.4 has ctime_rz, but omit it because POSIX says ctime and
1500 ** ctime_r are obsolescent and have potential security problems that
1501 ** ctime_rz would share. Callers can instead use localtime_rz + strftime.
1503 ** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work
1504 ** in zones with three or more time zone abbreviations.
1505 ** Callers can instead use localtime_rz + strftime.
1508 #endif
1511 ** The easy way to behave "as if no library function calls" localtime
1512 ** is to not call it, so we drop its guts into "localsub", which can be
1513 ** freely called. (And no, the PANS doesn't require the above behavior,
1514 ** but it *is* desirable.)
1516 ** If successful and SETNAME is nonzero,
1517 ** set the applicable parts of tzname, timezone and altzone;
1518 ** however, it's OK to omit this step if the timezone is POSIX-compatible,
1519 ** since in that case tzset should have already done this step correctly.
1520 ** SETNAME's type is intfast32_t for compatibility with gmtsub,
1521 ** but it is actually a boolean and its value should be 0 or 1.
1524 /*ARGSUSED*/
1525 static struct tm *
1526 localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
1527 struct tm *const tmp)
1529 const struct ttinfo * ttisp;
1530 int i;
1531 struct tm * result;
1532 const time_t t = *timep;
1534 if (sp == NULL) {
1535 /* Don't bother to set tzname etc.; tzset has already done it. */
1536 return gmtsub(gmtptr, timep, 0, tmp);
1538 if ((sp->goback && t < sp->ats[0]) ||
1539 (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1540 time_t newt = t;
1541 time_t seconds;
1542 time_t years;
1544 if (t < sp->ats[0])
1545 seconds = sp->ats[0] - t;
1546 else seconds = t - sp->ats[sp->timecnt - 1];
1547 --seconds;
1548 years = (time_t)((seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT);
1549 seconds = (time_t)(years * AVGSECSPERYEAR);
1550 if (t < sp->ats[0])
1551 newt += seconds;
1552 else newt -= seconds;
1553 if (newt < sp->ats[0] ||
1554 newt > sp->ats[sp->timecnt - 1]) {
1555 errno = EINVAL;
1556 return NULL; /* "cannot happen" */
1558 result = localsub(sp, &newt, setname, tmp);
1559 if (result) {
1560 int_fast64_t newy;
1562 newy = result->tm_year;
1563 if (t < sp->ats[0])
1564 newy -= years;
1565 else newy += years;
1566 if (! (INT_MIN <= newy && newy <= INT_MAX)) {
1567 errno = EOVERFLOW;
1568 return NULL;
1570 result->tm_year = (int)newy;
1572 return result;
1574 if (sp->timecnt == 0 || t < sp->ats[0]) {
1575 i = sp->defaulttype;
1576 } else {
1577 int lo = 1;
1578 int hi = sp->timecnt;
1580 while (lo < hi) {
1581 int mid = (lo + hi) / 2;
1583 if (t < sp->ats[mid])
1584 hi = mid;
1585 else lo = mid + 1;
1587 i = (int) sp->types[lo - 1];
1589 ttisp = &sp->ttis[i];
1591 ** To get (wrong) behavior that's compatible with System V Release 2.0
1592 ** you'd replace the statement below with
1593 ** t += ttisp->tt_utoff;
1594 ** timesub(&t, 0L, sp, tmp);
1596 result = timesub(&t, ttisp->tt_utoff, sp, tmp);
1597 if (result) {
1598 result->tm_isdst = ttisp->tt_isdst;
1599 #ifdef TM_ZONE
1600 result->TM_ZONE = __UNCONST(&sp->chars[ttisp->tt_desigidx]);
1601 #endif /* defined TM_ZONE */
1602 if (setname)
1603 update_tzname_etc(sp, ttisp);
1605 return result;
1608 #if NETBSD_INSPIRED
1610 struct tm *
1611 localtime_rz(timezone_t sp, time_t const *timep, struct tm *tmp)
1613 return localsub(sp, timep, 0, tmp);
1616 #endif
1618 static struct tm *
1619 localtime_tzset(time_t const *timep, struct tm *tmp, bool setname)
1621 rwlock_wrlock(&__lcl_lock);
1622 if (setname || !lcl_is_set)
1623 tzset_unlocked();
1624 tmp = localsub(__lclptr, timep, setname, tmp);
1625 rwlock_unlock(&__lcl_lock);
1626 return tmp;
1629 struct tm *
1630 localtime(const time_t *timep)
1632 return localtime_tzset(timep, &tm, true);
1635 struct tm *
1636 localtime_r(const time_t * __restrict timep, struct tm *tmp)
1638 return localtime_tzset(timep, tmp, true);
1642 ** gmtsub is to gmtime as localsub is to localtime.
1645 static struct tm *
1646 gmtsub(struct state const *sp, const time_t *timep, int_fast32_t offset,
1647 struct tm *tmp)
1649 struct tm * result;
1651 result = timesub(timep, offset, gmtptr, tmp);
1652 #ifdef TM_ZONE
1654 ** Could get fancy here and deliver something such as
1655 ** "+xx" or "-xx" if offset is non-zero,
1656 ** but this is no time for a treasure hunt.
1658 if (result)
1659 result->TM_ZONE = offset ? __UNCONST(wildabbr) : gmtptr ?
1660 gmtptr->chars : __UNCONST(gmt);
1661 #endif /* defined TM_ZONE */
1662 return result;
1667 ** Re-entrant version of gmtime.
1670 struct tm *
1671 gmtime_r(const time_t *timep, struct tm *tmp)
1673 gmtcheck();
1674 return gmtsub(NULL, timep, 0, tmp);
1677 struct tm *
1678 gmtime(const time_t *timep)
1680 return gmtime_r(timep, &tm);
1682 #ifdef STD_INSPIRED
1684 struct tm *
1685 offtime(const time_t *timep, long offset)
1687 gmtcheck();
1688 return gmtsub(gmtptr, timep, (int_fast32_t)offset, &tm);
1691 struct tm *
1692 offtime_r(const time_t *timep, long offset, struct tm *tmp)
1694 gmtcheck();
1695 return gmtsub(NULL, timep, (int_fast32_t)offset, tmp);
1698 #endif /* defined STD_INSPIRED */
1700 #if TZ_TIME_T
1702 # if USG_COMPAT
1703 # define daylight 0
1704 # define timezone 0
1705 # endif
1706 # ifndef ALTZONE
1707 # define altzone 0
1708 # endif
1710 /* Convert from the underlying system's time_t to the ersatz time_tz,
1711 which is called 'time_t' in this file. Typically, this merely
1712 converts the time's integer width. On some platforms, the system
1713 time is local time not UT, or uses some epoch other than the POSIX
1714 epoch.
1716 Although this code appears to define a function named 'time' that
1717 returns time_t, the macros in private.h cause this code to actually
1718 define a function named 'tz_time' that returns tz_time_t. The call
1719 to sys_time invokes the underlying system's 'time' function. */
1721 time_t
1722 time(time_t *p)
1724 time_t r = sys_time(0);
1725 if (r != (time_t) -1) {
1726 int_fast32_t offset = EPOCH_LOCAL ? (daylight ? timezone : altzone) : 0;
1727 if (increment_overflow32(&offset, -EPOCH_OFFSET)
1728 || increment_overflow_time (&r, offset)) {
1729 errno = EOVERFLOW;
1730 r = -1;
1733 if (p)
1734 *p = r;
1735 return r;
1737 #endif
1740 ** Return the number of leap years through the end of the given year
1741 ** where, to make the math easy, the answer for year zero is defined as zero.
1743 static int
1744 leaps_thru_end_of_nonneg(int y)
1746 return y / 4 - y / 100 + y / 400;
1749 static int ATTRIBUTE_PURE
1750 leaps_thru_end_of(const int y)
1752 return (y < 0
1753 ? -1 - leaps_thru_end_of_nonneg(-1 - y)
1754 : leaps_thru_end_of_nonneg(y));
1757 static struct tm *
1758 timesub(const time_t *timep, int_fast32_t offset,
1759 const struct state *sp, struct tm *tmp)
1761 const struct lsinfo * lp;
1762 time_t tdays;
1763 int idays; /* unsigned would be so 2003 */
1764 int_fast64_t rem;
1765 int y;
1766 const int * ip;
1767 int_fast64_t corr;
1768 int hit;
1769 int i;
1771 corr = 0;
1772 hit = false;
1773 i = (sp == NULL) ? 0 : sp->leapcnt;
1774 while (--i >= 0) {
1775 lp = &sp->lsis[i];
1776 if (*timep >= lp->ls_trans) {
1777 corr = lp->ls_corr;
1778 hit = (*timep == lp->ls_trans
1779 && (i == 0 ? 0 : lp[-1].ls_corr) < corr);
1780 break;
1783 y = EPOCH_YEAR;
1784 tdays = (time_t)(*timep / SECSPERDAY);
1785 rem = *timep % SECSPERDAY;
1786 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
1787 int newy;
1788 time_t tdelta;
1789 int idelta;
1790 int leapdays;
1792 tdelta = tdays / DAYSPERLYEAR;
1793 if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
1794 && tdelta <= INT_MAX))
1795 goto out_of_range;
1796 _DIAGASSERT(__type_fit(int, tdelta));
1797 idelta = (int)tdelta;
1798 if (idelta == 0)
1799 idelta = (tdays < 0) ? -1 : 1;
1800 newy = y;
1801 if (increment_overflow(&newy, idelta))
1802 goto out_of_range;
1803 leapdays = leaps_thru_end_of(newy - 1) -
1804 leaps_thru_end_of(y - 1);
1805 tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
1806 tdays -= leapdays;
1807 y = newy;
1810 ** Given the range, we can now fearlessly cast...
1812 idays = (int) tdays;
1813 rem += offset - corr;
1814 while (rem < 0) {
1815 rem += SECSPERDAY;
1816 --idays;
1818 while (rem >= SECSPERDAY) {
1819 rem -= SECSPERDAY;
1820 ++idays;
1822 while (idays < 0) {
1823 if (increment_overflow(&y, -1))
1824 goto out_of_range;
1825 idays += year_lengths[isleap(y)];
1827 while (idays >= year_lengths[isleap(y)]) {
1828 idays -= year_lengths[isleap(y)];
1829 if (increment_overflow(&y, 1))
1830 goto out_of_range;
1832 tmp->tm_year = y;
1833 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
1834 goto out_of_range;
1835 tmp->tm_yday = idays;
1837 ** The "extra" mods below avoid overflow problems.
1839 tmp->tm_wday = EPOCH_WDAY +
1840 ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1841 (DAYSPERNYEAR % DAYSPERWEEK) +
1842 leaps_thru_end_of(y - 1) -
1843 leaps_thru_end_of(EPOCH_YEAR - 1) +
1844 idays;
1845 tmp->tm_wday %= DAYSPERWEEK;
1846 if (tmp->tm_wday < 0)
1847 tmp->tm_wday += DAYSPERWEEK;
1848 tmp->tm_hour = (int) (rem / SECSPERHOUR);
1849 rem %= SECSPERHOUR;
1850 tmp->tm_min = (int) (rem / SECSPERMIN);
1852 ** A positive leap second requires a special
1853 ** representation. This uses "... ??:59:60" et seq.
1855 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1856 ip = mon_lengths[isleap(y)];
1857 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1858 idays -= ip[tmp->tm_mon];
1859 tmp->tm_mday = (int) (idays + 1);
1860 tmp->tm_isdst = 0;
1861 #ifdef TM_GMTOFF
1862 tmp->TM_GMTOFF = offset;
1863 #endif /* defined TM_GMTOFF */
1864 return tmp;
1865 out_of_range:
1866 errno = EOVERFLOW;
1867 return NULL;
1870 char *
1871 ctime(const time_t *timep)
1874 ** Section 4.12.3.2 of X3.159-1989 requires that
1875 ** The ctime function converts the calendar time pointed to by timer
1876 ** to local time in the form of a string. It is equivalent to
1877 ** asctime(localtime(timer))
1879 struct tm *tmp = localtime(timep);
1880 return tmp ? asctime(tmp) : NULL;
1883 char *
1884 ctime_r(const time_t *timep, char *buf)
1886 struct tm mytm;
1887 struct tm *tmp = localtime_r(timep, &mytm);
1888 return tmp ? asctime_r(tmp, buf) : NULL;
1891 char *
1892 ctime_rz(const timezone_t sp, const time_t * timep, char *buf)
1894 struct tm mytm, *rtm;
1896 rtm = localtime_rz(sp, timep, &mytm);
1897 if (rtm == NULL)
1898 return NULL;
1899 return asctime_r(rtm, buf);
1903 ** Adapted from code provided by Robert Elz, who writes:
1904 ** The "best" way to do mktime I think is based on an idea of Bob
1905 ** Kridle's (so its said...) from a long time ago.
1906 ** It does a binary search of the time_t space. Since time_t's are
1907 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1908 ** would still be very reasonable).
1911 #ifndef WRONG
1912 #define WRONG ((time_t)-1)
1913 #endif /* !defined WRONG */
1916 ** Normalize logic courtesy Paul Eggert.
1919 static bool
1920 increment_overflow(int *ip, int j)
1922 int const i = *ip;
1925 ** If i >= 0 there can only be overflow if i + j > INT_MAX
1926 ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1927 ** If i < 0 there can only be overflow if i + j < INT_MIN
1928 ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1930 if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
1931 return true;
1932 *ip += j;
1933 return false;
1936 static bool
1937 increment_overflow32(int_fast32_t *const lp, int const m)
1939 int_fast32_t const l = *lp;
1941 if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
1942 return true;
1943 *lp += m;
1944 return false;
1947 static bool
1948 increment_overflow_time(time_t *tp, int_fast32_t j)
1951 ** This is like
1952 ** 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
1953 ** except that it does the right thing even if *tp + j would overflow.
1955 if (! (j < 0
1956 ? (TYPE_SIGNED(time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
1957 : *tp <= TIME_T_MAX - j))
1958 return true;
1959 *tp += j;
1960 return false;
1963 static bool
1964 normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
1966 int tensdelta;
1968 tensdelta = (*unitsptr >= 0) ?
1969 (*unitsptr / base) :
1970 (-1 - (-1 - *unitsptr) / base);
1971 *unitsptr -= tensdelta * base;
1972 return increment_overflow(tensptr, tensdelta);
1975 static bool
1976 normalize_overflow32(int_fast32_t *tensptr, int *unitsptr, int base)
1978 int tensdelta;
1980 tensdelta = (*unitsptr >= 0) ?
1981 (*unitsptr / base) :
1982 (-1 - (-1 - *unitsptr) / base);
1983 *unitsptr -= tensdelta * base;
1984 return increment_overflow32(tensptr, tensdelta);
1987 static int
1988 tmcomp(const struct tm *const atmp,
1989 const struct tm *const btmp)
1991 int result;
1993 if (atmp->tm_year != btmp->tm_year)
1994 return atmp->tm_year < btmp->tm_year ? -1 : 1;
1995 if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1996 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1997 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1998 (result = (atmp->tm_min - btmp->tm_min)) == 0)
1999 result = atmp->tm_sec - btmp->tm_sec;
2000 return result;
2003 static time_t
2004 time2sub(struct tm *const tmp,
2005 struct tm *(*funcp)(struct state const *, time_t const *,
2006 int_fast32_t, struct tm *),
2007 struct state const *sp,
2008 const int_fast32_t offset,
2009 bool *okayp,
2010 bool do_norm_secs)
2012 int dir;
2013 int i, j;
2014 int saved_seconds;
2015 int_fast32_t li;
2016 time_t lo;
2017 time_t hi;
2018 #ifdef NO_ERROR_IN_DST_GAP
2019 time_t ilo;
2020 #endif
2021 int_fast32_t y;
2022 time_t newt;
2023 time_t t;
2024 struct tm yourtm, mytm;
2026 *okayp = false;
2027 yourtm = *tmp;
2028 #ifdef NO_ERROR_IN_DST_GAP
2029 again:
2030 #endif
2031 if (do_norm_secs) {
2032 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
2033 SECSPERMIN))
2034 goto out_of_range;
2036 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
2037 goto out_of_range;
2038 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
2039 goto out_of_range;
2040 y = yourtm.tm_year;
2041 if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
2042 goto out_of_range;
2044 ** Turn y into an actual year number for now.
2045 ** It is converted back to an offset from TM_YEAR_BASE later.
2047 if (increment_overflow32(&y, TM_YEAR_BASE))
2048 goto out_of_range;
2049 while (yourtm.tm_mday <= 0) {
2050 if (increment_overflow32(&y, -1))
2051 goto out_of_range;
2052 li = y + (1 < yourtm.tm_mon);
2053 yourtm.tm_mday += year_lengths[isleap(li)];
2055 while (yourtm.tm_mday > DAYSPERLYEAR) {
2056 li = y + (1 < yourtm.tm_mon);
2057 yourtm.tm_mday -= year_lengths[isleap(li)];
2058 if (increment_overflow32(&y, 1))
2059 goto out_of_range;
2061 for ( ; ; ) {
2062 i = mon_lengths[isleap(y)][yourtm.tm_mon];
2063 if (yourtm.tm_mday <= i)
2064 break;
2065 yourtm.tm_mday -= i;
2066 if (++yourtm.tm_mon >= MONSPERYEAR) {
2067 yourtm.tm_mon = 0;
2068 if (increment_overflow32(&y, 1))
2069 goto out_of_range;
2072 if (increment_overflow32(&y, -TM_YEAR_BASE))
2073 goto out_of_range;
2074 if (! (INT_MIN <= y && y <= INT_MAX))
2075 goto out_of_range;
2076 yourtm.tm_year = (int)y;
2077 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
2078 saved_seconds = 0;
2079 else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
2081 ** We can't set tm_sec to 0, because that might push the
2082 ** time below the minimum representable time.
2083 ** Set tm_sec to 59 instead.
2084 ** This assumes that the minimum representable time is
2085 ** not in the same minute that a leap second was deleted from,
2086 ** which is a safer assumption than using 58 would be.
2088 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
2089 goto out_of_range;
2090 saved_seconds = yourtm.tm_sec;
2091 yourtm.tm_sec = SECSPERMIN - 1;
2092 } else {
2093 saved_seconds = yourtm.tm_sec;
2094 yourtm.tm_sec = 0;
2097 ** Do a binary search (this works whatever time_t's type is).
2099 lo = TIME_T_MIN;
2100 hi = TIME_T_MAX;
2101 #ifdef NO_ERROR_IN_DST_GAP
2102 ilo = lo;
2103 #endif
2104 for ( ; ; ) {
2105 t = lo / 2 + hi / 2;
2106 if (t < lo)
2107 t = lo;
2108 else if (t > hi)
2109 t = hi;
2110 if (! funcp(sp, &t, offset, &mytm)) {
2112 ** Assume that t is too extreme to be represented in
2113 ** a struct tm; arrange things so that it is less
2114 ** extreme on the next pass.
2116 dir = (t > 0) ? 1 : -1;
2117 } else dir = tmcomp(&mytm, &yourtm);
2118 if (dir != 0) {
2119 if (t == lo) {
2120 if (t == TIME_T_MAX)
2121 goto out_of_range;
2122 ++t;
2123 ++lo;
2124 } else if (t == hi) {
2125 if (t == TIME_T_MIN)
2126 goto out_of_range;
2127 --t;
2128 --hi;
2130 #ifdef NO_ERROR_IN_DST_GAP
2131 if (ilo != lo && lo - 1 == hi && yourtm.tm_isdst < 0 &&
2132 do_norm_secs) {
2133 for (i = sp->typecnt - 1; i >= 0; --i) {
2134 for (j = sp->typecnt - 1; j >= 0; --j) {
2135 time_t off;
2136 if (sp->ttis[j].tt_isdst ==
2137 sp->ttis[i].tt_isdst)
2138 continue;
2139 off = sp->ttis[j].tt_utoff -
2140 sp->ttis[i].tt_utoff;
2141 yourtm.tm_sec += off < 0 ?
2142 -off : off;
2143 goto again;
2147 #endif
2148 if (lo > hi)
2149 goto invalid;
2150 if (dir > 0)
2151 hi = t;
2152 else lo = t;
2153 continue;
2155 #if defined TM_GMTOFF && ! UNINIT_TRAP
2156 if (mytm.TM_GMTOFF != yourtm.TM_GMTOFF
2157 && (yourtm.TM_GMTOFF < 0
2158 ? (-SECSPERDAY <= yourtm.TM_GMTOFF
2159 && (mytm.TM_GMTOFF <=
2160 (/*CONSTCOND*/SMALLEST (INT_FAST32_MAX, LONG_MAX)
2161 + yourtm.TM_GMTOFF)))
2162 : (yourtm.TM_GMTOFF <= SECSPERDAY
2163 && ((/*CONSTCOND*/BIGGEST (INT_FAST32_MIN, LONG_MIN)
2164 + yourtm.TM_GMTOFF)
2165 <= mytm.TM_GMTOFF)))) {
2166 /* MYTM matches YOURTM except with the wrong UT offset.
2167 YOURTM.TM_GMTOFF is plausible, so try it instead.
2168 It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
2169 since the guess gets checked. */
2170 time_t altt = t;
2171 int_fast32_t diff = (int_fast32_t)
2172 (mytm.TM_GMTOFF - yourtm.TM_GMTOFF);
2173 if (!increment_overflow_time(&altt, diff)) {
2174 struct tm alttm;
2175 if (! funcp(sp, &altt, offset, &alttm)
2176 && alttm.tm_isdst == mytm.tm_isdst
2177 && alttm.TM_GMTOFF == yourtm.TM_GMTOFF
2178 && tmcomp(&alttm, &yourtm)) {
2179 t = altt;
2180 mytm = alttm;
2184 #endif
2185 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
2186 break;
2188 ** Right time, wrong type.
2189 ** Hunt for right time, right type.
2190 ** It's okay to guess wrong since the guess
2191 ** gets checked.
2193 if (sp == NULL)
2194 goto invalid;
2195 for (i = sp->typecnt - 1; i >= 0; --i) {
2196 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
2197 continue;
2198 for (j = sp->typecnt - 1; j >= 0; --j) {
2199 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
2200 continue;
2201 newt = (time_t)(t + sp->ttis[j].tt_utoff -
2202 sp->ttis[i].tt_utoff);
2203 if (! funcp(sp, &newt, offset, &mytm))
2204 continue;
2205 if (tmcomp(&mytm, &yourtm) != 0)
2206 continue;
2207 if (mytm.tm_isdst != yourtm.tm_isdst)
2208 continue;
2210 ** We have a match.
2212 t = newt;
2213 goto label;
2216 goto invalid;
2218 label:
2219 newt = t + saved_seconds;
2220 if ((newt < t) != (saved_seconds < 0))
2221 goto out_of_range;
2222 t = newt;
2223 if (funcp(sp, &t, offset, tmp)) {
2224 *okayp = true;
2225 return t;
2227 out_of_range:
2228 errno = EOVERFLOW;
2229 return WRONG;
2230 invalid:
2231 errno = EINVAL;
2232 return WRONG;
2235 static time_t
2236 time2(struct tm * const tmp,
2237 struct tm *(*funcp)(struct state const *, time_t const *,
2238 int_fast32_t, struct tm *),
2239 struct state const *sp,
2240 const int_fast32_t offset,
2241 bool *okayp)
2243 time_t t;
2246 ** First try without normalization of seconds
2247 ** (in case tm_sec contains a value associated with a leap second).
2248 ** If that fails, try with normalization of seconds.
2250 t = time2sub(tmp, funcp, sp, offset, okayp, false);
2251 return *okayp ? t : time2sub(tmp, funcp, sp, offset, okayp, true);
2254 static time_t
2255 time1(struct tm *const tmp,
2256 struct tm *(*funcp) (struct state const *, time_t const *,
2257 int_fast32_t, struct tm *),
2258 struct state const *sp,
2259 const int_fast32_t offset)
2261 time_t t;
2262 int samei, otheri;
2263 int sameind, otherind;
2264 int i;
2265 int nseen;
2266 int save_errno;
2267 char seen[TZ_MAX_TYPES];
2268 unsigned char types[TZ_MAX_TYPES];
2269 bool okay;
2271 if (tmp == NULL) {
2272 errno = EINVAL;
2273 return WRONG;
2275 if (tmp->tm_isdst > 1)
2276 tmp->tm_isdst = 1;
2277 save_errno = errno;
2278 t = time2(tmp, funcp, sp, offset, &okay);
2279 if (okay) {
2280 errno = save_errno;
2281 return t;
2283 if (tmp->tm_isdst < 0)
2284 #ifdef PCTS
2286 ** POSIX Conformance Test Suite code courtesy Grant Sullivan.
2288 tmp->tm_isdst = 0; /* reset to std and try again */
2289 #else
2290 return t;
2291 #endif /* !defined PCTS */
2293 ** We're supposed to assume that somebody took a time of one type
2294 ** and did some math on it that yielded a "struct tm" that's bad.
2295 ** We try to divine the type they started from and adjust to the
2296 ** type they need.
2298 if (sp == NULL) {
2299 errno = EINVAL;
2300 return WRONG;
2302 for (i = 0; i < sp->typecnt; ++i)
2303 seen[i] = false;
2304 nseen = 0;
2305 for (i = sp->timecnt - 1; i >= 0; --i)
2306 if (!seen[sp->types[i]]) {
2307 seen[sp->types[i]] = true;
2308 types[nseen++] = sp->types[i];
2310 for (sameind = 0; sameind < nseen; ++sameind) {
2311 samei = types[sameind];
2312 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2313 continue;
2314 for (otherind = 0; otherind < nseen; ++otherind) {
2315 otheri = types[otherind];
2316 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2317 continue;
2318 tmp->tm_sec += (int)(sp->ttis[otheri].tt_utoff -
2319 sp->ttis[samei].tt_utoff);
2320 tmp->tm_isdst = !tmp->tm_isdst;
2321 t = time2(tmp, funcp, sp, offset, &okay);
2322 if (okay) {
2323 errno = save_errno;
2324 return t;
2326 tmp->tm_sec -= (int)(sp->ttis[otheri].tt_utoff -
2327 sp->ttis[samei].tt_utoff);
2328 tmp->tm_isdst = !tmp->tm_isdst;
2331 errno = EOVERFLOW;
2332 return WRONG;
2335 static time_t
2336 mktime_tzname(timezone_t sp, struct tm *tmp, bool setname)
2338 if (sp)
2339 return time1(tmp, localsub, sp, setname);
2340 else {
2341 gmtcheck();
2342 return time1(tmp, gmtsub, gmtptr, 0);
2346 #if NETBSD_INSPIRED
2348 time_t
2349 mktime_z(timezone_t sp, struct tm *const tmp)
2351 return mktime_tzname(sp, tmp, false);
2354 #endif
2356 time_t
2357 mktime(struct tm *tmp)
2359 time_t t;
2361 rwlock_wrlock(&__lcl_lock);
2362 tzset_unlocked();
2363 t = mktime_tzname(__lclptr, tmp, true);
2364 rwlock_unlock(&__lcl_lock);
2365 return t;
2368 #ifdef STD_INSPIRED
2370 time_t
2371 timelocal_z(const timezone_t sp, struct tm *const tmp)
2373 if (tmp != NULL)
2374 tmp->tm_isdst = -1; /* in case it wasn't initialized */
2375 return mktime_z(sp, tmp);
2378 time_t
2379 timelocal(struct tm *tmp)
2381 if (tmp != NULL)
2382 tmp->tm_isdst = -1; /* in case it wasn't initialized */
2383 return mktime(tmp);
2386 time_t
2387 timegm(struct tm *tmp)
2390 return timeoff(tmp, 0);
2393 time_t
2394 timeoff(struct tm *tmp, long offset)
2396 if (tmp)
2397 tmp->tm_isdst = 0;
2398 gmtcheck();
2399 return time1(tmp, gmtsub, gmtptr, (int_fast32_t)offset);
2402 #endif /* defined STD_INSPIRED */
2405 ** XXX--is the below the right way to conditionalize??
2408 #ifdef STD_INSPIRED
2411 ** IEEE Std 1003.1 (POSIX) says that 536457599
2412 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2413 ** is not the case if we are accounting for leap seconds.
2414 ** So, we provide the following conversion routines for use
2415 ** when exchanging timestamps with POSIX conforming systems.
2418 static int_fast64_t
2419 leapcorr(const timezone_t sp, time_t t)
2421 struct lsinfo const * lp;
2422 int i;
2424 i = sp->leapcnt;
2425 while (--i >= 0) {
2426 lp = &sp->lsis[i];
2427 if (t >= lp->ls_trans)
2428 return lp->ls_corr;
2430 return 0;
2433 NETBSD_INSPIRED_EXTERN time_t
2434 time2posix_z(timezone_t sp, time_t t)
2436 return (time_t)(t - leapcorr(sp, t));
2439 time_t
2440 time2posix(time_t t)
2442 rwlock_wrlock(&__lcl_lock);
2443 if (!lcl_is_set)
2444 tzset_unlocked();
2445 if (__lclptr)
2446 t = (time_t)(t - leapcorr(__lclptr, t));
2447 rwlock_unlock(&__lcl_lock);
2448 return t;
2451 NETBSD_INSPIRED_EXTERN time_t
2452 posix2time_z(timezone_t sp, time_t t)
2454 time_t x;
2455 time_t y;
2458 ** For a positive leap second hit, the result
2459 ** is not unique. For a negative leap second
2460 ** hit, the corresponding time doesn't exist,
2461 ** so we return an adjacent second.
2463 x = (time_t)(t + leapcorr(sp, t));
2464 y = (time_t)(x - leapcorr(sp, x));
2465 if (y < t) {
2466 do {
2467 x++;
2468 y = (time_t)(x - leapcorr(sp, x));
2469 } while (y < t);
2470 x -= y != t;
2471 } else if (y > t) {
2472 do {
2473 --x;
2474 y = (time_t)(x - leapcorr(sp, x));
2475 } while (y > t);
2476 x += y != t;
2478 return x;
2481 time_t
2482 posix2time(time_t t)
2484 rwlock_wrlock(&__lcl_lock);
2485 if (!lcl_is_set)
2486 tzset_unlocked();
2487 if (__lclptr)
2488 t = posix2time_z(__lclptr, t);
2489 rwlock_unlock(&__lcl_lock);
2490 return t;
2493 #endif /* defined STD_INSPIRED */