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