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