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