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