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