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