00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifndef _THREAD_SAFE
00041 #define _THREAD_SAFE
00042 #endif
00043 #define TZ_STRLEN_MAX 255
00044
00045
00046
00047
00048 #include <sys/types.h>
00049 #include <sys/stat.h>
00050 #include <fcntl.h>
00051 #ifdef DEBUG
00052 #include <stdio.h>
00053 #endif
00054
00055 #include "private.h"
00056 #include "tzfile.h"
00057
00058 #include "asterisk.h"
00059
00060 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 51256 $")
00061
00062 #include "asterisk/lock.h"
00063 #include "asterisk/localtime.h"
00064 #include "asterisk/strings.h"
00065
00066 #ifndef lint
00067 #ifndef NOID
00068 static const char elsieid[] = "@(#)localtime.c 7.57";
00069 #endif
00070 #endif
00071
00072
00073
00074
00075
00076
00077
00078 #ifdef O_BINARY
00079 #define OPEN_MODE (O_RDONLY | O_BINARY)
00080 #endif
00081 #ifndef O_BINARY
00082 #define OPEN_MODE O_RDONLY
00083 #endif
00084
00085 #ifdef SOLARIS
00086 #undef TM_ZONE
00087 #undef TM_GMTOFF
00088 #endif
00089
00090 #ifdef TM_ZONE
00091 #ifndef WILDABBR
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 #define WILDABBR " "
00112 #endif
00113
00114 static char wildabbr[] = "WILDABBR";
00115 #endif
00116
00117
00118
00119 static char gmt[] = "GMT";
00120
00121
00122 struct ttinfo {
00123 long tt_gmtoff;
00124 int tt_isdst;
00125 int tt_abbrind;
00126 int tt_ttisstd;
00127 int tt_ttisgmt;
00128 };
00129
00130
00131 struct lsinfo {
00132 time_t ls_trans;
00133 long ls_corr;
00134 };
00135
00136 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
00137
00138 #ifdef TZNAME_MAX
00139 #define MY_TZNAME_MAX TZNAME_MAX
00140 #endif
00141 #ifndef TZNAME_MAX
00142 #define MY_TZNAME_MAX 255
00143 #endif
00144
00145 struct state {
00146 char name[TZ_STRLEN_MAX + 1];
00147 int leapcnt;
00148 int timecnt;
00149 int typecnt;
00150 int charcnt;
00151 time_t ats[TZ_MAX_TIMES];
00152 unsigned char types[TZ_MAX_TIMES];
00153 struct ttinfo ttis[TZ_MAX_TYPES];
00154 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
00155 (2 * (MY_TZNAME_MAX + 1)))];
00156 struct lsinfo lsis[TZ_MAX_LEAPS];
00157 struct state *next;
00158 };
00159
00160 struct rule {
00161 int r_type;
00162 int r_day;
00163 int r_week;
00164 int r_mon;
00165 long r_time;
00166 };
00167
00168 #define JULIAN_DAY 0
00169 #define DAY_OF_YEAR 1
00170 #define MONTH_NTH_DAY_OF_WEEK 2
00171
00172
00173
00174
00175
00176 static long detzcode P((const char * codep));
00177 static const char * getnum P((const char * strp, int * nump, int min,
00178 int max));
00179 static const char * getsecs P((const char * strp, long * secsp));
00180 static const char * getoffset P((const char * strp, long * offsetp));
00181 static const char * getrule P((const char * strp, struct rule * rulep));
00182 static void gmtload P((struct state * sp));
00183 static void gmtsub P((const time_t * timep, long offset,
00184 struct tm * tmp, const char * zone));
00185 static void localsub P((const time_t * timep, long offset,
00186 struct tm * tmp, const char * zone));
00187 static int increment_overflow P((int * number, int delta));
00188 static int normalize_overflow P((int * tensptr, int * unitsptr,
00189 int base));
00190 static time_t time1 P((struct tm * tmp,
00191 void(*funcp) P((const time_t *,
00192 long, struct tm *, const char*)),
00193 long offset, const char * zone));
00194 static time_t time2 P((struct tm *tmp,
00195 void(*funcp) P((const time_t *,
00196 long, struct tm*, const char*)),
00197 long offset, int * okayp, const char * zone));
00198 static void timesub P((const time_t * timep, long offset,
00199 const struct state * sp, struct tm * tmp));
00200 static int tmcomp P((const struct tm * atmp,
00201 const struct tm * btmp));
00202 static time_t transtime P((time_t janfirst, int year,
00203 const struct rule * rulep, long offset));
00204 static int tzload P((const char * name, struct state * sp));
00205 static int tzparse P((const char * name, struct state * sp,
00206 int lastditch));
00207
00208 static struct state * lclptr = NULL;
00209 static struct state * last_lclptr = NULL;
00210 static struct state * gmtptr = NULL;
00211
00212 #ifndef TZ_STRLEN_MAX
00213 #define TZ_STRLEN_MAX 255
00214 #endif
00215
00216 static int gmt_is_set;
00217 #ifdef _THREAD_SAFE
00218 AST_MUTEX_DEFINE_STATIC(lcl_mutex);
00219 AST_MUTEX_DEFINE_STATIC(tzset_mutex);
00220 AST_MUTEX_DEFINE_STATIC(tzsetwall_mutex);
00221 AST_MUTEX_DEFINE_STATIC(gmt_mutex);
00222 #endif
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 static long detzcode(const char * const codep)
00233 {
00234 register long result;
00235 register int i;
00236
00237 result = (codep[0] & 0x80) ? ~0L : 0L;
00238 for (i = 0; i < 4; ++i)
00239 result = (result << 8) | (codep[i] & 0xff);
00240 return result;
00241 }
00242
00243 static int tzload(register const char *name, register struct state *const sp)
00244 {
00245 register const char * p;
00246 register int i;
00247 register int fid;
00248
00249 #ifdef DEBUG
00250 fprintf(stderr,"tzload called with name=%s, sp=%d\n", name, sp);
00251 #endif
00252 if (name == NULL && (name = TZDEFAULT) == NULL)
00253 return -1;
00254 {
00255 register int doaccess;
00256 struct stat stab;
00257
00258
00259
00260
00261
00262
00263
00264 char fullname[FILENAME_MAX + 1] = "";
00265
00266 if (name[0] == ':')
00267 ++name;
00268 doaccess = name[0] == '/';
00269 if (!doaccess) {
00270 if ((p = TZDIR) == NULL)
00271 return -1;
00272 if ((strlen(p) + 1 + strlen(name) + 1) >= sizeof fullname)
00273 return -1;
00274 (void) strncpy(fullname, p, sizeof(fullname) - 1);
00275 (void) strncat(fullname, "/", sizeof(fullname) - strlen(fullname) - 1);
00276 (void) strncat(fullname, name, sizeof(fullname) - strlen(fullname) - 1);
00277
00278
00279
00280 if (strchr(name, '.') != NULL)
00281 doaccess = TRUE;
00282 name = fullname;
00283 }
00284 if (doaccess && access(name, R_OK) != 0)
00285 return -1;
00286 if ((fid = open(name, OPEN_MODE)) == -1)
00287 return -1;
00288 if ((fstat(fid, &stab) < 0) || !S_ISREG(stab.st_mode)) {
00289 close(fid);
00290 return -1;
00291 }
00292 }
00293 {
00294 struct tzhead * tzhp;
00295 char buf[sizeof *sp + sizeof *tzhp];
00296 int ttisstdcnt;
00297 int ttisgmtcnt;
00298
00299 i = read(fid, buf, sizeof buf);
00300 if (close(fid) != 0)
00301 return -1;
00302 p = buf;
00303 p += (sizeof tzhp->tzh_magic) + (sizeof tzhp->tzh_reserved);
00304 ttisstdcnt = (int) detzcode(p);
00305 p += 4;
00306 ttisgmtcnt = (int) detzcode(p);
00307 p += 4;
00308 sp->leapcnt = (int) detzcode(p);
00309 p += 4;
00310 sp->timecnt = (int) detzcode(p);
00311 p += 4;
00312 sp->typecnt = (int) detzcode(p);
00313 p += 4;
00314 sp->charcnt = (int) detzcode(p);
00315 p += 4;
00316 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
00317 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
00318 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
00319 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
00320 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
00321 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
00322 return -1;
00323 if (i - (p - buf) < sp->timecnt * 4 +
00324 sp->timecnt +
00325 sp->typecnt * (4 + 2) +
00326 sp->charcnt +
00327 sp->leapcnt * (4 + 4) +
00328 ttisstdcnt +
00329 ttisgmtcnt)
00330 return -1;
00331 for (i = 0; i < sp->timecnt; ++i) {
00332 sp->ats[i] = detzcode(p);
00333 p += 4;
00334 }
00335 for (i = 0; i < sp->timecnt; ++i) {
00336 sp->types[i] = (unsigned char) *p++;
00337 if (sp->types[i] >= sp->typecnt)
00338 return -1;
00339 }
00340 for (i = 0; i < sp->typecnt; ++i) {
00341 register struct ttinfo * ttisp;
00342
00343 ttisp = &sp->ttis[i];
00344 ttisp->tt_gmtoff = detzcode(p);
00345 p += 4;
00346 ttisp->tt_isdst = (unsigned char) *p++;
00347 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
00348 return -1;
00349 ttisp->tt_abbrind = (unsigned char) *p++;
00350 if (ttisp->tt_abbrind < 0 ||
00351 ttisp->tt_abbrind > sp->charcnt)
00352 return -1;
00353 }
00354 for (i = 0; i < sp->charcnt; ++i)
00355 sp->chars[i] = *p++;
00356 sp->chars[i] = '\0';
00357 for (i = 0; i < sp->leapcnt; ++i) {
00358 register struct lsinfo * lsisp;
00359
00360 lsisp = &sp->lsis[i];
00361 lsisp->ls_trans = detzcode(p);
00362 p += 4;
00363 lsisp->ls_corr = detzcode(p);
00364 p += 4;
00365 }
00366 for (i = 0; i < sp->typecnt; ++i) {
00367 register struct ttinfo * ttisp;
00368
00369 ttisp = &sp->ttis[i];
00370 if (ttisstdcnt == 0)
00371 ttisp->tt_ttisstd = FALSE;
00372 else {
00373 ttisp->tt_ttisstd = *p++;
00374 if (ttisp->tt_ttisstd != TRUE &&
00375 ttisp->tt_ttisstd != FALSE)
00376 return -1;
00377 }
00378 }
00379 for (i = 0; i < sp->typecnt; ++i) {
00380 register struct ttinfo * ttisp;
00381
00382 ttisp = &sp->ttis[i];
00383 if (ttisgmtcnt == 0)
00384 ttisp->tt_ttisgmt = FALSE;
00385 else {
00386 ttisp->tt_ttisgmt = *p++;
00387 if (ttisp->tt_ttisgmt != TRUE &&
00388 ttisp->tt_ttisgmt != FALSE)
00389 return -1;
00390 }
00391 }
00392 }
00393 return 0;
00394 }
00395
00396 static const int mon_lengths[2][MONSPERYEAR] = {
00397 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
00398 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
00399 };
00400
00401 static const int year_lengths[2] = {
00402 DAYSPERNYEAR, DAYSPERLYEAR
00403 };
00404
00405
00406
00407
00408
00409
00410
00411
00412 static const char *getnum(register const char *strp, int * const nump, const int min, const int max)
00413 {
00414 register char c;
00415 register int num;
00416
00417 if (strp == NULL || !is_digit(c = *strp))
00418 return NULL;
00419 num = 0;
00420 do {
00421 num = num * 10 + (c - '0');
00422 if (num > max)
00423 return NULL;
00424 c = *++strp;
00425 } while (is_digit(c));
00426 if (num < min)
00427 return NULL;
00428 *nump = num;
00429 return strp;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 static const char *getsecs(register const char *strp, long * const secsp)
00441 {
00442 int num;
00443
00444
00445
00446
00447
00448
00449
00450 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
00451 if (strp == NULL)
00452 return NULL;
00453 *secsp = num * (long) SECSPERHOUR;
00454 if (*strp == ':') {
00455 ++strp;
00456 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
00457 if (strp == NULL)
00458 return NULL;
00459 *secsp += num * SECSPERMIN;
00460 if (*strp == ':') {
00461 ++strp;
00462
00463 strp = getnum(strp, &num, 0, SECSPERMIN);
00464 if (strp == NULL)
00465 return NULL;
00466 *secsp += num;
00467 }
00468 }
00469 return strp;
00470 }
00471
00472
00473
00474
00475
00476
00477
00478
00479 static const char * getoffset(register const char *strp, long * const offsetp)
00480 {
00481 register int neg = 0;
00482
00483 if (*strp == '-') {
00484 neg = 1;
00485 ++strp;
00486 } else if (*strp == '+')
00487 ++strp;
00488 strp = getsecs(strp, offsetp);
00489 if (strp == NULL)
00490 return NULL;
00491 if (neg)
00492 *offsetp = -*offsetp;
00493 return strp;
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503 static const char *getrule(const char *strp, register struct rule * const rulep)
00504 {
00505 if (*strp == 'J') {
00506
00507
00508
00509 rulep->r_type = JULIAN_DAY;
00510 ++strp;
00511 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
00512 } else if (*strp == 'M') {
00513
00514
00515
00516 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
00517 ++strp;
00518 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
00519 if (strp == NULL)
00520 return NULL;
00521 if (*strp++ != '.')
00522 return NULL;
00523 strp = getnum(strp, &rulep->r_week, 1, 5);
00524 if (strp == NULL)
00525 return NULL;
00526 if (*strp++ != '.')
00527 return NULL;
00528 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
00529 } else if (is_digit(*strp)) {
00530
00531
00532
00533 rulep->r_type = DAY_OF_YEAR;
00534 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
00535 } else return NULL;
00536 if (strp == NULL)
00537 return NULL;
00538 if (*strp == '/') {
00539
00540
00541
00542 ++strp;
00543 strp = getsecs(strp, &rulep->r_time);
00544 } else rulep->r_time = 2 * SECSPERHOUR;
00545 return strp;
00546 }
00547
00548
00549
00550
00551
00552
00553
00554 static time_t transtime(janfirst, year, rulep, offset)
00555 const time_t janfirst;
00556 const int year;
00557 register const struct rule * const rulep;
00558 const long offset;
00559 {
00560 register int leapyear;
00561 register time_t value = 0;
00562 register int i;
00563 int d, m1, yy0, yy1, yy2, dow;
00564
00565 leapyear = isleap(year);
00566 switch (rulep->r_type) {
00567
00568 case JULIAN_DAY:
00569
00570
00571
00572
00573
00574
00575
00576 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
00577 if (leapyear && rulep->r_day >= 60)
00578 value += SECSPERDAY;
00579 break;
00580
00581 case DAY_OF_YEAR:
00582
00583
00584
00585
00586
00587 value = janfirst + rulep->r_day * SECSPERDAY;
00588 break;
00589
00590 case MONTH_NTH_DAY_OF_WEEK:
00591
00592
00593
00594 value = janfirst;
00595 for (i = 0; i < rulep->r_mon - 1; ++i)
00596 value += mon_lengths[leapyear][i] * SECSPERDAY;
00597
00598
00599
00600
00601
00602 m1 = (rulep->r_mon + 9) % 12 + 1;
00603 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
00604 yy1 = yy0 / 100;
00605 yy2 = yy0 % 100;
00606 dow = ((26 * m1 - 2) / 10 +
00607 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
00608 if (dow < 0)
00609 dow += DAYSPERWEEK;
00610
00611
00612
00613
00614
00615
00616 d = rulep->r_day - dow;
00617 if (d < 0)
00618 d += DAYSPERWEEK;
00619 for (i = 1; i < rulep->r_week; ++i) {
00620 if (d + DAYSPERWEEK >=
00621 mon_lengths[leapyear][rulep->r_mon - 1])
00622 break;
00623 d += DAYSPERWEEK;
00624 }
00625
00626
00627
00628
00629 value += d * SECSPERDAY;
00630 break;
00631 }
00632
00633
00634
00635
00636
00637
00638
00639 return value + rulep->r_time + offset;
00640 }
00641
00642
00643
00644
00645
00646
00647 static int
00648 tzparse(name, sp, lastditch)
00649 const char * name;
00650 register struct state * const sp;
00651 const int lastditch;
00652 {
00653 const char * stdname;
00654 const char * dstname = NULL;
00655 size_t stdlen = 0;
00656 size_t dstlen = 0;
00657 long stdoffset = 0L;
00658 long dstoffset = 0L;
00659 register time_t * atp;
00660 register unsigned char * typep;
00661 register char * cp;
00662 register int load_result;
00663
00664 stdname = name;
00665 #ifdef DEBUG
00666 fprintf(stderr, "tzparse(): loading default rules\n");
00667 #endif
00668 load_result = tzload(TZDEFRULES, sp);
00669 if (load_result != 0)
00670 sp->leapcnt = 0;
00671 if (*name != '\0') {
00672 if (*name != '\0' && *name != ',' && *name != ';') {
00673 name = getoffset(name, &dstoffset);
00674 if (name == NULL)
00675 return -1;
00676 } else dstoffset = stdoffset - SECSPERHOUR;
00677 if (*name == ',' || *name == ';') {
00678 struct rule start;
00679 struct rule end;
00680 register int year;
00681 register time_t janfirst;
00682 time_t starttime;
00683 time_t endtime;
00684
00685 ++name;
00686 if ((name = getrule(name, &start)) == NULL)
00687 return -1;
00688 if (*name++ != ',')
00689 return -1;
00690 if ((name = getrule(name, &end)) == NULL)
00691 return -1;
00692 if (*name != '\0')
00693 return -1;
00694 sp->typecnt = 2;
00695
00696
00697
00698 sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
00699 if (sp->timecnt > TZ_MAX_TIMES)
00700 return -1;
00701 sp->ttis[0].tt_gmtoff = -dstoffset;
00702 sp->ttis[0].tt_isdst = 1;
00703 sp->ttis[0].tt_abbrind = stdlen + 1;
00704 sp->ttis[1].tt_gmtoff = -stdoffset;
00705 sp->ttis[1].tt_isdst = 0;
00706 sp->ttis[1].tt_abbrind = 0;
00707 atp = sp->ats;
00708 typep = sp->types;
00709 janfirst = 0;
00710 for (year = EPOCH_YEAR; year <= 2037; ++year) {
00711 starttime = transtime(janfirst, year, &start,
00712 stdoffset);
00713 endtime = transtime(janfirst, year, &end,
00714 dstoffset);
00715 if (starttime > endtime) {
00716 *atp++ = endtime;
00717 *typep++ = 1;
00718 *atp++ = starttime;
00719 *typep++ = 0;
00720 } else {
00721 *atp++ = starttime;
00722 *typep++ = 0;
00723 *atp++ = endtime;
00724 *typep++ = 1;
00725 }
00726 janfirst += year_lengths[isleap(year)] *
00727 SECSPERDAY;
00728 }
00729 } else {
00730 register long theirstdoffset;
00731 register long theirdstoffset;
00732 register long theiroffset;
00733 register int isdst;
00734 register int i;
00735 register int j;
00736
00737 if (*name != '\0')
00738 return -1;
00739 if (load_result != 0)
00740 return -1;
00741
00742
00743
00744 theirstdoffset = 0;
00745 for (i = 0; i < sp->timecnt; ++i) {
00746 j = sp->types[i];
00747 if (!sp->ttis[j].tt_isdst) {
00748 theirstdoffset =
00749 -sp->ttis[j].tt_gmtoff;
00750 break;
00751 }
00752 }
00753 theirdstoffset = 0;
00754 for (i = 0; i < sp->timecnt; ++i) {
00755 j = sp->types[i];
00756 if (sp->ttis[j].tt_isdst) {
00757 theirdstoffset =
00758 -sp->ttis[j].tt_gmtoff;
00759 break;
00760 }
00761 }
00762
00763
00764
00765 isdst = FALSE;
00766 theiroffset = theirstdoffset;
00767
00768
00769
00770
00771 for (i = 0; i < sp->timecnt; ++i) {
00772 j = sp->types[i];
00773 sp->types[i] = sp->ttis[j].tt_isdst;
00774 if (sp->ttis[j].tt_ttisgmt) {
00775
00776 } else {
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791 if (isdst && !sp->ttis[j].tt_ttisstd) {
00792 sp->ats[i] += dstoffset -
00793 theirdstoffset;
00794 } else {
00795 sp->ats[i] += stdoffset -
00796 theirstdoffset;
00797 }
00798 }
00799 theiroffset = -sp->ttis[j].tt_gmtoff;
00800 if (sp->ttis[j].tt_isdst)
00801 theirdstoffset = theiroffset;
00802 else theirstdoffset = theiroffset;
00803 }
00804
00805
00806
00807
00808 sp->ttis[0].tt_gmtoff = -stdoffset;
00809 sp->ttis[0].tt_isdst = FALSE;
00810 sp->ttis[0].tt_abbrind = 0;
00811 sp->ttis[1].tt_gmtoff = -dstoffset;
00812 sp->ttis[1].tt_isdst = TRUE;
00813 sp->ttis[1].tt_abbrind = stdlen + 1;
00814 }
00815 } else {
00816 dstlen = 0;
00817 sp->typecnt = 1;
00818 sp->timecnt = 0;
00819 sp->ttis[0].tt_gmtoff = -stdoffset;
00820 sp->ttis[0].tt_isdst = 0;
00821 sp->ttis[0].tt_abbrind = 0;
00822 }
00823 sp->charcnt = stdlen + 1;
00824 if (dstlen != 0)
00825 sp->charcnt += dstlen + 1;
00826 if (sp->charcnt > sizeof sp->chars)
00827 return -1;
00828 cp = sp->chars;
00829 (void) strncpy(cp, stdname, stdlen);
00830 cp += stdlen;
00831 *cp++ = '\0';
00832 if (dstlen != 0) {
00833 (void) strncpy(cp, dstname, dstlen);
00834 *(cp + dstlen) = '\0';
00835 }
00836 return 0;
00837 }
00838
00839 static void
00840 gmtload(sp)
00841 struct state * const sp;
00842 {
00843 if (tzload(gmt, sp) != 0)
00844 (void) tzparse(gmt, sp, TRUE);
00845 }
00846
00847
00848
00849
00850
00851 static
00852 #ifdef _THREAD_SAFE
00853 int
00854 ast_tzsetwall_basic P((void))
00855 #else
00856 int
00857 ast_tzsetwall P((void))
00858 #endif
00859 {
00860 struct state *cur_state = lclptr;
00861
00862
00863 while (cur_state != NULL) {
00864 if (cur_state->name[0] == '\0')
00865 break;
00866 cur_state = cur_state->next;
00867 }
00868 if (cur_state != NULL)
00869 return 0;
00870 cur_state = malloc(sizeof(struct state));
00871 if (cur_state == NULL) {
00872 return -1;
00873 }
00874 memset(cur_state,0,sizeof(struct state));
00875 if (tzload((char *) NULL, cur_state) != 0)
00876 #ifdef DEBUG
00877 {
00878 fprintf(stderr, "ast_tzsetwall: calling gmtload()\n");
00879 #endif
00880 gmtload(cur_state);
00881 #ifdef DEBUG
00882 }
00883 #endif
00884
00885 if (last_lclptr)
00886 last_lclptr->next = cur_state;
00887 else
00888 lclptr = cur_state;
00889 last_lclptr = cur_state;
00890 return 0;
00891 }
00892
00893 #ifdef _THREAD_SAFE
00894 int
00895 ast_tzsetwall P((void))
00896 {
00897 ast_mutex_lock(&tzsetwall_mutex);
00898 ast_tzsetwall_basic();
00899 ast_mutex_unlock(&tzsetwall_mutex);
00900 return 0;
00901 }
00902 #endif
00903
00904 #ifdef _THREAD_SAFE
00905 static int
00906 ast_tzset_basic P((const char *name))
00907 #else
00908 int
00909 ast_tzset P((const char *name))
00910 #endif
00911 {
00912 struct state *cur_state = lclptr;
00913
00914
00915 if (name == NULL) {
00916 return ast_tzsetwall();
00917 }
00918
00919
00920 while (cur_state != NULL) {
00921 if (!strcmp(cur_state->name,name))
00922 break;
00923 cur_state = cur_state->next;
00924 }
00925 if (cur_state != NULL)
00926 return 0;
00927
00928 cur_state = malloc(sizeof(struct state));
00929 if (cur_state == NULL) {
00930 return -1;
00931 }
00932 memset(cur_state,0,sizeof(*cur_state));
00933
00934
00935 if (name[0] == '\0') {
00936
00937
00938
00939 cur_state->leapcnt = 0;
00940 cur_state->timecnt = 0;
00941 cur_state->ttis[0].tt_gmtoff = 0;
00942 cur_state->ttis[0].tt_abbrind = 0;
00943 (void) strncpy(cur_state->chars, gmt, sizeof(cur_state->chars) - 1);
00944 } else if (tzload(name, cur_state) != 0) {
00945 if (name[0] == ':') {
00946 (void) gmtload(cur_state);
00947 } else if (tzparse(name, cur_state, FALSE) != 0) {
00948
00949 if (tzload("/etc/localtime", cur_state) != 0)
00950
00951 (void) gmtload(cur_state);
00952 }
00953 }
00954 strncpy(cur_state->name, name, sizeof(cur_state->name) - 1);
00955 if (last_lclptr)
00956 last_lclptr->next = cur_state;
00957 else
00958 lclptr = cur_state;
00959 last_lclptr = cur_state;
00960 return 0;
00961 }
00962
00963 #ifdef _THREAD_SAFE
00964 void
00965 ast_tzset P((const char *name))
00966 {
00967 ast_mutex_lock(&tzset_mutex);
00968 ast_tzset_basic(name);
00969 ast_mutex_unlock(&tzset_mutex);
00970 }
00971 #endif
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 static void
00984 localsub(timep, offset, tmp, zone)
00985 const time_t * const timep;
00986 const long offset;
00987 struct tm * const tmp;
00988 const char * const zone;
00989 {
00990 register struct state * sp;
00991 register const struct ttinfo * ttisp;
00992 register int i;
00993 const time_t t = *timep;
00994
00995 sp = lclptr;
00996
00997 if (zone == NULL)
00998 sp = NULL;
00999 else
01000 while (sp != NULL) {
01001 if (!strcmp(sp->name,zone))
01002 break;
01003 sp = sp->next;
01004 }
01005
01006 if (sp == NULL) {
01007 ast_tzsetwall();
01008 sp = lclptr;
01009
01010 while (sp != NULL) {
01011 if (sp->name[0] == '\0')
01012 break;
01013 sp = sp->next;
01014 }
01015 }
01016
01017
01018 if (sp == NULL) {
01019 gmtsub(timep, offset, tmp, zone);
01020 return;
01021 }
01022 if (sp->timecnt == 0 || t < sp->ats[0]) {
01023 i = 0;
01024 while (sp->ttis[i].tt_isdst)
01025 if (++i >= sp->typecnt) {
01026 i = 0;
01027 break;
01028 }
01029 } else {
01030 for (i = 1; i < sp->timecnt; ++i)
01031 if (t < sp->ats[i])
01032 break;
01033 i = sp->types[i - 1];
01034 }
01035 ttisp = &sp->ttis[i];
01036
01037
01038
01039
01040
01041
01042 timesub(&t, ttisp->tt_gmtoff, sp, tmp);
01043 tmp->tm_isdst = ttisp->tt_isdst;
01044 tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
01045 #ifdef TM_ZONE
01046 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
01047 #endif
01048 }
01049
01050 struct tm *
01051 ast_localtime(timep, p_tm, zone)
01052 const time_t * const timep;
01053 struct tm *p_tm;
01054 const char * const zone;
01055 {
01056 #ifdef _THREAD_SAFE
01057 ast_mutex_lock(&lcl_mutex);
01058 #endif
01059 ast_tzset(ast_strlen_zero(zone) ? "/etc/localtime" : zone);
01060 localsub(timep, 0L, p_tm, zone);
01061 #ifdef _THREAD_SAFE
01062 ast_mutex_unlock(&lcl_mutex);
01063 #endif
01064 return(p_tm);
01065 }
01066
01067
01068
01069
01070
01071 static void
01072 gmtsub(timep, offset, tmp, zone)
01073 const time_t * const timep;
01074 const long offset;
01075 struct tm * const tmp;
01076 const char * const zone;
01077 {
01078 #ifdef _THREAD_SAFE
01079 ast_mutex_lock(&gmt_mutex);
01080 #endif
01081 if (!gmt_is_set) {
01082 gmt_is_set = TRUE;
01083 gmtptr = (struct state *) malloc(sizeof *gmtptr);
01084 if (gmtptr != NULL)
01085 gmtload(gmtptr);
01086 }
01087 ast_mutex_unlock(&gmt_mutex);
01088 timesub(timep, offset, gmtptr, tmp);
01089 #ifdef TM_ZONE
01090
01091
01092
01093
01094
01095 if (offset != 0)
01096 tmp->TM_ZONE = wildabbr;
01097 else {
01098 if (gmtptr == NULL)
01099 tmp->TM_ZONE = gmt;
01100 else tmp->TM_ZONE = gmtptr->chars;
01101 }
01102 #endif
01103 }
01104
01105 static void
01106 timesub(timep, offset, sp, tmp)
01107 const time_t * const timep;
01108 const long offset;
01109 register const struct state * const sp;
01110 register struct tm * const tmp;
01111 {
01112 register const struct lsinfo * lp;
01113 register long days;
01114 register long rem;
01115 register int y;
01116 register int yleap;
01117 register const int * ip;
01118 register long corr;
01119 register int hit;
01120 register int i;
01121
01122 corr = 0;
01123 hit = 0;
01124 i = (sp == NULL) ? 0 : sp->leapcnt;
01125 while (--i >= 0) {
01126 lp = &sp->lsis[i];
01127 if (*timep >= lp->ls_trans) {
01128 if (*timep == lp->ls_trans) {
01129 hit = ((i == 0 && lp->ls_corr > 0) ||
01130 lp->ls_corr > sp->lsis[i - 1].ls_corr);
01131 if (hit)
01132 while (i > 0 &&
01133 sp->lsis[i].ls_trans ==
01134 sp->lsis[i - 1].ls_trans + 1 &&
01135 sp->lsis[i].ls_corr ==
01136 sp->lsis[i - 1].ls_corr + 1) {
01137 ++hit;
01138 --i;
01139 }
01140 }
01141 corr = lp->ls_corr;
01142 break;
01143 }
01144 }
01145 days = *timep / SECSPERDAY;
01146 rem = *timep % SECSPERDAY;
01147 #ifdef mc68k
01148 if (*timep == 0x80000000) {
01149
01150
01151
01152 days = -24855;
01153 rem = -11648;
01154 }
01155 #endif
01156 rem += (offset - corr);
01157 while (rem < 0) {
01158 rem += SECSPERDAY;
01159 --days;
01160 }
01161 while (rem >= SECSPERDAY) {
01162 rem -= SECSPERDAY;
01163 ++days;
01164 }
01165 tmp->tm_hour = (int) (rem / SECSPERHOUR);
01166 rem = rem % SECSPERHOUR;
01167 tmp->tm_min = (int) (rem / SECSPERMIN);
01168
01169
01170
01171
01172 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
01173 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
01174 if (tmp->tm_wday < 0)
01175 tmp->tm_wday += DAYSPERWEEK;
01176 y = EPOCH_YEAR;
01177 #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
01178 while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
01179 register int newy;
01180
01181 newy = y + days / DAYSPERNYEAR;
01182 if (days < 0)
01183 --newy;
01184 days -= (newy - y) * DAYSPERNYEAR +
01185 LEAPS_THRU_END_OF(newy - 1) -
01186 LEAPS_THRU_END_OF(y - 1);
01187 y = newy;
01188 }
01189 tmp->tm_year = y - TM_YEAR_BASE;
01190 tmp->tm_yday = (int) days;
01191 ip = mon_lengths[yleap];
01192 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
01193 days = days - (long) ip[tmp->tm_mon];
01194 tmp->tm_mday = (int) (days + 1);
01195 tmp->tm_isdst = 0;
01196 #ifdef TM_GMTOFF
01197 tmp->TM_GMTOFF = offset;
01198 #endif
01199 }
01200
01201 char *
01202 ast_ctime(timep)
01203 const time_t * const timep;
01204 {
01205
01206
01207
01208
01209
01210
01211 return asctime(localtime(timep));
01212 }
01213
01214 char *
01215 ast_ctime_r(timep, buf)
01216 const time_t * const timep;
01217 char *buf;
01218 {
01219 struct tm tm;
01220 return asctime_r(localtime_r(timep, &tm), buf);
01221 }
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233 #ifndef WRONG
01234 #define WRONG (-1)
01235 #endif
01236
01237
01238
01239
01240
01241 static int
01242 increment_overflow(number, delta)
01243 int * number;
01244 int delta;
01245 {
01246 int number0;
01247
01248 number0 = *number;
01249 *number += delta;
01250 return (*number < number0) != (delta < 0);
01251 }
01252
01253 static int
01254 normalize_overflow(tensptr, unitsptr, base)
01255 int * const tensptr;
01256 int * const unitsptr;
01257 const int base;
01258 {
01259 register int tensdelta;
01260
01261 tensdelta = (*unitsptr >= 0) ?
01262 (*unitsptr / base) :
01263 (-1 - (-1 - *unitsptr) / base);
01264 *unitsptr -= tensdelta * base;
01265 return increment_overflow(tensptr, tensdelta);
01266 }
01267
01268 static int
01269 tmcomp(atmp, btmp)
01270 register const struct tm * const atmp;
01271 register const struct tm * const btmp;
01272 {
01273 register int result;
01274
01275 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
01276 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
01277 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
01278 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
01279 (result = (atmp->tm_min - btmp->tm_min)) == 0)
01280 result = atmp->tm_sec - btmp->tm_sec;
01281 return result;
01282 }
01283
01284 static time_t
01285 time2(tmp, funcp, offset, okayp, zone)
01286 struct tm * const tmp;
01287 void (* const funcp) P((const time_t*, long, struct tm*, const char*));
01288 const long offset;
01289 int * const okayp;
01290 const char * const zone;
01291 {
01292 register const struct state * sp;
01293 register int dir;
01294 register int bits;
01295 register int i, j ;
01296 register int saved_seconds;
01297 time_t newt;
01298 time_t t;
01299 struct tm yourtm, mytm;
01300
01301 *okayp = FALSE;
01302 yourtm = *tmp;
01303 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
01304 return WRONG;
01305 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
01306 return WRONG;
01307 if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
01308 return WRONG;
01309
01310
01311
01312
01313 if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
01314 return WRONG;
01315 while (yourtm.tm_mday <= 0) {
01316 if (increment_overflow(&yourtm.tm_year, -1))
01317 return WRONG;
01318 i = yourtm.tm_year + (1 < yourtm.tm_mon);
01319 yourtm.tm_mday += year_lengths[isleap(i)];
01320 }
01321 while (yourtm.tm_mday > DAYSPERLYEAR) {
01322 i = yourtm.tm_year + (1 < yourtm.tm_mon);
01323 yourtm.tm_mday -= year_lengths[isleap(i)];
01324 if (increment_overflow(&yourtm.tm_year, 1))
01325 return WRONG;
01326 }
01327 for ( ; ; ) {
01328 i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
01329 if (yourtm.tm_mday <= i)
01330 break;
01331 yourtm.tm_mday -= i;
01332 if (++yourtm.tm_mon >= MONSPERYEAR) {
01333 yourtm.tm_mon = 0;
01334 if (increment_overflow(&yourtm.tm_year, 1))
01335 return WRONG;
01336 }
01337 }
01338 if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
01339 return WRONG;
01340 if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
01341
01342
01343
01344
01345
01346
01347
01348
01349 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
01350 return WRONG;
01351 saved_seconds = yourtm.tm_sec;
01352 yourtm.tm_sec = SECSPERMIN - 1;
01353 } else {
01354 saved_seconds = yourtm.tm_sec;
01355 yourtm.tm_sec = 0;
01356 }
01357
01358
01359
01360
01361 bits = TYPE_BIT(time_t) - 1;
01362
01363
01364
01365
01366
01367 t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
01368 for ( ; ; ) {
01369 (*funcp)(&t, offset, &mytm, zone);
01370 dir = tmcomp(&mytm, &yourtm);
01371 if (dir != 0) {
01372 if (bits-- < 0)
01373 return WRONG;
01374 if (bits < 0)
01375 --t;
01376 else if (dir > 0)
01377 t -= ((time_t) 1) << bits;
01378 else t += ((time_t) 1) << bits;
01379 continue;
01380 }
01381 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
01382 break;
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392 sp = (const struct state *)
01393 (((void *) funcp == (void *) localsub) ?
01394 lclptr : gmtptr);
01395 if (sp == NULL)
01396 return WRONG;
01397 for (i = sp->typecnt - 1; i >= 0; --i) {
01398 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
01399 continue;
01400 for (j = sp->typecnt - 1; j >= 0; --j) {
01401 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
01402 continue;
01403 newt = t + sp->ttis[j].tt_gmtoff -
01404 sp->ttis[i].tt_gmtoff;
01405 (*funcp)(&newt, offset, &mytm, zone);
01406 if (tmcomp(&mytm, &yourtm) != 0)
01407 continue;
01408 if (mytm.tm_isdst != yourtm.tm_isdst)
01409 continue;
01410
01411
01412
01413 t = newt;
01414 goto label;
01415 }
01416 }
01417 return WRONG;
01418 }
01419 label:
01420 newt = t + saved_seconds;
01421 if ((newt < t) != (saved_seconds < 0))
01422 return WRONG;
01423 t = newt;
01424 (*funcp)(&t, offset, tmp, zone);
01425 *okayp = TRUE;
01426 return t;
01427 }
01428
01429 static time_t
01430 time1(tmp, funcp, offset, zone)
01431 struct tm * const tmp;
01432 void (* const funcp) P((const time_t *, long, struct tm *, const char*));
01433 const long offset;
01434 const char * const zone;
01435 {
01436 register time_t t;
01437 register const struct state * sp;
01438 register int samei, otheri;
01439 int okay;
01440
01441 if (tmp->tm_isdst > 1)
01442 tmp->tm_isdst = 1;
01443 t = time2(tmp, funcp, offset, &okay, zone);
01444 #ifdef PCTS
01445
01446
01447
01448 if (okay)
01449 return t;
01450 if (tmp->tm_isdst < 0)
01451 tmp->tm_isdst = 0;
01452 #endif
01453 #ifndef PCTS
01454 if (okay || tmp->tm_isdst < 0)
01455 return t;
01456 #endif
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466 sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
01467 lclptr : gmtptr);
01468 if (sp == NULL)
01469 return WRONG;
01470 for (samei = sp->typecnt - 1; samei >= 0; --samei) {
01471 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
01472 continue;
01473 for (otheri = sp->typecnt - 1; otheri >= 0; --otheri) {
01474 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
01475 continue;
01476 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
01477 sp->ttis[samei].tt_gmtoff;
01478 tmp->tm_isdst = !tmp->tm_isdst;
01479 t = time2(tmp, funcp, offset, &okay, zone);
01480 if (okay)
01481 return t;
01482 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
01483 sp->ttis[samei].tt_gmtoff;
01484 tmp->tm_isdst = !tmp->tm_isdst;
01485 }
01486 }
01487 return WRONG;
01488 }
01489
01490 time_t
01491 ast_mktime(tmp,zone)
01492 struct tm * const tmp;
01493 const char * const zone;
01494 {
01495 time_t mktime_return_value;
01496 #ifdef _THREAD_SAFE
01497 ast_mutex_lock(&lcl_mutex);
01498 #endif
01499 ast_tzset(!ast_strlen_zero(zone) ? zone : "/etc/localtime");
01500 mktime_return_value = time1(tmp, localsub, 0L, !ast_strlen_zero(zone) ? zone : "/etc/localtime");
01501 #ifdef _THREAD_SAFE
01502 ast_mutex_unlock(&lcl_mutex);
01503 #endif
01504 return(mktime_return_value);
01505 }
01506