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