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