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