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