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