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