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
00041
00042
00043
00044
00045
00046
00047 #include "asterisk.h"
00048
00049 #include <sys/types.h>
00050 #include <sys/stat.h>
00051 #include <fcntl.h>
00052 #ifdef DEBUG
00053 #include <stdio.h>
00054 #endif
00055 #include <float.h>
00056
00057
00058 #include "private.h"
00059 #include "tzfile.h"
00060
00061 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 144924 $")
00062
00063 #include "asterisk/lock.h"
00064 #include "asterisk/localtime.h"
00065 #include "asterisk/strings.h"
00066 #include "asterisk/linkedlists.h"
00067 #include "asterisk/utils.h"
00068
00069 #ifndef lint
00070 #ifndef NOID
00071 static char __attribute__((unused)) elsieid[] = "@(#)localtime.c 8.5";
00072 #endif
00073 #endif
00074
00075 #ifndef TZ_ABBR_MAX_LEN
00076 #define TZ_ABBR_MAX_LEN 16
00077 #endif
00078
00079 #ifndef TZ_ABBR_CHAR_SET
00080 #define TZ_ABBR_CHAR_SET \
00081 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
00082 #endif
00083
00084 #ifndef TZ_ABBR_ERR_CHAR
00085 #define TZ_ABBR_ERR_CHAR '_'
00086 #endif
00087
00088
00089
00090
00091
00092 #ifdef O_BINARY
00093 #define OPEN_MODE (O_RDONLY | O_BINARY)
00094 #endif
00095 #ifndef O_BINARY
00096 #define OPEN_MODE O_RDONLY
00097 #endif
00098
00099 static const char gmt[] = "GMT";
00100
00101
00102
00103
00104
00105
00106
00107
00108 #ifndef TZDEFRULESTRING
00109 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
00110 #endif
00111
00112 #ifndef WRONG
00113 #define WRONG (-1)
00114 #endif
00115
00116
00117 struct ttinfo {
00118 long tt_gmtoff;
00119 int tt_isdst;
00120 int tt_abbrind;
00121 int tt_ttisstd;
00122 int tt_ttisgmt;
00123 };
00124
00125
00126 struct lsinfo {
00127 time_t ls_trans;
00128 long ls_corr;
00129 };
00130
00131 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
00132
00133 #ifdef TZNAME_MAX
00134 #define MY_TZNAME_MAX TZNAME_MAX
00135 #endif
00136 #ifndef TZNAME_MAX
00137 #define MY_TZNAME_MAX 255
00138 #endif
00139 #ifndef TZ_STRLEN_MAX
00140 #define TZ_STRLEN_MAX 255
00141 #endif
00142
00143 struct state {
00144
00145 char name[TZ_STRLEN_MAX + 1];
00146 int leapcnt;
00147 int timecnt;
00148 int typecnt;
00149 int charcnt;
00150 int goback;
00151 int goahead;
00152 time_t ats[TZ_MAX_TIMES];
00153 unsigned char types[TZ_MAX_TIMES];
00154 struct ttinfo ttis[TZ_MAX_TYPES];
00155 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
00156 (2 * (MY_TZNAME_MAX + 1)))];
00157 struct lsinfo lsis[TZ_MAX_LEAPS];
00158 AST_LIST_ENTRY(state) list;
00159 };
00160
00161 struct rule {
00162 int r_type;
00163 int r_day;
00164 int r_week;
00165 int r_mon;
00166 long r_time;
00167 };
00168
00169 #define JULIAN_DAY 0
00170 #define DAY_OF_YEAR 1
00171 #define MONTH_NTH_DAY_OF_WEEK 2
00172
00173
00174
00175
00176
00177 static long detzcode P((const char * codep));
00178 static time_t detzcode64 P((const char * codep));
00179 static int differ_by_repeat P((time_t t1, time_t t0));
00180 static const char * getzname P((const char * strp));
00181 static const char * getqzname P((const char * strp, const int delim));
00182 static const char * getnum P((const char * strp, int * nump, int min,
00183 int max));
00184 static const char * getsecs P((const char * strp, long * secsp));
00185 static const char * getoffset P((const char * strp, long * offsetp));
00186 static const char * getrule P((const char * strp, struct rule * rulep));
00187 static int gmtload P((struct state * sp));
00188 static struct tm * gmtsub P((const time_t * timep, long offset,
00189 struct tm * tmp));
00190 static struct tm * localsub P((const time_t * timep, long offset,
00191 struct tm * tmp, const struct state *sp));
00192 static int increment_overflow P((int * number, int delta));
00193 static int leaps_thru_end_of P((int y));
00194 static int long_increment_overflow P((long * number, int delta));
00195 static int long_normalize_overflow P((long * tensptr,
00196 int * unitsptr, const int base));
00197 static int normalize_overflow P((int * tensptr, int * unitsptr,
00198 const int base));
00199 static time_t time1 P((struct tm * tmp,
00200 struct tm * (*funcp) P((const time_t *,
00201 long, struct tm *, const struct state *sp)),
00202 long offset, const struct state *sp));
00203 static time_t time2 P((struct tm *tmp,
00204 struct tm * (*funcp) P((const time_t *,
00205 long, struct tm*, const struct state *sp)),
00206 long offset, int * okayp, const struct state *sp));
00207 static time_t time2sub P((struct tm *tmp,
00208 struct tm * (*funcp) (const time_t *,
00209 long, struct tm*, const struct state *sp),
00210 long offset, int * okayp, int do_norm_secs, const struct state *sp));
00211 static struct tm * timesub P((const time_t * timep, long offset,
00212 const struct state * sp, struct tm * tmp));
00213 static int tmcomp P((const struct tm * atmp,
00214 const struct tm * btmp));
00215 static time_t transtime P((time_t janfirst, int year,
00216 const struct rule * rulep, long offset));
00217 static int tzload P((const char * name, struct state * sp,
00218 int doextend));
00219 static int tzparse P((const char * name, struct state * sp,
00220 int lastditch));
00221
00222 static AST_LIST_HEAD_STATIC(zonelist, state);
00223
00224 #ifndef TZ_STRLEN_MAX
00225 #define TZ_STRLEN_MAX 255
00226 #endif
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 static long detzcode(const char * const codep)
00237 {
00238 long result;
00239 int i;
00240
00241 result = (codep[0] & 0x80) ? ~0L : 0;
00242 for (i = 0; i < 4; ++i)
00243 result = (result << 8) | (codep[i] & 0xff);
00244 return result;
00245 }
00246
00247 static time_t detzcode64(const char * const codep)
00248 {
00249 time_t result;
00250 int i;
00251
00252 result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
00253 for (i = 0; i < 8; ++i)
00254 result = result * 256 + (codep[i] & 0xff);
00255 return result;
00256 }
00257
00258 static int differ_by_repeat(const time_t t1, const time_t t0)
00259 {
00260 const long long at1 = t1, at0 = t0;
00261 if (TYPE_INTEGRAL(time_t) &&
00262 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
00263 return 0;
00264 return at1 - at0 == SECSPERREPEAT;
00265 }
00266
00267 static int tzload(const char *name, struct state * const sp, const int doextend)
00268 {
00269 const char * p;
00270 int i;
00271 int fid;
00272 int stored;
00273 int nread;
00274 union {
00275 struct tzhead tzhead;
00276 char buf[2 * sizeof(struct tzhead) +
00277 2 * sizeof *sp +
00278 4 * TZ_MAX_TIMES];
00279 } u;
00280
00281 if (name == NULL && (name = TZDEFAULT) == NULL)
00282 return WRONG;
00283 {
00284 int doaccess;
00285
00286
00287
00288
00289
00290
00291
00292 char fullname[FILENAME_MAX + 1];
00293
00294 if (name[0] == ':')
00295 ++name;
00296 doaccess = name[0] == '/';
00297 if (!doaccess) {
00298 if ((p = TZDIR) == NULL)
00299 return WRONG;
00300 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
00301 return WRONG;
00302 (void) strcpy(fullname, p);
00303 (void) strcat(fullname, "/");
00304 (void) strcat(fullname, name);
00305
00306
00307
00308 if (strchr(name, '.') != NULL)
00309 doaccess = TRUE;
00310 name = fullname;
00311 }
00312 if (doaccess && access(name, R_OK) != 0)
00313 return WRONG;
00314 if ((fid = open(name, OPEN_MODE)) == -1)
00315 return WRONG;
00316 }
00317 nread = read(fid, u.buf, sizeof u.buf);
00318 if (close(fid) < 0 || nread <= 0)
00319 return WRONG;
00320 for (stored = 4; stored <= 8; stored *= 2) {
00321 int ttisstdcnt;
00322 int ttisgmtcnt;
00323
00324 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
00325 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
00326 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
00327 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
00328 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
00329 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
00330 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
00331 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
00332 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
00333 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
00334 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
00335 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
00336 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
00337 return WRONG;
00338 if (nread - (p - u.buf) <
00339 sp->timecnt * stored +
00340 sp->timecnt +
00341 sp->typecnt * 6 +
00342 sp->charcnt +
00343 sp->leapcnt * (stored + 4) +
00344 ttisstdcnt +
00345 ttisgmtcnt)
00346 return WRONG;
00347 for (i = 0; i < sp->timecnt; ++i) {
00348 sp->ats[i] = (stored == 4) ?
00349 detzcode(p) : detzcode64(p);
00350 p += stored;
00351 }
00352 for (i = 0; i < sp->timecnt; ++i) {
00353 sp->types[i] = (unsigned char) *p++;
00354 if (sp->types[i] >= sp->typecnt)
00355 return WRONG;
00356 }
00357 for (i = 0; i < sp->typecnt; ++i) {
00358 struct ttinfo * ttisp;
00359
00360 ttisp = &sp->ttis[i];
00361 ttisp->tt_gmtoff = detzcode(p);
00362 p += 4;
00363 ttisp->tt_isdst = (unsigned char) *p++;
00364 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
00365 return WRONG;
00366 ttisp->tt_abbrind = (unsigned char) *p++;
00367 if (ttisp->tt_abbrind < 0 ||
00368 ttisp->tt_abbrind > sp->charcnt)
00369 return WRONG;
00370 }
00371 for (i = 0; i < sp->charcnt; ++i)
00372 sp->chars[i] = *p++;
00373 sp->chars[i] = '\0';
00374 for (i = 0; i < sp->leapcnt; ++i) {
00375 struct lsinfo * lsisp;
00376
00377 lsisp = &sp->lsis[i];
00378 lsisp->ls_trans = (stored == 4) ?
00379 detzcode(p) : detzcode64(p);
00380 p += stored;
00381 lsisp->ls_corr = detzcode(p);
00382 p += 4;
00383 }
00384 for (i = 0; i < sp->typecnt; ++i) {
00385 struct ttinfo * ttisp;
00386
00387 ttisp = &sp->ttis[i];
00388 if (ttisstdcnt == 0)
00389 ttisp->tt_ttisstd = FALSE;
00390 else {
00391 ttisp->tt_ttisstd = *p++;
00392 if (ttisp->tt_ttisstd != TRUE &&
00393 ttisp->tt_ttisstd != FALSE)
00394 return WRONG;
00395 }
00396 }
00397 for (i = 0; i < sp->typecnt; ++i) {
00398 struct ttinfo * ttisp;
00399
00400 ttisp = &sp->ttis[i];
00401 if (ttisgmtcnt == 0)
00402 ttisp->tt_ttisgmt = FALSE;
00403 else {
00404 ttisp->tt_ttisgmt = *p++;
00405 if (ttisp->tt_ttisgmt != TRUE &&
00406 ttisp->tt_ttisgmt != FALSE)
00407 return WRONG;
00408 }
00409 }
00410
00411
00412
00413
00414
00415 for (i = 0; i < sp->timecnt - 2; ++i)
00416 if (sp->ats[i] > sp->ats[i + 1]) {
00417 ++i;
00418 if (TYPE_SIGNED(time_t)) {
00419
00420
00421
00422 sp->timecnt = i;
00423 } else {
00424
00425
00426
00427 int j;
00428
00429 for (j = 0; j + i < sp->timecnt; ++j) {
00430 sp->ats[j] = sp->ats[j + i];
00431 sp->types[j] = sp->types[j + i];
00432 }
00433 sp->timecnt = j;
00434 }
00435 break;
00436 }
00437
00438
00439
00440 if (u.tzhead.tzh_version[0] == '\0')
00441 break;
00442 nread -= p - u.buf;
00443 for (i = 0; i < nread; ++i)
00444 u.buf[i] = p[i];
00445
00446
00447
00448 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
00449 break;
00450 }
00451 if (doextend && nread > 2 &&
00452 u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
00453 sp->typecnt + 2 <= TZ_MAX_TYPES) {
00454 struct state ts;
00455 int result;
00456
00457 u.buf[nread - 1] = '\0';
00458 result = tzparse(&u.buf[1], &ts, FALSE);
00459 if (result == 0 && ts.typecnt == 2 &&
00460 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
00461 for (i = 0; i < 2; ++i)
00462 ts.ttis[i].tt_abbrind +=
00463 sp->charcnt;
00464 for (i = 0; i < ts.charcnt; ++i)
00465 sp->chars[sp->charcnt++] =
00466 ts.chars[i];
00467 i = 0;
00468 while (i < ts.timecnt &&
00469 ts.ats[i] <=
00470 sp->ats[sp->timecnt - 1])
00471 ++i;
00472 while (i < ts.timecnt &&
00473 sp->timecnt < TZ_MAX_TIMES) {
00474 sp->ats[sp->timecnt] =
00475 ts.ats[i];
00476 sp->types[sp->timecnt] =
00477 sp->typecnt +
00478 ts.types[i];
00479 ++sp->timecnt;
00480 ++i;
00481 }
00482 sp->ttis[sp->typecnt++] = ts.ttis[0];
00483 sp->ttis[sp->typecnt++] = ts.ttis[1];
00484 }
00485 }
00486 i = 2 * YEARSPERREPEAT;
00487 sp->goback = sp->goahead = sp->timecnt > i;
00488 sp->goback = sp->goback && sp->types[i] == sp->types[0] &&
00489 differ_by_repeat(sp->ats[i], sp->ats[0]);
00490 sp->goahead = sp->goahead &&
00491 sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
00492 differ_by_repeat(sp->ats[sp->timecnt - 1],
00493 sp->ats[sp->timecnt - 1 - i]);
00494 return 0;
00495 }
00496
00497 static const int mon_lengths[2][MONSPERYEAR] = {
00498 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
00499 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
00500 };
00501
00502 static const int year_lengths[2] = {
00503 DAYSPERNYEAR, DAYSPERLYEAR
00504 };
00505
00506
00507
00508
00509
00510
00511
00512 static const char * getzname(const char *strp)
00513 {
00514 char c;
00515
00516 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
00517 c != '+')
00518 ++strp;
00519 return strp;
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 static const char * getqzname(const char *strp, const int delim)
00532 {
00533 int c;
00534
00535 while ((c = *strp) != '\0' && c != delim)
00536 ++strp;
00537 return strp;
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547 static const char *getnum(const char *strp, int *nump, const int min, const int max)
00548 {
00549 char c;
00550 int num;
00551
00552 if (strp == NULL || !is_digit(c = *strp))
00553 return NULL;
00554 num = 0;
00555 do {
00556 num = num * 10 + (c - '0');
00557 if (num > max)
00558 return NULL;
00559 c = *++strp;
00560 } while (is_digit(c));
00561 if (num < min)
00562 return NULL;
00563 *nump = num;
00564 return strp;
00565 }
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 static const char *getsecs(const char *strp, long * const secsp)
00576 {
00577 int num;
00578
00579
00580
00581
00582
00583
00584
00585 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
00586 if (strp == NULL)
00587 return NULL;
00588 *secsp = num * (long) SECSPERHOUR;
00589 if (*strp == ':') {
00590 ++strp;
00591 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
00592 if (strp == NULL)
00593 return NULL;
00594 *secsp += num * SECSPERMIN;
00595 if (*strp == ':') {
00596 ++strp;
00597
00598 strp = getnum(strp, &num, 0, SECSPERMIN);
00599 if (strp == NULL)
00600 return NULL;
00601 *secsp += num;
00602 }
00603 }
00604 return strp;
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614 static const char *getoffset(const char *strp, long *offsetp)
00615 {
00616 int neg = 0;
00617
00618 if (*strp == '-') {
00619 neg = 1;
00620 ++strp;
00621 } else if (*strp == '+')
00622 ++strp;
00623 strp = getsecs(strp, offsetp);
00624 if (strp == NULL)
00625 return NULL;
00626 if (neg)
00627 *offsetp = -*offsetp;
00628 return strp;
00629 }
00630
00631
00632
00633
00634
00635
00636
00637
00638 static const char *getrule(const char *strp, struct rule *rulep)
00639 {
00640 if (*strp == 'J') {
00641
00642
00643
00644 rulep->r_type = JULIAN_DAY;
00645 ++strp;
00646 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
00647 } else if (*strp == 'M') {
00648
00649
00650
00651 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
00652 ++strp;
00653 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
00654 if (strp == NULL)
00655 return NULL;
00656 if (*strp++ != '.')
00657 return NULL;
00658 strp = getnum(strp, &rulep->r_week, 1, 5);
00659 if (strp == NULL)
00660 return NULL;
00661 if (*strp++ != '.')
00662 return NULL;
00663 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
00664 } else if (is_digit(*strp)) {
00665
00666
00667
00668 rulep->r_type = DAY_OF_YEAR;
00669 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
00670 } else return NULL;
00671 if (strp == NULL)
00672 return NULL;
00673 if (*strp == '/') {
00674
00675
00676
00677 ++strp;
00678 strp = getsecs(strp, &rulep->r_time);
00679 } else rulep->r_time = 2 * SECSPERHOUR;
00680 return strp;
00681 }
00682
00683
00684
00685
00686
00687
00688
00689 static time_t transtime(const time_t janfirst, const int year, const struct rule *rulep, const long offset)
00690 {
00691 int leapyear;
00692 time_t value;
00693 int i;
00694 int d, m1, yy0, yy1, yy2, dow;
00695
00696 INITIALIZE(value);
00697 leapyear = isleap(year);
00698 switch (rulep->r_type) {
00699
00700 case JULIAN_DAY:
00701
00702
00703
00704
00705
00706
00707
00708 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
00709 if (leapyear && rulep->r_day >= 60)
00710 value += SECSPERDAY;
00711 break;
00712
00713 case DAY_OF_YEAR:
00714
00715
00716
00717
00718
00719 value = janfirst + rulep->r_day * SECSPERDAY;
00720 break;
00721
00722 case MONTH_NTH_DAY_OF_WEEK:
00723
00724
00725
00726 value = janfirst;
00727 for (i = 0; i < rulep->r_mon - 1; ++i)
00728 value += mon_lengths[leapyear][i] * SECSPERDAY;
00729
00730
00731
00732
00733
00734 m1 = (rulep->r_mon + 9) % 12 + 1;
00735 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
00736 yy1 = yy0 / 100;
00737 yy2 = yy0 % 100;
00738 dow = ((26 * m1 - 2) / 10 +
00739 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
00740 if (dow < 0)
00741 dow += DAYSPERWEEK;
00742
00743
00744
00745
00746
00747
00748 d = rulep->r_day - dow;
00749 if (d < 0)
00750 d += DAYSPERWEEK;
00751 for (i = 1; i < rulep->r_week; ++i) {
00752 if (d + DAYSPERWEEK >=
00753 mon_lengths[leapyear][rulep->r_mon - 1])
00754 break;
00755 d += DAYSPERWEEK;
00756 }
00757
00758
00759
00760
00761 value += d * SECSPERDAY;
00762 break;
00763 }
00764
00765
00766
00767
00768
00769
00770
00771 return value + rulep->r_time + offset;
00772 }
00773
00774
00775
00776
00777
00778
00779 static int tzparse(const char *name, struct state *sp, const int lastditch)
00780 {
00781 const char * stdname;
00782 const char * dstname;
00783 size_t stdlen;
00784 size_t dstlen;
00785 long stdoffset;
00786 long dstoffset;
00787 time_t * atp;
00788 unsigned char * typep;
00789 char * cp;
00790 int load_result;
00791
00792 INITIALIZE(dstname);
00793 stdname = name;
00794 if (lastditch) {
00795 stdlen = strlen(name);
00796 name += stdlen;
00797 if (stdlen >= sizeof sp->chars)
00798 stdlen = (sizeof sp->chars) - 1;
00799 stdoffset = 0;
00800 } else {
00801 if (*name == '<') {
00802 name++;
00803 stdname = name;
00804 name = getqzname(name, '>');
00805 if (*name != '>')
00806 return WRONG;
00807 stdlen = name - stdname;
00808 name++;
00809 } else {
00810 name = getzname(name);
00811 stdlen = name - stdname;
00812 }
00813 if (*name == '\0')
00814 return WRONG;
00815 name = getoffset(name, &stdoffset);
00816 if (name == NULL)
00817 return WRONG;
00818 }
00819 load_result = tzload(TZDEFRULES, sp, FALSE);
00820 if (load_result != 0)
00821 sp->leapcnt = 0;
00822 if (*name != '\0') {
00823 if (*name == '<') {
00824 dstname = ++name;
00825 name = getqzname(name, '>');
00826 if (*name != '>')
00827 return WRONG;
00828 dstlen = name - dstname;
00829 name++;
00830 } else {
00831 dstname = name;
00832 name = getzname(name);
00833 dstlen = name - dstname;
00834 }
00835 if (*name != '\0' && *name != ',' && *name != ';') {
00836 name = getoffset(name, &dstoffset);
00837 if (name == NULL)
00838 return WRONG;
00839 } else dstoffset = stdoffset - SECSPERHOUR;
00840 if (*name == '\0' && load_result != 0)
00841 name = TZDEFRULESTRING;
00842 if (*name == ',' || *name == ';') {
00843 struct rule start;
00844 struct rule end;
00845 int year;
00846 time_t janfirst;
00847 time_t starttime;
00848 time_t endtime;
00849
00850 ++name;
00851 if ((name = getrule(name, &start)) == NULL)
00852 return WRONG;
00853 if (*name++ != ',')
00854 return WRONG;
00855 if ((name = getrule(name, &end)) == NULL)
00856 return WRONG;
00857 if (*name != '\0')
00858 return WRONG;
00859 sp->typecnt = 2;
00860
00861
00862
00863 sp->ttis[0].tt_gmtoff = -dstoffset;
00864 sp->ttis[0].tt_isdst = 1;
00865 sp->ttis[0].tt_abbrind = stdlen + 1;
00866 sp->ttis[1].tt_gmtoff = -stdoffset;
00867 sp->ttis[1].tt_isdst = 0;
00868 sp->ttis[1].tt_abbrind = 0;
00869 atp = sp->ats;
00870 typep = sp->types;
00871 janfirst = 0;
00872 sp->timecnt = 0;
00873 for (year = EPOCH_YEAR;
00874 sp->timecnt + 2 <= TZ_MAX_TIMES;
00875 ++year) {
00876 time_t newfirst;
00877
00878 starttime = transtime(janfirst, year, &start,
00879 stdoffset);
00880 endtime = transtime(janfirst, year, &end,
00881 dstoffset);
00882 if (starttime > endtime) {
00883 *atp++ = endtime;
00884 *typep++ = 1;
00885 *atp++ = starttime;
00886 *typep++ = 0;
00887 } else {
00888 *atp++ = starttime;
00889 *typep++ = 0;
00890 *atp++ = endtime;
00891 *typep++ = 1;
00892 }
00893 sp->timecnt += 2;
00894 newfirst = janfirst;
00895 newfirst += year_lengths[isleap(year)] *
00896 SECSPERDAY;
00897 if (newfirst <= janfirst)
00898 break;
00899 janfirst = newfirst;
00900 }
00901 } else {
00902 long theirstdoffset;
00903 long theirdstoffset;
00904 long theiroffset;
00905 int isdst;
00906 int i;
00907 int j;
00908
00909 if (*name != '\0')
00910 return WRONG;
00911
00912
00913
00914 theirstdoffset = 0;
00915 for (i = 0; i < sp->timecnt; ++i) {
00916 j = sp->types[i];
00917 if (!sp->ttis[j].tt_isdst) {
00918 theirstdoffset =
00919 -sp->ttis[j].tt_gmtoff;
00920 break;
00921 }
00922 }
00923 theirdstoffset = 0;
00924 for (i = 0; i < sp->timecnt; ++i) {
00925 j = sp->types[i];
00926 if (sp->ttis[j].tt_isdst) {
00927 theirdstoffset =
00928 -sp->ttis[j].tt_gmtoff;
00929 break;
00930 }
00931 }
00932
00933
00934
00935 isdst = FALSE;
00936 theiroffset = theirstdoffset;
00937
00938
00939
00940
00941 for (i = 0; i < sp->timecnt; ++i) {
00942 j = sp->types[i];
00943 sp->types[i] = sp->ttis[j].tt_isdst;
00944 if (sp->ttis[j].tt_ttisgmt) {
00945
00946 } else {
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961 if (isdst && !sp->ttis[j].tt_ttisstd) {
00962 sp->ats[i] += dstoffset -
00963 theirdstoffset;
00964 } else {
00965 sp->ats[i] += stdoffset -
00966 theirstdoffset;
00967 }
00968 }
00969 theiroffset = -sp->ttis[j].tt_gmtoff;
00970 if (sp->ttis[j].tt_isdst)
00971 theirdstoffset = theiroffset;
00972 else theirstdoffset = theiroffset;
00973 }
00974
00975
00976
00977
00978 sp->ttis[0].tt_gmtoff = -stdoffset;
00979 sp->ttis[0].tt_isdst = FALSE;
00980 sp->ttis[0].tt_abbrind = 0;
00981 sp->ttis[1].tt_gmtoff = -dstoffset;
00982 sp->ttis[1].tt_isdst = TRUE;
00983 sp->ttis[1].tt_abbrind = stdlen + 1;
00984 sp->typecnt = 2;
00985 }
00986 } else {
00987 dstlen = 0;
00988 sp->typecnt = 1;
00989 sp->timecnt = 0;
00990 sp->ttis[0].tt_gmtoff = -stdoffset;
00991 sp->ttis[0].tt_isdst = 0;
00992 sp->ttis[0].tt_abbrind = 0;
00993 }
00994 sp->charcnt = stdlen + 1;
00995 if (dstlen != 0)
00996 sp->charcnt += dstlen + 1;
00997 if ((size_t) sp->charcnt > sizeof sp->chars)
00998 return WRONG;
00999 cp = sp->chars;
01000 (void) strncpy(cp, stdname, stdlen);
01001 cp += stdlen;
01002 *cp++ = '\0';
01003 if (dstlen != 0) {
01004 (void) strncpy(cp, dstname, dstlen);
01005 *(cp + dstlen) = '\0';
01006 }
01007 return 0;
01008 }
01009
01010 static int gmtload(struct state *sp)
01011 {
01012 if (tzload(gmt, sp, TRUE) != 0)
01013 return tzparse(gmt, sp, TRUE);
01014 else
01015 return WRONG;
01016 }
01017
01018 static const struct state *ast_tzset(const char *zone)
01019 {
01020 struct state *sp;
01021
01022 if (ast_strlen_zero(zone))
01023 zone = "/etc/localtime";
01024
01025 AST_LIST_LOCK(&zonelist);
01026 AST_LIST_TRAVERSE(&zonelist, sp, list) {
01027 if (!strcmp(sp->name, zone)) {
01028 AST_LIST_UNLOCK(&zonelist);
01029 return sp;
01030 }
01031 }
01032 AST_LIST_UNLOCK(&zonelist);
01033
01034 if (!(sp = ast_calloc(1, sizeof *sp)))
01035 return NULL;
01036
01037 if (tzload(zone, sp, TRUE) != 0) {
01038 if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0)
01039 (void) gmtload(sp);
01040 }
01041 ast_copy_string(sp->name, zone, sizeof(sp->name));
01042 AST_LIST_LOCK(&zonelist);
01043 AST_LIST_INSERT_TAIL(&zonelist, sp, list);
01044 AST_LIST_UNLOCK(&zonelist);
01045 return sp;
01046 }
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057 static struct tm *localsub(const time_t *timep, const long offset, struct tm *tmp, const struct state *sp)
01058 {
01059 const struct ttinfo * ttisp;
01060 int i;
01061 struct tm * result;
01062 const time_t t = *timep;
01063
01064 if (sp == NULL)
01065 return gmtsub(timep, offset, tmp);
01066 if ((sp->goback && t < sp->ats[0]) ||
01067 (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
01068 time_t newt = t;
01069 time_t seconds;
01070 time_t tcycles;
01071 int_fast64_t icycles;
01072
01073 if (t < sp->ats[0])
01074 seconds = sp->ats[0] - t;
01075 else seconds = t - sp->ats[sp->timecnt - 1];
01076 --seconds;
01077 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
01078 ++tcycles;
01079 icycles = tcycles;
01080 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
01081 return NULL;
01082 seconds = icycles;
01083 seconds *= YEARSPERREPEAT;
01084 seconds *= AVGSECSPERYEAR;
01085 if (t < sp->ats[0])
01086 newt += seconds;
01087 else newt -= seconds;
01088 if (newt < sp->ats[0] ||
01089 newt > sp->ats[sp->timecnt - 1])
01090 return NULL;
01091 result = localsub(&newt, offset, tmp, sp);
01092 if (result == tmp) {
01093 time_t newy;
01094
01095 newy = tmp->tm_year;
01096 if (t < sp->ats[0])
01097 newy -= icycles * YEARSPERREPEAT;
01098 else
01099 newy += icycles * YEARSPERREPEAT;
01100 tmp->tm_year = newy;
01101 if (tmp->tm_year != newy)
01102 return NULL;
01103 }
01104 return result;
01105 }
0110