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