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