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