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