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