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