localtime.c revision 134231
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 134231 2004-08-24 00:15:37Z peter $"); 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 _pthread_mutex_lock(&localtime_mutex); 1097 if (localtime_key < 0) { 1098 if (_pthread_key_create(&localtime_key, free) < 0) { 1099 _pthread_mutex_unlock(&localtime_mutex); 1100 return(NULL); 1101 } 1102 } 1103 _pthread_mutex_unlock(&localtime_mutex); 1104 p_tm = _pthread_getspecific(localtime_key); 1105 if (p_tm == NULL) { 1106 if ((p_tm = (struct tm *)malloc(sizeof(struct tm))) 1107 == NULL) 1108 return(NULL); 1109 _pthread_setspecific(localtime_key, p_tm); 1110 } 1111 _pthread_mutex_lock(&lcl_mutex); 1112 tzset_basic(); 1113 localsub(timep, 0L, p_tm); 1114 _pthread_mutex_unlock(&lcl_mutex); 1115 return(p_tm); 1116 } else { 1117 tzset_basic(); 1118 localsub(timep, 0L, &tm); 1119 return(&tm); 1120 } 1121} 1122 1123/* 1124** Re-entrant version of localtime. 1125*/ 1126 1127struct tm * 1128localtime_r(timep, tm) 1129const time_t * const timep; 1130struct tm * tm; 1131{ 1132 _MUTEX_LOCK(&lcl_mutex); 1133 tzset_basic(); 1134 localsub(timep, 0L, tm); 1135 _MUTEX_UNLOCK(&lcl_mutex); 1136 return tm; 1137} 1138 1139/* 1140** gmtsub is to gmtime as localsub is to localtime. 1141*/ 1142 1143static void 1144gmtsub(timep, offset, tmp) 1145const time_t * const timep; 1146const long offset; 1147struct tm * const tmp; 1148{ 1149 _MUTEX_LOCK(&gmt_mutex); 1150 if (!gmt_is_set) { 1151 gmt_is_set = TRUE; 1152#ifdef ALL_STATE 1153 gmtptr = (struct state *) malloc(sizeof *gmtptr); 1154 if (gmtptr != NULL) 1155#endif /* defined ALL_STATE */ 1156 gmtload(gmtptr); 1157 } 1158 _MUTEX_UNLOCK(&gmt_mutex); 1159 timesub(timep, offset, gmtptr, tmp); 1160#ifdef TM_ZONE 1161 /* 1162 ** Could get fancy here and deliver something such as 1163 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, 1164 ** but this is no time for a treasure hunt. 1165 */ 1166 if (offset != 0) 1167 tmp->TM_ZONE = wildabbr; 1168 else { 1169#ifdef ALL_STATE 1170 if (gmtptr == NULL) 1171 tmp->TM_ZONE = gmt; 1172 else tmp->TM_ZONE = gmtptr->chars; 1173#endif /* defined ALL_STATE */ 1174#ifndef ALL_STATE 1175 tmp->TM_ZONE = gmtptr->chars; 1176#endif /* State Farm */ 1177 } 1178#endif /* defined TM_ZONE */ 1179} 1180 1181struct tm * 1182gmtime(timep) 1183const time_t * const timep; 1184{ 1185 static pthread_mutex_t gmtime_mutex = PTHREAD_MUTEX_INITIALIZER; 1186 static pthread_key_t gmtime_key = -1; 1187 struct tm *p_tm; 1188 1189 if (__isthreaded != 0) { 1190 _pthread_mutex_lock(&gmtime_mutex); 1191 if (gmtime_key < 0) { 1192 if (_pthread_key_create(&gmtime_key, free) < 0) { 1193 _pthread_mutex_unlock(&gmtime_mutex); 1194 return(NULL); 1195 } 1196 } 1197 _pthread_mutex_unlock(&gmtime_mutex); 1198 /* 1199 * Changed to follow POSIX.1 threads standard, which 1200 * is what BSD currently has. 1201 */ 1202 if ((p_tm = _pthread_getspecific(gmtime_key)) == NULL) { 1203 if ((p_tm = (struct tm *)malloc(sizeof(struct tm))) 1204 == NULL) { 1205 return(NULL); 1206 } 1207 _pthread_setspecific(gmtime_key, p_tm); 1208 } 1209 gmtsub(timep, 0L, p_tm); 1210 return(p_tm); 1211 } 1212 else { 1213 gmtsub(timep, 0L, &tm); 1214 return(&tm); 1215 } 1216} 1217 1218/* 1219* Re-entrant version of gmtime. 1220*/ 1221 1222struct tm * 1223gmtime_r(timep, tm) 1224const time_t * const timep; 1225struct tm * tm; 1226{ 1227 gmtsub(timep, 0L, tm); 1228 return tm; 1229} 1230 1231#ifdef STD_INSPIRED 1232 1233struct tm * 1234offtime(timep, offset) 1235const time_t * const timep; 1236const long offset; 1237{ 1238 gmtsub(timep, offset, &tm); 1239 return &tm; 1240} 1241 1242#endif /* defined STD_INSPIRED */ 1243 1244static void 1245timesub(timep, offset, sp, tmp) 1246const time_t * const timep; 1247const long offset; 1248const struct state * const sp; 1249struct tm * const tmp; 1250{ 1251 const struct lsinfo * lp; 1252 long days; 1253 long rem; 1254 long y; 1255 int yleap; 1256 const int * ip; 1257 long corr; 1258 int hit; 1259 int i; 1260 1261 corr = 0; 1262 hit = 0; 1263#ifdef ALL_STATE 1264 i = (sp == NULL) ? 0 : sp->leapcnt; 1265#endif /* defined ALL_STATE */ 1266#ifndef ALL_STATE 1267 i = sp->leapcnt; 1268#endif /* State Farm */ 1269 while (--i >= 0) { 1270 lp = &sp->lsis[i]; 1271 if (*timep >= lp->ls_trans) { 1272 if (*timep == lp->ls_trans) { 1273 hit = ((i == 0 && lp->ls_corr > 0) || 1274 lp->ls_corr > sp->lsis[i - 1].ls_corr); 1275 if (hit) 1276 while (i > 0 && 1277 sp->lsis[i].ls_trans == 1278 sp->lsis[i - 1].ls_trans + 1 && 1279 sp->lsis[i].ls_corr == 1280 sp->lsis[i - 1].ls_corr + 1) { 1281 ++hit; 1282 --i; 1283 } 1284 } 1285 corr = lp->ls_corr; 1286 break; 1287 } 1288 } 1289 days = *timep / SECSPERDAY; 1290 rem = *timep % SECSPERDAY; 1291#ifdef mc68k 1292 if (*timep == 0x80000000) { 1293 /* 1294 ** A 3B1 muffs the division on the most negative number. 1295 */ 1296 days = -24855; 1297 rem = -11648; 1298 } 1299#endif /* defined mc68k */ 1300 rem += (offset - corr); 1301 while (rem < 0) { 1302 rem += SECSPERDAY; 1303 --days; 1304 } 1305 while (rem >= SECSPERDAY) { 1306 rem -= SECSPERDAY; 1307 ++days; 1308 } 1309 tmp->tm_hour = (int) (rem / SECSPERHOUR); 1310 rem = rem % SECSPERHOUR; 1311 tmp->tm_min = (int) (rem / SECSPERMIN); 1312 /* 1313 ** A positive leap second requires a special 1314 ** representation. This uses "... ??:59:60" et seq. 1315 */ 1316 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; 1317 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK); 1318 if (tmp->tm_wday < 0) 1319 tmp->tm_wday += DAYSPERWEEK; 1320 y = EPOCH_YEAR; 1321#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400) 1322 while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) { 1323 long newy; 1324 1325 newy = y + days / DAYSPERNYEAR; 1326 if (days < 0) 1327 --newy; 1328 days -= (newy - y) * DAYSPERNYEAR + 1329 LEAPS_THRU_END_OF(newy - 1) - 1330 LEAPS_THRU_END_OF(y - 1); 1331 y = newy; 1332 } 1333 tmp->tm_year = y - TM_YEAR_BASE; 1334 tmp->tm_yday = (int) days; 1335 ip = mon_lengths[yleap]; 1336 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) 1337 days = days - (long) ip[tmp->tm_mon]; 1338 tmp->tm_mday = (int) (days + 1); 1339 tmp->tm_isdst = 0; 1340#ifdef TM_GMTOFF 1341 tmp->TM_GMTOFF = offset; 1342#endif /* defined TM_GMTOFF */ 1343} 1344 1345char * 1346ctime(timep) 1347const time_t * const timep; 1348{ 1349/* 1350** Section 4.12.3.2 of X3.159-1989 requires that 1351** The ctime function converts the calendar time pointed to by timer 1352** to local time in the form of a string. It is equivalent to 1353** asctime(localtime(timer)) 1354*/ 1355 return asctime(localtime(timep)); 1356} 1357 1358char * 1359ctime_r(timep, buf) 1360const time_t * const timep; 1361char * buf; 1362{ 1363 struct tm tm; 1364 1365 return asctime_r(localtime_r(timep, &tm), buf); 1366} 1367 1368/* 1369** Adapted from code provided by Robert Elz, who writes: 1370** The "best" way to do mktime I think is based on an idea of Bob 1371** Kridle's (so its said...) from a long time ago. 1372** [kridle@xinet.com as of 1996-01-16.] 1373** It does a binary search of the time_t space. Since time_t's are 1374** just 32 bits, its a max of 32 iterations (even at 64 bits it 1375** would still be very reasonable). 1376*/ 1377 1378#ifndef WRONG 1379#define WRONG (-1) 1380#endif /* !defined WRONG */ 1381 1382/* 1383** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com). 1384*/ 1385 1386static int 1387increment_overflow(number, delta) 1388int * number; 1389int delta; 1390{ 1391 int number0; 1392 1393 number0 = *number; 1394 *number += delta; 1395 return (*number < number0) != (delta < 0); 1396} 1397 1398static int 1399normalize_overflow(tensptr, unitsptr, base) 1400int * const tensptr; 1401int * const unitsptr; 1402const int base; 1403{ 1404 int tensdelta; 1405 1406 tensdelta = (*unitsptr >= 0) ? 1407 (*unitsptr / base) : 1408 (-1 - (-1 - *unitsptr) / base); 1409 *unitsptr -= tensdelta * base; 1410 return increment_overflow(tensptr, tensdelta); 1411} 1412 1413static int 1414tmcomp(atmp, btmp) 1415const struct tm * const atmp; 1416const struct tm * const btmp; 1417{ 1418 int result; 1419 1420 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && 1421 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && 1422 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && 1423 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && 1424 (result = (atmp->tm_min - btmp->tm_min)) == 0) 1425 result = atmp->tm_sec - btmp->tm_sec; 1426 return result; 1427} 1428 1429static time_t 1430time2sub(tmp, funcp, offset, okayp, do_norm_secs) 1431struct tm * const tmp; 1432void (* const funcp)(const time_t*, long, struct tm*); 1433const long offset; 1434int * const okayp; 1435const int do_norm_secs; 1436{ 1437 const struct state * sp; 1438 int dir; 1439 int bits; 1440 int i, j ; 1441 int saved_seconds; 1442 time_t newt; 1443 time_t t; 1444 struct tm yourtm, mytm; 1445 1446 *okayp = FALSE; 1447 yourtm = *tmp; 1448 if (do_norm_secs) { 1449 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, 1450 SECSPERMIN)) 1451 return WRONG; 1452 } 1453 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) 1454 return WRONG; 1455 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) 1456 return WRONG; 1457 if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR)) 1458 return WRONG; 1459 /* 1460 ** Turn yourtm.tm_year into an actual year number for now. 1461 ** It is converted back to an offset from TM_YEAR_BASE later. 1462 */ 1463 if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE)) 1464 return WRONG; 1465 while (yourtm.tm_mday <= 0) { 1466 if (increment_overflow(&yourtm.tm_year, -1)) 1467 return WRONG; 1468 i = yourtm.tm_year + (1 < yourtm.tm_mon); 1469 yourtm.tm_mday += year_lengths[isleap(i)]; 1470 } 1471 while (yourtm.tm_mday > DAYSPERLYEAR) { 1472 i = yourtm.tm_year + (1 < yourtm.tm_mon); 1473 yourtm.tm_mday -= year_lengths[isleap(i)]; 1474 if (increment_overflow(&yourtm.tm_year, 1)) 1475 return WRONG; 1476 } 1477 for ( ; ; ) { 1478 i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon]; 1479 if (yourtm.tm_mday <= i) 1480 break; 1481 yourtm.tm_mday -= i; 1482 if (++yourtm.tm_mon >= MONSPERYEAR) { 1483 yourtm.tm_mon = 0; 1484 if (increment_overflow(&yourtm.tm_year, 1)) 1485 return WRONG; 1486 } 1487 } 1488 if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE)) 1489 return WRONG; 1490 /* Don't go below 1900 for POLA */ 1491 if (yourtm.tm_year < 0) 1492 return WRONG; 1493 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) 1494 saved_seconds = 0; 1495 else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) { 1496 /* 1497 ** We can't set tm_sec to 0, because that might push the 1498 ** time below the minimum representable time. 1499 ** Set tm_sec to 59 instead. 1500 ** This assumes that the minimum representable time is 1501 ** not in the same minute that a leap second was deleted from, 1502 ** which is a safer assumption than using 58 would be. 1503 */ 1504 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) 1505 return WRONG; 1506 saved_seconds = yourtm.tm_sec; 1507 yourtm.tm_sec = SECSPERMIN - 1; 1508 } else { 1509 saved_seconds = yourtm.tm_sec; 1510 yourtm.tm_sec = 0; 1511 } 1512 /* 1513 ** Divide the search space in half 1514 ** (this works whether time_t is signed or unsigned). 1515 */ 1516 bits = TYPE_BIT(time_t) - 1; 1517 /* 1518 ** If we have more than this, we will overflow tm_year for tmcomp(). 1519 ** We should really return an error if we cannot represent it. 1520 */ 1521 if (bits > 56) 1522 bits = 56; 1523 /* 1524 ** If time_t is signed, then 0 is just above the median, 1525 ** assuming two's complement arithmetic. 1526 ** If time_t is unsigned, then (1 << bits) is just above the median. 1527 */ 1528 t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits); 1529 for ( ; ; ) { 1530 (*funcp)(&t, offset, &mytm); 1531 dir = tmcomp(&mytm, &yourtm); 1532 if (dir != 0) { 1533 if (bits-- < 0) 1534 return WRONG; 1535 if (bits < 0) 1536 --t; /* may be needed if new t is minimal */ 1537 else if (dir > 0) 1538 t -= ((time_t) 1) << bits; 1539 else t += ((time_t) 1) << bits; 1540 continue; 1541 } 1542 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) 1543 break; 1544 /* 1545 ** Right time, wrong type. 1546 ** Hunt for right time, right type. 1547 ** It's okay to guess wrong since the guess 1548 ** gets checked. 1549 */ 1550 sp = (funcp == localsub) ? lclptr : gmtptr; 1551#ifdef ALL_STATE 1552 if (sp == NULL) 1553 return WRONG; 1554#endif /* defined ALL_STATE */ 1555 for (i = sp->typecnt - 1; i >= 0; --i) { 1556 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) 1557 continue; 1558 for (j = sp->typecnt - 1; j >= 0; --j) { 1559 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) 1560 continue; 1561 newt = t + sp->ttis[j].tt_gmtoff - 1562 sp->ttis[i].tt_gmtoff; 1563 (*funcp)(&newt, offset, &mytm); 1564 if (tmcomp(&mytm, &yourtm) != 0) 1565 continue; 1566 if (mytm.tm_isdst != yourtm.tm_isdst) 1567 continue; 1568 /* 1569 ** We have a match. 1570 */ 1571 t = newt; 1572 goto label; 1573 } 1574 } 1575 return WRONG; 1576 } 1577label: 1578 newt = t + saved_seconds; 1579 if ((newt < t) != (saved_seconds < 0)) 1580 return WRONG; 1581 t = newt; 1582 (*funcp)(&t, offset, tmp); 1583 *okayp = TRUE; 1584 return t; 1585} 1586 1587static time_t 1588time2(tmp, funcp, offset, okayp) 1589struct tm * const tmp; 1590void (* const funcp)(const time_t*, long, struct tm*); 1591const long offset; 1592int * const okayp; 1593{ 1594 time_t t; 1595 1596 /* 1597 ** First try without normalization of seconds 1598 ** (in case tm_sec contains a value associated with a leap second). 1599 ** If that fails, try with normalization of seconds. 1600 */ 1601 t = time2sub(tmp, funcp, offset, okayp, FALSE); 1602 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE); 1603} 1604 1605static time_t 1606time1(tmp, funcp, offset) 1607struct tm * const tmp; 1608void (* const funcp)(const time_t *, long, struct tm *); 1609const long offset; 1610{ 1611 time_t t; 1612 const struct state * sp; 1613 int samei, otheri; 1614 int sameind, otherind; 1615 int i; 1616 int nseen; 1617 int seen[TZ_MAX_TYPES]; 1618 int types[TZ_MAX_TYPES]; 1619 int okay; 1620 1621 if (tmp->tm_isdst > 1) 1622 tmp->tm_isdst = 1; 1623 t = time2(tmp, funcp, offset, &okay); 1624#ifdef PCTS 1625 /* 1626 ** PCTS code courtesy Grant Sullivan (grant@osf.org). 1627 */ 1628 if (okay) 1629 return t; 1630 if (tmp->tm_isdst < 0) 1631 tmp->tm_isdst = 0; /* reset to std and try again */ 1632#endif /* defined PCTS */ 1633#ifndef PCTS 1634 if (okay || tmp->tm_isdst < 0) 1635 return t; 1636#endif /* !defined PCTS */ 1637 /* 1638 ** We're supposed to assume that somebody took a time of one type 1639 ** and did some math on it that yielded a "struct tm" that's bad. 1640 ** We try to divine the type they started from and adjust to the 1641 ** type they need. 1642 */ 1643 sp = (funcp == localsub) ? lclptr : gmtptr; 1644#ifdef ALL_STATE 1645 if (sp == NULL) 1646 return WRONG; 1647#endif /* defined ALL_STATE */ 1648 for (i = 0; i < sp->typecnt; ++i) 1649 seen[i] = FALSE; 1650 nseen = 0; 1651 for (i = sp->timecnt - 1; i >= 0; --i) 1652 if (!seen[sp->types[i]]) { 1653 seen[sp->types[i]] = TRUE; 1654 types[nseen++] = sp->types[i]; 1655 } 1656 for (sameind = 0; sameind < nseen; ++sameind) { 1657 samei = types[sameind]; 1658 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) 1659 continue; 1660 for (otherind = 0; otherind < nseen; ++otherind) { 1661 otheri = types[otherind]; 1662 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) 1663 continue; 1664 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - 1665 sp->ttis[samei].tt_gmtoff; 1666 tmp->tm_isdst = !tmp->tm_isdst; 1667 t = time2(tmp, funcp, offset, &okay); 1668 if (okay) 1669 return t; 1670 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - 1671 sp->ttis[samei].tt_gmtoff; 1672 tmp->tm_isdst = !tmp->tm_isdst; 1673 } 1674 } 1675 return WRONG; 1676} 1677 1678time_t 1679mktime(tmp) 1680struct tm * const tmp; 1681{ 1682 time_t mktime_return_value; 1683 _MUTEX_LOCK(&lcl_mutex); 1684 tzset_basic(); 1685 mktime_return_value = time1(tmp, localsub, 0L); 1686 _MUTEX_UNLOCK(&lcl_mutex); 1687 return(mktime_return_value); 1688} 1689 1690#ifdef STD_INSPIRED 1691 1692time_t 1693timelocal(tmp) 1694struct tm * const tmp; 1695{ 1696 tmp->tm_isdst = -1; /* in case it wasn't initialized */ 1697 return mktime(tmp); 1698} 1699 1700time_t 1701timegm(tmp) 1702struct tm * const tmp; 1703{ 1704 tmp->tm_isdst = 0; 1705 return time1(tmp, gmtsub, 0L); 1706} 1707 1708time_t 1709timeoff(tmp, offset) 1710struct tm * const tmp; 1711const long offset; 1712{ 1713 tmp->tm_isdst = 0; 1714 return time1(tmp, gmtsub, offset); 1715} 1716 1717#endif /* defined STD_INSPIRED */ 1718 1719#ifdef CMUCS 1720 1721/* 1722** The following is supplied for compatibility with 1723** previous versions of the CMUCS runtime library. 1724*/ 1725 1726long 1727gtime(tmp) 1728struct tm * const tmp; 1729{ 1730 const time_t t = mktime(tmp); 1731 1732 if (t == WRONG) 1733 return -1; 1734 return t; 1735} 1736 1737#endif /* defined CMUCS */ 1738 1739/* 1740** XXX--is the below the right way to conditionalize?? 1741*/ 1742 1743#ifdef STD_INSPIRED 1744 1745/* 1746** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599 1747** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which 1748** is not the case if we are accounting for leap seconds. 1749** So, we provide the following conversion routines for use 1750** when exchanging timestamps with POSIX conforming systems. 1751*/ 1752 1753static long 1754leapcorr(timep) 1755time_t * timep; 1756{ 1757 struct state * sp; 1758 struct lsinfo * lp; 1759 int i; 1760 1761 sp = lclptr; 1762 i = sp->leapcnt; 1763 while (--i >= 0) { 1764 lp = &sp->lsis[i]; 1765 if (*timep >= lp->ls_trans) 1766 return lp->ls_corr; 1767 } 1768 return 0; 1769} 1770 1771time_t 1772time2posix(t) 1773time_t t; 1774{ 1775 tzset(); 1776 return t - leapcorr(&t); 1777} 1778 1779time_t 1780posix2time(t) 1781time_t t; 1782{ 1783 time_t x; 1784 time_t y; 1785 1786 tzset(); 1787 /* 1788 ** For a positive leap second hit, the result 1789 ** is not unique. For a negative leap second 1790 ** hit, the corresponding time doesn't exist, 1791 ** so we return an adjacent second. 1792 */ 1793 x = t + leapcorr(&t); 1794 y = x - leapcorr(&x); 1795 if (y < t) { 1796 do { 1797 x++; 1798 y = x - leapcorr(&x); 1799 } while (y < t); 1800 if (t != y) 1801 return x - 1; 1802 } else if (y > t) { 1803 do { 1804 --x; 1805 y = x - leapcorr(&x); 1806 } while (y > t); 1807 if (t != y) 1808 return x + 1; 1809 } 1810 return x; 1811} 1812 1813#endif /* defined STD_INSPIRED */ 1814