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