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