localtime.c revision 174766
1/* 2** This file is in the public domain, so clarified as of 3** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). 4*/ 5 6#include <sys/cdefs.h> 7#ifndef lint 8#ifndef NOID 9static char elsieid[] __unused = "@(#)localtime.c 7.78"; 10#endif /* !defined NOID */ 11#endif /* !defined lint */ 12__FBSDID("$FreeBSD: head/lib/libc/stdtime/localtime.c 174766 2007-12-19 04:30:10Z imp $"); 13 14/* 15** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu). 16** POSIX-style TZ environment variable handling from Guy Harris 17** (guy@auspex.com). 18*/ 19 20/*LINTLIBRARY*/ 21 22#include "namespace.h" 23#include <sys/types.h> 24#include <sys/stat.h> 25#include <fcntl.h> 26#include <pthread.h> 27#include "private.h" 28#include "un-namespace.h" 29 30#include "tzfile.h" 31 32#include "libc_private.h" 33 34#define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x) 35#define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x) 36 37/* 38** SunOS 4.1.1 headers lack O_BINARY. 39*/ 40 41#ifdef O_BINARY 42#define OPEN_MODE (O_RDONLY | O_BINARY) 43#endif /* defined O_BINARY */ 44#ifndef O_BINARY 45#define OPEN_MODE O_RDONLY 46#endif /* !defined O_BINARY */ 47 48#ifndef WILDABBR 49/* 50** Someone might make incorrect use of a time zone abbreviation: 51** 1. They might reference tzname[0] before calling tzset (explicitly 52** or implicitly). 53** 2. They might reference tzname[1] before calling tzset (explicitly 54** or implicitly). 55** 3. They might reference tzname[1] after setting to a time zone 56** in which Daylight Saving Time is never observed. 57** 4. They might reference tzname[0] after setting to a time zone 58** in which Standard Time is never observed. 59** 5. They might reference tm.TM_ZONE after calling offtime. 60** What's best to do in the above cases is open to debate; 61** for now, we just set things up so that in any of the five cases 62** WILDABBR is used. Another possibility: initialize tzname[0] to the 63** string "tzname[0] used before set", and similarly for the other cases. 64** And another: initialize tzname[0] to "ERA", with an explanation in the 65** manual page of what this "time zone abbreviation" means (doing this so 66** that tzname[0] has the "normal" length of three characters). 67*/ 68#define WILDABBR " " 69#endif /* !defined WILDABBR */ 70 71static char wildabbr[] = "WILDABBR"; 72 73/* 74 * In June 2004 it was decided UTC was a more appropriate default time 75 * zone than GMT. 76 */ 77 78static const char gmt[] = "UTC"; 79 80/* 81** The DST rules to use if TZ has no rules and we can't load TZDEFRULES. 82** We default to US rules as of 1999-08-17. 83** POSIX 1003.1 section 8.1.1 says that the default DST rules are 84** implementation dependent; for historical reasons, US rules are a 85** common default. 86*/ 87#ifndef TZDEFRULESTRING 88#define TZDEFRULESTRING ",M4.1.0,M10.5.0" 89#endif /* !defined TZDEFDST */ 90 91struct ttinfo { /* time type information */ 92 long tt_gmtoff; /* UTC offset in seconds */ 93 int tt_isdst; /* used to set tm_isdst */ 94 int tt_abbrind; /* abbreviation list index */ 95 int tt_ttisstd; /* TRUE if transition is std time */ 96 int tt_ttisgmt; /* TRUE if transition is UTC */ 97}; 98 99struct lsinfo { /* leap second information */ 100 time_t ls_trans; /* transition time */ 101 long ls_corr; /* correction to apply */ 102}; 103 104#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) 105 106#ifdef TZNAME_MAX 107#define MY_TZNAME_MAX TZNAME_MAX 108#endif /* defined TZNAME_MAX */ 109#ifndef TZNAME_MAX 110#define MY_TZNAME_MAX 255 111#endif /* !defined TZNAME_MAX */ 112 113struct state { 114 int leapcnt; 115 int timecnt; 116 int typecnt; 117 int charcnt; 118 time_t ats[TZ_MAX_TIMES]; 119 unsigned char types[TZ_MAX_TIMES]; 120 struct ttinfo ttis[TZ_MAX_TYPES]; 121 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), 122 (2 * (MY_TZNAME_MAX + 1)))]; 123 struct lsinfo lsis[TZ_MAX_LEAPS]; 124}; 125 126struct rule { 127 int r_type; /* type of rule--see below */ 128 int r_day; /* day number of rule */ 129 int r_week; /* week number of rule */ 130 int r_mon; /* month number of rule */ 131 long r_time; /* transition time of rule */ 132}; 133 134#define JULIAN_DAY 0 /* Jn - Julian day */ 135#define DAY_OF_YEAR 1 /* n - day of year */ 136#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */ 137 138/* 139** Prototypes for static functions. 140*/ 141 142static long detzcode(const char * codep); 143static const char * getzname(const char * strp); 144static const char * getnum(const char * strp, int * nump, int min, 145 int max); 146static const char * getsecs(const char * strp, long * secsp); 147static const char * getoffset(const char * strp, long * offsetp); 148static const char * getrule(const char * strp, struct rule * rulep); 149static void gmtload(struct state * sp); 150static void gmtsub(const time_t * timep, long offset, 151 struct tm * tmp); 152static void localsub(const time_t * timep, long offset, 153 struct tm * tmp); 154static int increment_overflow(int * number, int delta); 155static int normalize_overflow(int * tensptr, int * unitsptr, 156 int base); 157static void settzname(void); 158static time_t time1(struct tm * tmp, 159 void(*funcp) (const time_t *, 160 long, struct tm *), 161 long offset); 162static time_t time2(struct tm *tmp, 163 void(*funcp) (const time_t *, 164 long, struct tm*), 165 long offset, int * okayp); 166static time_t time2sub(struct tm *tmp, 167 void(*funcp) (const time_t *, 168 long, struct tm*), 169 long offset, int * okayp, int do_norm_secs); 170static void timesub(const time_t * timep, long offset, 171 const struct state * sp, struct tm * tmp); 172static int tmcomp(const struct tm * atmp, 173 const struct tm * btmp); 174static time_t transtime(time_t janfirst, int year, 175 const struct rule * rulep, long offset); 176static int tzload(const char * name, struct state * sp); 177static int tzparse(const char * name, struct state * sp, 178 int lastditch); 179 180#ifdef ALL_STATE 181static struct state * lclptr; 182static struct state * gmtptr; 183#endif /* defined ALL_STATE */ 184 185#ifndef ALL_STATE 186static struct state lclmem; 187static struct state gmtmem; 188#define lclptr (&lclmem) 189#define gmtptr (&gmtmem) 190#endif /* State Farm */ 191 192#ifndef TZ_STRLEN_MAX 193#define TZ_STRLEN_MAX 255 194#endif /* !defined TZ_STRLEN_MAX */ 195 196static char lcl_TZname[TZ_STRLEN_MAX + 1]; 197static int lcl_is_set; 198static int gmt_is_set; 199static pthread_mutex_t lcl_mutex = PTHREAD_MUTEX_INITIALIZER; 200static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER; 201 202char * tzname[2] = { 203 wildabbr, 204 wildabbr 205}; 206 207/* 208** Section 4.12.3 of X3.159-1989 requires that 209** Except for the strftime function, these functions [asctime, 210** ctime, gmtime, localtime] return values in one of two static 211** objects: a broken-down time structure and an array of char. 212** Thanks to Paul Eggert (eggert@twinsun.com) for noting this. 213*/ 214 215static struct tm tm; 216 217#ifdef USG_COMPAT 218time_t timezone = 0; 219int daylight = 0; 220#endif /* defined USG_COMPAT */ 221 222#ifdef ALTZONE 223time_t altzone = 0; 224#endif /* defined ALTZONE */ 225 226static long 227detzcode(codep) 228const char * const codep; 229{ 230 long result; 231 int i; 232 233 result = (codep[0] & 0x80) ? ~0L : 0L; 234 for (i = 0; i < 4; ++i) 235 result = (result << 8) | (codep[i] & 0xff); 236 return result; 237} 238 239static void 240settzname(void) 241{ 242 struct state * sp = lclptr; 243 int i; 244 245 tzname[0] = wildabbr; 246 tzname[1] = wildabbr; 247#ifdef USG_COMPAT 248 daylight = 0; 249 timezone = 0; 250#endif /* defined USG_COMPAT */ 251#ifdef ALTZONE 252 altzone = 0; 253#endif /* defined ALTZONE */ 254#ifdef ALL_STATE 255 if (sp == NULL) { 256 tzname[0] = tzname[1] = gmt; 257 return; 258 } 259#endif /* defined ALL_STATE */ 260 for (i = 0; i < sp->typecnt; ++i) { 261 const struct ttinfo * const ttisp = &sp->ttis[i]; 262 263 tzname[ttisp->tt_isdst] = 264 &sp->chars[ttisp->tt_abbrind]; 265#ifdef USG_COMPAT 266 if (ttisp->tt_isdst) 267 daylight = 1; 268 if (i == 0 || !ttisp->tt_isdst) 269 timezone = -(ttisp->tt_gmtoff); 270#endif /* defined USG_COMPAT */ 271#ifdef ALTZONE 272 if (i == 0 || ttisp->tt_isdst) 273 altzone = -(ttisp->tt_gmtoff); 274#endif /* defined ALTZONE */ 275 } 276 /* 277 ** And to get the latest zone names into tzname. . . 278 */ 279 for (i = 0; i < sp->timecnt; ++i) { 280 const struct ttinfo * const ttisp = 281 &sp->ttis[ 282 sp->types[i]]; 283 284 tzname[ttisp->tt_isdst] = 285 &sp->chars[ttisp->tt_abbrind]; 286 } 287} 288 289static int 290tzload(name, sp) 291const char * name; 292struct state * const sp; 293{ 294 const char * p; 295 int i; 296 int fid; 297 298 /* XXX The following is from OpenBSD, and I'm not sure it is correct */ 299 if (name != NULL && issetugid() != 0) 300 if ((name[0] == ':' && name[1] == '/') || 301 name[0] == '/' || strchr(name, '.')) 302 name = NULL; 303 if (name == NULL && (name = TZDEFAULT) == NULL) 304 return -1; 305 { 306 int doaccess; 307 struct stat stab; 308 /* 309 ** Section 4.9.1 of the C standard says that 310 ** "FILENAME_MAX expands to an integral constant expression 311 ** that is the size needed for an array of char large enough 312 ** to hold the longest file name string that the implementation 313 ** guarantees can be opened." 314 */ 315 char fullname[FILENAME_MAX + 1]; 316 317 if (name[0] == ':') 318 ++name; 319 doaccess = name[0] == '/'; 320 if (!doaccess) { 321 if ((p = TZDIR) == NULL) 322 return -1; 323 if ((strlen(p) + 1 + strlen(name) + 1) >= sizeof fullname) 324 return -1; 325 (void) strcpy(fullname, p); 326 (void) strcat(fullname, "/"); 327 (void) strcat(fullname, name); 328 /* 329 ** Set doaccess if '.' (as in "../") shows up in name. 330 */ 331 if (strchr(name, '.') != NULL) 332 doaccess = TRUE; 333 name = fullname; 334 } 335 if (doaccess && access(name, R_OK) != 0) 336 return -1; 337 if ((fid = _open(name, OPEN_MODE)) == -1) 338 return -1; 339 if ((_fstat(fid, &stab) < 0) || !S_ISREG(stab.st_mode)) { 340 _close(fid); 341 return -1; 342 } 343 } 344 { 345 struct tzhead * tzhp; 346 union { 347 struct tzhead tzhead; 348 char buf[sizeof *sp + sizeof *tzhp]; 349 } u; 350 int ttisstdcnt; 351 int ttisgmtcnt; 352 353 i = _read(fid, u.buf, sizeof u.buf); 354 if (_close(fid) != 0) 355 return -1; 356 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); 357 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); 358 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); 359 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); 360 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); 361 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); 362 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; 363 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || 364 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || 365 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || 366 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || 367 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || 368 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) 369 return -1; 370 if (i - (p - u.buf) < sp->timecnt * 4 + /* ats */ 371 sp->timecnt + /* types */ 372 sp->typecnt * (4 + 2) + /* ttinfos */ 373 sp->charcnt + /* chars */ 374 sp->leapcnt * (4 + 4) + /* lsinfos */ 375 ttisstdcnt + /* ttisstds */ 376 ttisgmtcnt) /* ttisgmts */ 377 return -1; 378 for (i = 0; i < sp->timecnt; ++i) { 379 sp->ats[i] = detzcode(p); 380 p += 4; 381 } 382 for (i = 0; i < sp->timecnt; ++i) { 383 sp->types[i] = (unsigned char) *p++; 384 if (sp->types[i] >= sp->typecnt) 385 return -1; 386 } 387 for (i = 0; i < sp->typecnt; ++i) { 388 struct ttinfo * ttisp; 389 390 ttisp = &sp->ttis[i]; 391 ttisp->tt_gmtoff = detzcode(p); 392 p += 4; 393 ttisp->tt_isdst = (unsigned char) *p++; 394 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) 395 return -1; 396 ttisp->tt_abbrind = (unsigned char) *p++; 397 if (ttisp->tt_abbrind < 0 || 398 ttisp->tt_abbrind > sp->charcnt) 399 return -1; 400 } 401 for (i = 0; i < sp->charcnt; ++i) 402 sp->chars[i] = *p++; 403 sp->chars[i] = '\0'; /* ensure '\0' at end */ 404 for (i = 0; i < sp->leapcnt; ++i) { 405 struct lsinfo * lsisp; 406 407 lsisp = &sp->lsis[i]; 408 lsisp->ls_trans = detzcode(p); 409 p += 4; 410 lsisp->ls_corr = detzcode(p); 411 p += 4; 412 } 413 for (i = 0; i < sp->typecnt; ++i) { 414 struct ttinfo * ttisp; 415 416 ttisp = &sp->ttis[i]; 417 if (ttisstdcnt == 0) 418 ttisp->tt_ttisstd = FALSE; 419 else { 420 ttisp->tt_ttisstd = *p++; 421 if (ttisp->tt_ttisstd != TRUE && 422 ttisp->tt_ttisstd != FALSE) 423 return -1; 424 } 425 } 426 for (i = 0; i < sp->typecnt; ++i) { 427 struct ttinfo * ttisp; 428 429 ttisp = &sp->ttis[i]; 430 if (ttisgmtcnt == 0) 431 ttisp->tt_ttisgmt = FALSE; 432 else { 433 ttisp->tt_ttisgmt = *p++; 434 if (ttisp->tt_ttisgmt != TRUE && 435 ttisp->tt_ttisgmt != FALSE) 436 return -1; 437 } 438 } 439 } 440 return 0; 441} 442 443static const int mon_lengths[2][MONSPERYEAR] = { 444 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 445 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 446}; 447 448static const int year_lengths[2] = { 449 DAYSPERNYEAR, DAYSPERLYEAR 450}; 451 452/* 453** Given a pointer into a time zone string, scan until a character that is not 454** a valid character in a zone name is found. Return a pointer to that 455** character. 456*/ 457 458static const char * 459getzname(strp) 460const char * strp; 461{ 462 char c; 463 464 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && 465 c != '+') 466 ++strp; 467 return strp; 468} 469 470/* 471** Given a pointer into a time zone string, extract a number from that string. 472** Check that the number is within a specified range; if it is not, return 473** NULL. 474** Otherwise, return a pointer to the first character not part of the number. 475*/ 476 477static const char * 478getnum(strp, nump, min, max) 479const char * strp; 480int * const nump; 481const int min; 482const int max; 483{ 484 char c; 485 int num; 486 487 if (strp == NULL || !is_digit(c = *strp)) 488 return NULL; 489 num = 0; 490 do { 491 num = num * 10 + (c - '0'); 492 if (num > max) 493 return NULL; /* illegal value */ 494 c = *++strp; 495 } while (is_digit(c)); 496 if (num < min) 497 return NULL; /* illegal value */ 498 *nump = num; 499 return strp; 500} 501 502/* 503** Given a pointer into a time zone string, extract a number of seconds, 504** in hh[:mm[:ss]] form, from the string. 505** If any error occurs, return NULL. 506** Otherwise, return a pointer to the first character not part of the number 507** of seconds. 508*/ 509 510static const char * 511getsecs(strp, secsp) 512const char * strp; 513long * const secsp; 514{ 515 int num; 516 517 /* 518 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like 519 ** "M10.4.6/26", which does not conform to Posix, 520 ** but which specifies the equivalent of 521 ** ``02:00 on the first Sunday on or after 23 Oct''. 522 */ 523 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); 524 if (strp == NULL) 525 return NULL; 526 *secsp = num * (long) SECSPERHOUR; 527 if (*strp == ':') { 528 ++strp; 529 strp = getnum(strp, &num, 0, MINSPERHOUR - 1); 530 if (strp == NULL) 531 return NULL; 532 *secsp += num * SECSPERMIN; 533 if (*strp == ':') { 534 ++strp; 535 /* `SECSPERMIN' allows for leap seconds. */ 536 strp = getnum(strp, &num, 0, SECSPERMIN); 537 if (strp == NULL) 538 return NULL; 539 *secsp += num; 540 } 541 } 542 return strp; 543} 544 545/* 546** Given a pointer into a time zone string, extract an offset, in 547** [+-]hh[:mm[:ss]] form, from the string. 548** If any error occurs, return NULL. 549** Otherwise, return a pointer to the first character not part of the time. 550*/ 551 552static const char * 553getoffset(strp, offsetp) 554const char * strp; 555long * const offsetp; 556{ 557 int neg = 0; 558 559 if (*strp == '-') { 560 neg = 1; 561 ++strp; 562 } else if (*strp == '+') 563 ++strp; 564 strp = getsecs(strp, offsetp); 565 if (strp == NULL) 566 return NULL; /* illegal time */ 567 if (neg) 568 *offsetp = -*offsetp; 569 return strp; 570} 571 572/* 573** Given a pointer into a time zone string, extract a rule in the form 574** date[/time]. See POSIX section 8 for the format of "date" and "time". 575** If a valid rule is not found, return NULL. 576** Otherwise, return a pointer to the first character not part of the rule. 577*/ 578 579static const char * 580getrule(strp, rulep) 581const char * strp; 582struct rule * const rulep; 583{ 584 if (*strp == 'J') { 585 /* 586 ** Julian day. 587 */ 588 rulep->r_type = JULIAN_DAY; 589 ++strp; 590 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); 591 } else if (*strp == 'M') { 592 /* 593 ** Month, week, day. 594 */ 595 rulep->r_type = MONTH_NTH_DAY_OF_WEEK; 596 ++strp; 597 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); 598 if (strp == NULL) 599 return NULL; 600 if (*strp++ != '.') 601 return NULL; 602 strp = getnum(strp, &rulep->r_week, 1, 5); 603 if (strp == NULL) 604 return NULL; 605 if (*strp++ != '.') 606 return NULL; 607 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); 608 } else if (is_digit(*strp)) { 609 /* 610 ** Day of year. 611 */ 612 rulep->r_type = DAY_OF_YEAR; 613 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); 614 } else return NULL; /* invalid format */ 615 if (strp == NULL) 616 return NULL; 617 if (*strp == '/') { 618 /* 619 ** Time specified. 620 */ 621 ++strp; 622 strp = getsecs(strp, &rulep->r_time); 623 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ 624 return strp; 625} 626 627/* 628** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the 629** year, a rule, and the offset from UTC at the time that rule takes effect, 630** calculate the Epoch-relative time that rule takes effect. 631*/ 632 633static time_t 634transtime(janfirst, year, rulep, offset) 635const time_t janfirst; 636const int year; 637const struct rule * const rulep; 638const long offset; 639{ 640 int leapyear; 641 time_t value; 642 int i; 643 int d, m1, yy0, yy1, yy2, dow; 644 645 INITIALIZE(value); 646 leapyear = isleap(year); 647 switch (rulep->r_type) { 648 649 case JULIAN_DAY: 650 /* 651 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap 652 ** years. 653 ** In non-leap years, or if the day number is 59 or less, just 654 ** add SECSPERDAY times the day number-1 to the time of 655 ** January 1, midnight, to get the day. 656 */ 657 value = janfirst + (rulep->r_day - 1) * SECSPERDAY; 658 if (leapyear && rulep->r_day >= 60) 659 value += SECSPERDAY; 660 break; 661 662 case DAY_OF_YEAR: 663 /* 664 ** n - day of year. 665 ** Just add SECSPERDAY times the day number to the time of 666 ** January 1, midnight, to get the day. 667 */ 668 value = janfirst + rulep->r_day * SECSPERDAY; 669 break; 670 671 case MONTH_NTH_DAY_OF_WEEK: 672 /* 673 ** Mm.n.d - nth "dth day" of month m. 674 */ 675 value = janfirst; 676 for (i = 0; i < rulep->r_mon - 1; ++i) 677 value += mon_lengths[leapyear][i] * SECSPERDAY; 678 679 /* 680 ** Use Zeller's Congruence to get day-of-week of first day of 681 ** month. 682 */ 683 m1 = (rulep->r_mon + 9) % 12 + 1; 684 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; 685 yy1 = yy0 / 100; 686 yy2 = yy0 % 100; 687 dow = ((26 * m1 - 2) / 10 + 688 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; 689 if (dow < 0) 690 dow += DAYSPERWEEK; 691 692 /* 693 ** "dow" is the day-of-week of the first day of the month. Get 694 ** the day-of-month (zero-origin) of the first "dow" day of the 695 ** month. 696 */ 697 d = rulep->r_day - dow; 698 if (d < 0) 699 d += DAYSPERWEEK; 700 for (i = 1; i < rulep->r_week; ++i) { 701 if (d + DAYSPERWEEK >= 702 mon_lengths[leapyear][rulep->r_mon - 1]) 703 break; 704 d += DAYSPERWEEK; 705 } 706 707 /* 708 ** "d" is the day-of-month (zero-origin) of the day we want. 709 */ 710 value += d * SECSPERDAY; 711 break; 712 } 713 714 /* 715 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in 716 ** question. To get the Epoch-relative time of the specified local 717 ** time on that day, add the transition time and the current offset 718 ** from UTC. 719 */ 720 return value + rulep->r_time + offset; 721} 722 723/* 724** Given a POSIX section 8-style TZ string, fill in the rule tables as 725** appropriate. 726*/ 727 728static int 729tzparse(name, sp, lastditch) 730const char * name; 731struct state * const sp; 732const int lastditch; 733{ 734 const char * stdname; 735 const char * dstname; 736 size_t stdlen; 737 size_t dstlen; 738 long stdoffset; 739 long dstoffset; 740 time_t * atp; 741 unsigned char * typep; 742 char * cp; 743 int load_result; 744 745 INITIALIZE(dstname); 746 stdname = name; 747 if (lastditch) { 748 stdlen = strlen(name); /* length of standard zone name */ 749 name += stdlen; 750 if (stdlen >= sizeof sp->chars) 751 stdlen = (sizeof sp->chars) - 1; 752 stdoffset = 0; 753 } else { 754 name = getzname(name); 755 stdlen = name - stdname; 756 if (stdlen < 3) 757 return -1; 758 if (*name == '\0') 759 return -1; /* was "stdoffset = 0;" */ 760 else { 761 name = getoffset(name, &stdoffset); 762 if (name == NULL) 763 return -1; 764 } 765 } 766 load_result = tzload(TZDEFRULES, sp); 767 if (load_result != 0) 768 sp->leapcnt = 0; /* so, we're off a little */ 769 if (*name != '\0') { 770 dstname = name; 771 name = getzname(name); 772 dstlen = name - dstname; /* length of DST zone name */ 773 if (dstlen < 3) 774 return -1; 775 if (*name != '\0' && *name != ',' && *name != ';') { 776 name = getoffset(name, &dstoffset); 777 if (name == NULL) 778 return -1; 779 } else dstoffset = stdoffset - SECSPERHOUR; 780 if (*name == '\0' && load_result != 0) 781 name = TZDEFRULESTRING; 782 if (*name == ',' || *name == ';') { 783 struct rule start; 784 struct rule end; 785 int year; 786 time_t janfirst; 787 time_t starttime; 788 time_t endtime; 789 790 ++name; 791 if ((name = getrule(name, &start)) == NULL) 792 return -1; 793 if (*name++ != ',') 794 return -1; 795 if ((name = getrule(name, &end)) == NULL) 796 return -1; 797 if (*name != '\0') 798 return -1; 799 sp->typecnt = 2; /* standard time and DST */ 800 /* 801 ** Two transitions per year, from EPOCH_YEAR to 2037. 802 */ 803 sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1); 804 if (sp->timecnt > TZ_MAX_TIMES) 805 return -1; 806 sp->ttis[0].tt_gmtoff = -dstoffset; 807 sp->ttis[0].tt_isdst = 1; 808 sp->ttis[0].tt_abbrind = stdlen + 1; 809 sp->ttis[1].tt_gmtoff = -stdoffset; 810 sp->ttis[1].tt_isdst = 0; 811 sp->ttis[1].tt_abbrind = 0; 812 atp = sp->ats; 813 typep = sp->types; 814 janfirst = 0; 815 for (year = EPOCH_YEAR; year <= 2037; ++year) { 816 starttime = transtime(janfirst, year, &start, 817 stdoffset); 818 endtime = transtime(janfirst, year, &end, 819 dstoffset); 820 if (starttime > endtime) { 821 *atp++ = endtime; 822 *typep++ = 1; /* DST ends */ 823 *atp++ = starttime; 824 *typep++ = 0; /* DST begins */ 825 } else { 826 *atp++ = starttime; 827 *typep++ = 0; /* DST begins */ 828 *atp++ = endtime; 829 *typep++ = 1; /* DST ends */ 830 } 831 janfirst += year_lengths[isleap(year)] * 832 SECSPERDAY; 833 } 834 } else { 835 long theirstdoffset; 836 long theirdstoffset; 837 long theiroffset; 838 int isdst; 839 int i; 840 int j; 841 842 if (*name != '\0') 843 return -1; 844 /* 845 ** Initial values of theirstdoffset and theirdstoffset. 846 */ 847 theirstdoffset = 0; 848 for (i = 0; i < sp->timecnt; ++i) { 849 j = sp->types[i]; 850 if (!sp->ttis[j].tt_isdst) { 851 theirstdoffset = 852 -sp->ttis[j].tt_gmtoff; 853 break; 854 } 855 } 856 theirdstoffset = 0; 857 for (i = 0; i < sp->timecnt; ++i) { 858 j = sp->types[i]; 859 if (sp->ttis[j].tt_isdst) { 860 theirdstoffset = 861 -sp->ttis[j].tt_gmtoff; 862 break; 863 } 864 } 865 /* 866 ** Initially we're assumed to be in standard time. 867 */ 868 isdst = FALSE; 869 theiroffset = theirstdoffset; 870 /* 871 ** Now juggle transition times and types 872 ** tracking offsets as you do. 873 */ 874 for (i = 0; i < sp->timecnt; ++i) { 875 j = sp->types[i]; 876 sp->types[i] = sp->ttis[j].tt_isdst; 877 if (sp->ttis[j].tt_ttisgmt) { 878 /* No adjustment to transition time */ 879 } else { 880 /* 881 ** If summer time is in effect, and the 882 ** transition time was not specified as 883 ** standard time, add the summer time 884 ** offset to the transition time; 885 ** otherwise, add the standard time 886 ** offset to the transition time. 887 */ 888 /* 889 ** Transitions from DST to DDST 890 ** will effectively disappear since 891 ** POSIX provides for only one DST 892 ** offset. 893 */ 894 if (isdst && !sp->ttis[j].tt_ttisstd) { 895 sp->ats[i] += dstoffset - 896 theirdstoffset; 897 } else { 898 sp->ats[i] += stdoffset - 899 theirstdoffset; 900 } 901 } 902 theiroffset = -sp->ttis[j].tt_gmtoff; 903 if (sp->ttis[j].tt_isdst) 904 theirdstoffset = theiroffset; 905 else theirstdoffset = theiroffset; 906 } 907 /* 908 ** Finally, fill in ttis. 909 ** ttisstd and ttisgmt need not be handled. 910 */ 911 sp->ttis[0].tt_gmtoff = -stdoffset; 912 sp->ttis[0].tt_isdst = FALSE; 913 sp->ttis[0].tt_abbrind = 0; 914 sp->ttis[1].tt_gmtoff = -dstoffset; 915 sp->ttis[1].tt_isdst = TRUE; 916 sp->ttis[1].tt_abbrind = stdlen + 1; 917 sp->typecnt = 2; 918 } 919 } else { 920 dstlen = 0; 921 sp->typecnt = 1; /* only standard time */ 922 sp->timecnt = 0; 923 sp->ttis[0].tt_gmtoff = -stdoffset; 924 sp->ttis[0].tt_isdst = 0; 925 sp->ttis[0].tt_abbrind = 0; 926 } 927 sp->charcnt = stdlen + 1; 928 if (dstlen != 0) 929 sp->charcnt += dstlen + 1; 930 if ((size_t) sp->charcnt > sizeof sp->chars) 931 return -1; 932 cp = sp->chars; 933 (void) strncpy(cp, stdname, stdlen); 934 cp += stdlen; 935 *cp++ = '\0'; 936 if (dstlen != 0) { 937 (void) strncpy(cp, dstname, dstlen); 938 *(cp + dstlen) = '\0'; 939 } 940 return 0; 941} 942 943static void 944gmtload(sp) 945struct state * const sp; 946{ 947 if (tzload(gmt, sp) != 0) 948 (void) tzparse(gmt, sp, TRUE); 949} 950 951static void 952tzsetwall_basic(void) 953{ 954 if (lcl_is_set < 0) 955 return; 956 lcl_is_set = -1; 957 958#ifdef ALL_STATE 959 if (lclptr == NULL) { 960 lclptr = (struct state *) malloc(sizeof *lclptr); 961 if (lclptr == NULL) { 962 settzname(); /* all we can do */ 963 return; 964 } 965 } 966#endif /* defined ALL_STATE */ 967 if (tzload((char *) NULL, lclptr) != 0) 968 gmtload(lclptr); 969 settzname(); 970} 971 972void 973tzsetwall(void) 974{ 975 _MUTEX_LOCK(&lcl_mutex); 976 tzsetwall_basic(); 977 _MUTEX_UNLOCK(&lcl_mutex); 978} 979 980static void 981tzset_basic(void) 982{ 983 const char * name; 984 985 name = getenv("TZ"); 986 if (name == NULL) { 987 tzsetwall_basic(); 988 return; 989 } 990 991 if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) 992 return; 993 lcl_is_set = strlen(name) < sizeof lcl_TZname; 994 if (lcl_is_set) 995 (void) strcpy(lcl_TZname, name); 996 997#ifdef ALL_STATE 998 if (lclptr == NULL) { 999 lclptr = (struct state *) malloc(sizeof *lclptr); 1000 if (lclptr == NULL) { 1001 settzname(); /* all we can do */ 1002 return; 1003 } 1004 } 1005#endif /* defined ALL_STATE */ 1006 if (*name == '\0') { 1007 /* 1008 ** User wants it fast rather than right. 1009 */ 1010 lclptr->leapcnt = 0; /* so, we're off a little */ 1011 lclptr->timecnt = 0; 1012 lclptr->typecnt = 0; 1013 lclptr->ttis[0].tt_isdst = 0; 1014 lclptr->ttis[0].tt_gmtoff = 0; 1015 lclptr->ttis[0].tt_abbrind = 0; 1016 (void) strcpy(lclptr->chars, gmt); 1017 } else if (tzload(name, lclptr) != 0) 1018 if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0) 1019 (void) gmtload(lclptr); 1020 settzname(); 1021} 1022 1023void 1024tzset(void) 1025{ 1026 _MUTEX_LOCK(&lcl_mutex); 1027 tzset_basic(); 1028 _MUTEX_UNLOCK(&lcl_mutex); 1029} 1030 1031/* 1032** The easy way to behave "as if no library function calls" localtime 1033** is to not call it--so we drop its guts into "localsub", which can be 1034** freely called. (And no, the PANS doesn't require the above behavior-- 1035** but it *is* desirable.) 1036** 1037** The unused offset argument is for the benefit of mktime variants. 1038*/ 1039 1040/*ARGSUSED*/ 1041static void 1042localsub(timep, offset, tmp) 1043const time_t * const timep; 1044const long offset; 1045struct tm * const tmp; 1046{ 1047 struct state * sp; 1048 const struct ttinfo * ttisp; 1049 int i; 1050 const time_t t = *timep; 1051 1052 sp = lclptr; 1053#ifdef ALL_STATE 1054 if (sp == NULL) { 1055 gmtsub(timep, offset, tmp); 1056 return; 1057 } 1058#endif /* defined ALL_STATE */ 1059 if (sp->timecnt == 0 || t < sp->ats[0]) { 1060 i = 0; 1061 while (sp->ttis[i].tt_isdst) 1062 if (++i >= sp->typecnt) { 1063 i = 0; 1064 break; 1065 } 1066 } else { 1067 for (i = 1; i < sp->timecnt; ++i) 1068 if (t < sp->ats[i]) 1069 break; 1070 i = sp->types[i - 1]; 1071 } 1072 ttisp = &sp->ttis[i]; 1073 /* 1074 ** To get (wrong) behavior that's compatible with System V Release 2.0 1075 ** you'd replace the statement below with 1076 ** t += ttisp->tt_gmtoff; 1077 ** timesub(&t, 0L, sp, tmp); 1078 */ 1079 timesub(&t, ttisp->tt_gmtoff, sp, tmp); 1080 tmp->tm_isdst = ttisp->tt_isdst; 1081 tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind]; 1082#ifdef TM_ZONE 1083 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; 1084#endif /* defined TM_ZONE */ 1085} 1086 1087struct tm * 1088localtime(timep) 1089const time_t * const timep; 1090{ 1091 static pthread_mutex_t localtime_mutex = PTHREAD_MUTEX_INITIALIZER; 1092 static pthread_key_t localtime_key = -1; 1093 struct tm *p_tm; 1094 1095 if (__isthreaded != 0) { 1096 if (localtime_key < 0) { 1097 _pthread_mutex_lock(&localtime_mutex); 1098 if (localtime_key < 0) { 1099 if (_pthread_key_create(&localtime_key, free) < 0) { 1100 _pthread_mutex_unlock(&localtime_mutex); 1101 return(NULL); 1102 } 1103 } 1104 _pthread_mutex_unlock(&localtime_mutex); 1105 } 1106 p_tm = _pthread_getspecific(localtime_key); 1107 if (p_tm == NULL) { 1108 if ((p_tm = (struct tm *)malloc(sizeof(struct tm))) 1109 == NULL) 1110 return(NULL); 1111 _pthread_setspecific(localtime_key, p_tm); 1112 } 1113 _pthread_mutex_lock(&lcl_mutex); 1114 tzset_basic(); 1115 localsub(timep, 0L, p_tm); 1116 _pthread_mutex_unlock(&lcl_mutex); 1117 return(p_tm); 1118 } else { 1119 tzset_basic(); 1120 localsub(timep, 0L, &tm); 1121 return(&tm); 1122 } 1123} 1124 1125/* 1126** Re-entrant version of localtime. 1127*/ 1128 1129struct tm * 1130localtime_r(timep, tm) 1131const time_t * const timep; 1132struct tm * tm; 1133{ 1134 _MUTEX_LOCK(&lcl_mutex); 1135 tzset_basic(); 1136 localsub(timep, 0L, tm); 1137 _MUTEX_UNLOCK(&lcl_mutex); 1138 return tm; 1139} 1140 1141/* 1142** gmtsub is to gmtime as localsub is to localtime. 1143*/ 1144 1145static void 1146gmtsub(timep, offset, tmp) 1147const time_t * const timep; 1148const long offset; 1149struct tm * const tmp; 1150{ 1151 if (!gmt_is_set) { 1152 _MUTEX_LOCK(&gmt_mutex); 1153 if (!gmt_is_set) { 1154#ifdef ALL_STATE 1155 gmtptr = (struct state *) malloc(sizeof *gmtptr); 1156 if (gmtptr != NULL) 1157#endif /* defined ALL_STATE */ 1158 gmtload(gmtptr); 1159 gmt_is_set = TRUE; 1160 } 1161 _MUTEX_UNLOCK(&gmt_mutex); 1162 } 1163 timesub(timep, offset, gmtptr, tmp); 1164#ifdef TM_ZONE 1165 /* 1166 ** Could get fancy here and deliver something such as 1167 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, 1168 ** but this is no time for a treasure hunt. 1169 */ 1170 if (offset != 0) 1171 tmp->TM_ZONE = wildabbr; 1172 else { 1173#ifdef ALL_STATE 1174 if (gmtptr == NULL) 1175 tmp->TM_ZONE = gmt; 1176 else tmp->TM_ZONE = gmtptr->chars; 1177#endif /* defined ALL_STATE */ 1178#ifndef ALL_STATE 1179 tmp->TM_ZONE = gmtptr->chars; 1180#endif /* State Farm */ 1181 } 1182#endif /* defined TM_ZONE */ 1183} 1184 1185struct tm * 1186gmtime(timep) 1187const time_t * const timep; 1188{ 1189 static pthread_mutex_t gmtime_mutex = PTHREAD_MUTEX_INITIALIZER; 1190 static pthread_key_t gmtime_key = -1; 1191 struct tm *p_tm; 1192 1193 if (__isthreaded != 0) { 1194 if (gmtime_key < 0) { 1195 _pthread_mutex_lock(&gmtime_mutex); 1196 if (gmtime_key < 0) { 1197 if (_pthread_key_create(&gmtime_key, free) < 0) { 1198 _pthread_mutex_unlock(&gmtime_mutex); 1199 return(NULL); 1200 } 1201 } 1202 _pthread_mutex_unlock(&gmtime_mutex); 1203 } 1204 /* 1205 * Changed to follow POSIX.1 threads standard, which 1206 * is what BSD currently has. 1207 */ 1208 if ((p_tm = _pthread_getspecific(gmtime_key)) == NULL) { 1209 if ((p_tm = (struct tm *)malloc(sizeof(struct tm))) 1210 == NULL) { 1211 return(NULL); 1212 } 1213 _pthread_setspecific(gmtime_key, p_tm); 1214 } 1215 gmtsub(timep, 0L, p_tm); 1216 return(p_tm); 1217 } 1218 else { 1219 gmtsub(timep, 0L, &tm); 1220 return(&tm); 1221 } 1222} 1223 1224/* 1225* Re-entrant version of gmtime. 1226*/ 1227 1228struct tm * 1229gmtime_r(timep, tm) 1230const time_t * const timep; 1231struct tm * tm; 1232{ 1233 gmtsub(timep, 0L, tm); 1234 return tm; 1235} 1236 1237#ifdef STD_INSPIRED 1238 1239struct tm * 1240offtime(timep, offset) 1241const time_t * const timep; 1242const long offset; 1243{ 1244 gmtsub(timep, offset, &tm); 1245 return &tm; 1246} 1247 1248#endif /* defined STD_INSPIRED */ 1249 1250static void 1251timesub(timep, offset, sp, tmp) 1252const time_t * const timep; 1253const long offset; 1254const struct state * const sp; 1255struct tm * const tmp; 1256{ 1257 const struct lsinfo * lp; 1258 long days; 1259 long rem; 1260 long y; 1261 int yleap; 1262 const int * ip; 1263 long corr; 1264 int hit; 1265 int i; 1266 1267 corr = 0; 1268 hit = 0; 1269#ifdef ALL_STATE 1270 i = (sp == NULL) ? 0 : sp->leapcnt; 1271#endif /* defined ALL_STATE */ 1272#ifndef ALL_STATE 1273 i = sp->leapcnt; 1274#endif /* State Farm */ 1275 while (--i >= 0) { 1276 lp = &sp->lsis[i]; 1277 if (*timep >= lp->ls_trans) { 1278 if (*timep == lp->ls_trans) { 1279 hit = ((i == 0 && lp->ls_corr > 0) || 1280 lp->ls_corr > sp->lsis[i - 1].ls_corr); 1281 if (hit) 1282 while (i > 0 && 1283 sp->lsis[i].ls_trans == 1284 sp->lsis[i - 1].ls_trans + 1 && 1285 sp->lsis[i].ls_corr == 1286 sp->lsis[i - 1].ls_corr + 1) { 1287 ++hit; 1288 --i; 1289 } 1290 } 1291 corr = lp->ls_corr; 1292 break; 1293 } 1294 } 1295 days = *timep / SECSPERDAY; 1296 rem = *timep % SECSPERDAY; 1297#ifdef mc68k 1298 if (*timep == 0x80000000) { 1299 /* 1300 ** A 3B1 muffs the division on the most negative number. 1301 */ 1302 days = -24855; 1303 rem = -11648; 1304 } 1305#endif /* defined mc68k */ 1306 rem += (offset - corr); 1307 while (rem < 0) { 1308 rem += SECSPERDAY; 1309 --days; 1310 } 1311 while (rem >= SECSPERDAY) { 1312 rem -= SECSPERDAY; 1313 ++days; 1314 } 1315 tmp->tm_hour = (int) (rem / SECSPERHOUR); 1316 rem = rem % SECSPERHOUR; 1317 tmp->tm_min = (int) (rem / SECSPERMIN); 1318 /* 1319 ** A positive leap second requires a special 1320 ** representation. This uses "... ??:59:60" et seq. 1321 */ 1322 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; 1323 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); 1324 if (tmp->tm_wday < 0) 1325 tmp->tm_wday += DAYSPERWEEK; 1326 y = EPOCH_YEAR; 1327#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) 1328 while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) { 1329 long newy; 1330 1331 newy = y + days / DAYSPERNYEAR; 1332 if (days < 0) 1333 --newy; 1334 days -= (newy - y) * DAYSPERNYEAR + 1335 LEAPS_THRU_END_OF(newy - 1) - 1336 LEAPS_THRU_END_OF(y - 1); 1337 y = newy; 1338 } 1339 tmp->tm_year = y - TM_YEAR_BASE; 1340 tmp->tm_yday = (int) days; 1341 ip = mon_lengths[yleap]; 1342 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) 1343 days = days - (long) ip[tmp->tm_mon]; 1344 tmp->tm_mday = (int) (days + 1); 1345 tmp->tm_isdst = 0; 1346#ifdef TM_GMTOFF 1347 tmp->TM_GMTOFF = offset; 1348#endif /* defined TM_GMTOFF */ 1349} 1350 1351char * 1352ctime(timep) 1353const time_t * const timep; 1354{ 1355/* 1356** Section 4.12.3.2 of X3.159-1989 requires that 1357** The ctime function converts the calendar time pointed to by timer 1358** to local time in the form of a string. It is equivalent to 1359** asctime(localtime(timer)) 1360*/ 1361 return asctime(localtime(timep)); 1362} 1363 1364char * 1365ctime_r(timep, buf) 1366const time_t * const timep; 1367char * buf; 1368{ 1369 struct tm tm; 1370 1371 return asctime_r(localtime_r(timep, &tm), buf); 1372} 1373 1374/* 1375** Adapted from code provided by Robert Elz, who writes: 1376** The "best" way to do mktime I think is based on an idea of Bob 1377** Kridle's (so its said...) from a long time ago. 1378** [kridle@xinet.com as of 1996-01-16.] 1379** It does a binary search of the time_t space. Since time_t's are 1380** just 32 bits, its a max of 32 iterations (even at 64 bits it 1381** would still be very reasonable). 1382*/ 1383 1384#ifndef WRONG 1385#define WRONG (-1) 1386#endif /* !defined WRONG */ 1387 1388/* 1389** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com). 1390*/ 1391 1392static int 1393increment_overflow(number, delta) 1394int * number; 1395int delta; 1396{ 1397 int number0; 1398 1399 number0 = *number; 1400 *number += delta; 1401 return (*number < number0) != (delta < 0); 1402} 1403 1404static int 1405normalize_overflow(tensptr, unitsptr, base) 1406int * const tensptr; 1407int * const unitsptr; 1408const int base; 1409{ 1410 int tensdelta; 1411 1412 tensdelta = (*unitsptr >= 0) ? 1413 (*unitsptr / base) : 1414 (-1 - (-1 - *unitsptr) / base); 1415 *unitsptr -= tensdelta * base; 1416 return increment_overflow(tensptr, tensdelta); 1417} 1418 1419static int 1420tmcomp(atmp, btmp) 1421const struct tm * const atmp; 1422const struct tm * const btmp; 1423{ 1424 int result; 1425 1426 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && 1427 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && 1428 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && 1429 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && 1430 (result = (atmp->tm_min - btmp->tm_min)) == 0) 1431 result = atmp->tm_sec - btmp->tm_sec; 1432 return result; 1433} 1434 1435static time_t 1436time2sub(tmp, funcp, offset, okayp, do_norm_secs) 1437struct tm * const tmp; 1438void (* const funcp)(const time_t*, long, struct tm*); 1439const long offset; 1440int * const okayp; 1441const int do_norm_secs; 1442{ 1443 const struct state * sp; 1444 int dir; 1445 int bits; 1446 int i, j ; 1447 int saved_seconds; 1448 time_t newt; 1449 time_t t; 1450 struct tm yourtm, mytm; 1451 1452 *okayp = FALSE; 1453 yourtm = *tmp; 1454 if (do_norm_secs) { 1455 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, 1456 SECSPERMIN)) 1457 return WRONG; 1458 } 1459 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) 1460 return WRONG; 1461 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) 1462 return WRONG; 1463 if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR)) 1464 return WRONG; 1465 /* 1466 ** Turn yourtm.tm_year into an actual year number for now. 1467 ** It is converted back to an offset from TM_YEAR_BASE later. 1468 */ 1469 if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE)) 1470 return WRONG; 1471 while (yourtm.tm_mday <= 0) { 1472 if (increment_overflow(&yourtm.tm_year, -1)) 1473 return WRONG; 1474 i = yourtm.tm_year + (1 < yourtm.tm_mon); 1475 yourtm.tm_mday += year_lengths[isleap(i)]; 1476 } 1477 while (yourtm.tm_mday > DAYSPERLYEAR) { 1478 i = yourtm.tm_year + (1 < yourtm.tm_mon); 1479 yourtm.tm_mday -= year_lengths[isleap(i)]; 1480 if (increment_overflow(&yourtm.tm_year, 1)) 1481 return WRONG; 1482 } 1483 for ( ; ; ) { 1484 i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon]; 1485 if (yourtm.tm_mday <= i) 1486 break; 1487 yourtm.tm_mday -= i; 1488 if (++yourtm.tm_mon >= MONSPERYEAR) { 1489 yourtm.tm_mon = 0; 1490 if (increment_overflow(&yourtm.tm_year, 1)) 1491 return WRONG; 1492 } 1493 } 1494 if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE)) 1495 return WRONG; 1496 /* Don't go below 1900 for POLA */ 1497 if (yourtm.tm_year < 0) 1498 return WRONG; 1499 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) 1500 saved_seconds = 0; 1501 else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) { 1502 /* 1503 ** We can't set tm_sec to 0, because that might push the 1504 ** time below the minimum representable time. 1505 ** Set tm_sec to 59 instead. 1506 ** This assumes that the minimum representable time is 1507 ** not in the same minute that a leap second was deleted from, 1508 ** which is a safer assumption than using 58 would be. 1509 */ 1510 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) 1511 return WRONG; 1512 saved_seconds = yourtm.tm_sec; 1513 yourtm.tm_sec = SECSPERMIN - 1; 1514 } else { 1515 saved_seconds = yourtm.tm_sec; 1516 yourtm.tm_sec = 0; 1517 } 1518 /* 1519 ** Divide the search space in half 1520 ** (this works whether time_t is signed or unsigned). 1521 */ 1522 bits = TYPE_BIT(time_t) - 1; 1523 /* 1524 ** If we have more than this, we will overflow tm_year for tmcomp(). 1525 ** We should really return an error if we cannot represent it. 1526 */ 1527 if (bits > 48) 1528 bits = 48; 1529 /* 1530 ** If time_t is signed, then 0 is just above the median, 1531 ** assuming two's complement arithmetic. 1532 ** If time_t is unsigned, then (1 << bits) is just above the median. 1533 */ 1534 t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits); 1535 for ( ; ; ) { 1536 (*funcp)(&t, offset, &mytm); 1537 dir = tmcomp(&mytm, &yourtm); 1538 if (dir != 0) { 1539 if (bits-- < 0) 1540 return WRONG; 1541 if (bits < 0) 1542 --t; /* may be needed if new t is minimal */ 1543 else if (dir > 0) 1544 t -= ((time_t) 1) << bits; 1545 else t += ((time_t) 1) << bits; 1546 continue; 1547 } 1548 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) 1549 break; 1550 /* 1551 ** Right time, wrong type. 1552 ** Hunt for right time, right type. 1553 ** It's okay to guess wrong since the guess 1554 ** gets checked. 1555 */ 1556 sp = (funcp == localsub) ? lclptr : gmtptr; 1557#ifdef ALL_STATE 1558 if (sp == NULL) 1559 return WRONG; 1560#endif /* defined ALL_STATE */ 1561 for (i = sp->typecnt - 1; i >= 0; --i) { 1562 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) 1563 continue; 1564 for (j = sp->typecnt - 1; j >= 0; --j) { 1565 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) 1566 continue; 1567 newt = t + sp->ttis[j].tt_gmtoff - 1568 sp->ttis[i].tt_gmtoff; 1569 (*funcp)(&newt, offset, &mytm); 1570 if (tmcomp(&mytm, &yourtm) != 0) 1571 continue; 1572 if (mytm.tm_isdst != yourtm.tm_isdst) 1573 continue; 1574 /* 1575 ** We have a match. 1576 */ 1577 t = newt; 1578 goto label; 1579 } 1580 } 1581 return WRONG; 1582 } 1583label: 1584 newt = t + saved_seconds; 1585 if ((newt < t) != (saved_seconds < 0)) 1586 return WRONG; 1587 t = newt; 1588 (*funcp)(&t, offset, tmp); 1589 *okayp = TRUE; 1590 return t; 1591} 1592 1593static time_t 1594time2(tmp, funcp, offset, okayp) 1595struct tm * const tmp; 1596void (* const funcp)(const time_t*, long, struct tm*); 1597const long offset; 1598int * const okayp; 1599{ 1600 time_t t; 1601 1602 /* 1603 ** First try without normalization of seconds 1604 ** (in case tm_sec contains a value associated with a leap second). 1605 ** If that fails, try with normalization of seconds. 1606 */ 1607 t = time2sub(tmp, funcp, offset, okayp, FALSE); 1608 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE); 1609} 1610 1611static time_t 1612time1(tmp, funcp, offset) 1613struct tm * const tmp; 1614void (* const funcp)(const time_t *, long, struct tm *); 1615const long offset; 1616{ 1617 time_t t; 1618 const struct state * sp; 1619 int samei, otheri; 1620 int sameind, otherind; 1621 int i; 1622 int nseen; 1623 int seen[TZ_MAX_TYPES]; 1624 int types[TZ_MAX_TYPES]; 1625 int okay; 1626 1627 if (tmp->tm_isdst > 1) 1628 tmp->tm_isdst = 1; 1629 t = time2(tmp, funcp, offset, &okay); 1630#ifdef PCTS 1631 /* 1632 ** PCTS code courtesy Grant Sullivan (grant@osf.org). 1633 */ 1634 if (okay) 1635 return t; 1636 if (tmp->tm_isdst < 0) 1637 tmp->tm_isdst = 0; /* reset to std and try again */ 1638#endif /* defined PCTS */ 1639#ifndef PCTS 1640 if (okay || tmp->tm_isdst < 0) 1641 return t; 1642#endif /* !defined PCTS */ 1643 /* 1644 ** We're supposed to assume that somebody took a time of one type 1645 ** and did some math on it that yielded a "struct tm" that's bad. 1646 ** We try to divine the type they started from and adjust to the 1647 ** type they need. 1648 */ 1649 sp = (funcp == localsub) ? lclptr : gmtptr; 1650#ifdef ALL_STATE 1651 if (sp == NULL) 1652 return WRONG; 1653#endif /* defined ALL_STATE */ 1654 for (i = 0; i < sp->typecnt; ++i) 1655 seen[i] = FALSE; 1656 nseen = 0; 1657 for (i = sp->timecnt - 1; i >= 0; --i) 1658 if (!seen[sp->types[i]]) { 1659 seen[sp->types[i]] = TRUE; 1660 types[nseen++] = sp->types[i]; 1661 } 1662 for (sameind = 0; sameind < nseen; ++sameind) { 1663 samei = types[sameind]; 1664 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) 1665 continue; 1666 for (otherind = 0; otherind < nseen; ++otherind) { 1667 otheri = types[otherind]; 1668 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) 1669 continue; 1670 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - 1671 sp->ttis[samei].tt_gmtoff; 1672 tmp->tm_isdst = !tmp->tm_isdst; 1673 t = time2(tmp, funcp, offset, &okay); 1674 if (okay) 1675 return t; 1676 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - 1677 sp->ttis[samei].tt_gmtoff; 1678 tmp->tm_isdst = !tmp->tm_isdst; 1679 } 1680 } 1681 return WRONG; 1682} 1683 1684time_t 1685mktime(tmp) 1686struct tm * const tmp; 1687{ 1688 time_t mktime_return_value; 1689 _MUTEX_LOCK(&lcl_mutex); 1690 tzset_basic(); 1691 mktime_return_value = time1(tmp, localsub, 0L); 1692 _MUTEX_UNLOCK(&lcl_mutex); 1693 return(mktime_return_value); 1694} 1695 1696#ifdef STD_INSPIRED 1697 1698time_t 1699timelocal(tmp) 1700struct tm * const tmp; 1701{ 1702 tmp->tm_isdst = -1; /* in case it wasn't initialized */ 1703 return mktime(tmp); 1704} 1705 1706time_t 1707timegm(tmp) 1708struct tm * const tmp; 1709{ 1710 tmp->tm_isdst = 0; 1711 return time1(tmp, gmtsub, 0L); 1712} 1713 1714time_t 1715timeoff(tmp, offset) 1716struct tm * const tmp; 1717const long offset; 1718{ 1719 tmp->tm_isdst = 0; 1720 return time1(tmp, gmtsub, offset); 1721} 1722 1723#endif /* defined STD_INSPIRED */ 1724 1725#ifdef CMUCS 1726 1727/* 1728** The following is supplied for compatibility with 1729** previous versions of the CMUCS runtime library. 1730*/ 1731 1732long 1733gtime(tmp) 1734struct tm * const tmp; 1735{ 1736 const time_t t = mktime(tmp); 1737 1738 if (t == WRONG) 1739 return -1; 1740 return t; 1741} 1742 1743#endif /* defined CMUCS */ 1744 1745/* 1746** XXX--is the below the right way to conditionalize?? 1747*/ 1748 1749#ifdef STD_INSPIRED 1750 1751/* 1752** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599 1753** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which 1754** is not the case if we are accounting for leap seconds. 1755** So, we provide the following conversion routines for use 1756** when exchanging timestamps with POSIX conforming systems. 1757*/ 1758 1759static long 1760leapcorr(timep) 1761time_t * timep; 1762{ 1763 struct state * sp; 1764 struct lsinfo * lp; 1765 int i; 1766 1767 sp = lclptr; 1768 i = sp->leapcnt; 1769 while (--i >= 0) { 1770 lp = &sp->lsis[i]; 1771 if (*timep >= lp->ls_trans) 1772 return lp->ls_corr; 1773 } 1774 return 0; 1775} 1776 1777time_t 1778time2posix(t) 1779time_t t; 1780{ 1781 tzset(); 1782 return t - leapcorr(&t); 1783} 1784 1785time_t 1786posix2time(t) 1787time_t t; 1788{ 1789 time_t x; 1790 time_t y; 1791 1792 tzset(); 1793 /* 1794 ** For a positive leap second hit, the result 1795 ** is not unique. For a negative leap second 1796 ** hit, the corresponding time doesn't exist, 1797 ** so we return an adjacent second. 1798 */ 1799 x = t + leapcorr(&t); 1800 y = x - leapcorr(&x); 1801 if (y < t) { 1802 do { 1803 x++; 1804 y = x - leapcorr(&x); 1805 } while (y < t); 1806 if (t != y) 1807 return x - 1; 1808 } else if (y > t) { 1809 do { 1810 --x; 1811 y = x - leapcorr(&x); 1812 } while (y > t); 1813 if (t != y) 1814 return x + 1; 1815 } 1816 return x; 1817} 1818 1819#endif /* defined STD_INSPIRED */ 1820