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