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