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: 103845 $")
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 #ifndef SOLARIS
01137 tmp->tm_gmtoff = ttisp->tt_gmtoff;
01138 #endif
01139 #ifdef TM_ZONE
01140 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
01141 #endif
01142 return result;
01143 }
01144
01145 struct tm *ast_localtime(const time_t *timep, struct tm *tmp, const char *zone)
01146 {
01147 const struct state *sp = ast_tzset(zone);
01148 memset(tmp, 0, sizeof(*tmp));
01149 return sp ? localsub(timep, 0L, tmp, sp) : NULL;
01150 }
01151
01152
01153
01154
01155
01156 static struct tm *gmtsub(const time_t *timep, const long offset, struct tm *tmp)
01157 {
01158 struct tm * result;
01159 struct state *sp;
01160
01161 AST_LIST_LOCK(&zonelist);
01162 AST_LIST_TRAVERSE(&zonelist, sp, list) {
01163 if (!strcmp(sp->name, "UTC"))
01164 break;
01165 }
01166
01167 if (!sp) {
01168 if (!(sp = (struct state *) ast_calloc(1, sizeof *sp)))
01169 return NULL;
01170 gmtload(sp);
01171 AST_LIST_INSERT_TAIL(&zonelist, sp, list);
01172 }
01173 AST_LIST_UNLOCK(&zonelist);
01174
01175 result = timesub(timep, offset, sp, tmp);
01176 #ifdef TM_ZONE
01177
01178
01179
01180
01181
01182 if (offset != 0)
01183 tmp->TM_ZONE = " ";
01184 else
01185 tmp->TM_ZONE = sp->chars;
01186 #endif
01187 return result;
01188 }
01189
01190
01191
01192
01193
01194
01195 static int leaps_thru_end_of(const int y)
01196 {
01197 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
01198 -(leaps_thru_end_of(-(y + 1)) + 1);
01199 }
01200
01201 static struct tm *timesub(const time_t *timep, const long offset, const struct state *sp, struct tm *tmp)
01202 {
01203 const struct lsinfo * lp;
01204 time_t tdays;
01205 int idays;
01206 long rem;
01207 int y;
01208 const int * ip;
01209 long corr;
01210 int hit;
01211 int i;
01212 long seconds;
01213
01214
01215 corr = 0;
01216 hit = 0;
01217 i = (sp == NULL) ? 0 : sp->leapcnt;
01218 while (--i >= 0) {
01219 lp = &sp->lsis[i];
01220 if (*timep >= lp->ls_trans) {
01221 if (*timep == lp->ls_trans) {
01222 hit = ((i == 0 && lp->ls_corr > 0) ||
01223 lp->ls_corr > sp->lsis[i - 1].ls_corr);
01224 if (hit)
01225 while (i > 0 &&
01226 sp->lsis[i].ls_trans ==
01227 sp->lsis[i - 1].ls_trans + 1 &&
01228 sp->lsis[i].ls_corr ==
01229 sp->lsis[i - 1].ls_corr + 1) {
01230 ++hit;
01231 --i;
01232 }
01233 }
01234 corr = lp->ls_corr;
01235 break;
01236 }
01237 }
01238 y = EPOCH_YEAR;
01239 tdays = *timep / SECSPERDAY;
01240 rem = *timep - tdays * SECSPERDAY;
01241 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
01242 int newy;
01243 time_t tdelta;
01244 int idelta;
01245 int leapdays;
01246
01247 tdelta = tdays / DAYSPERLYEAR;
01248 idelta = tdelta;
01249 if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
01250 return NULL;
01251 if (idelta == 0)
01252 idelta = (tdays < 0) ? -1 : 1;
01253 newy = y;
01254 if (increment_overflow(&newy, idelta))
01255 return NULL;
01256 leapdays = leaps_thru_end_of(newy - 1) -
01257 leaps_thru_end_of(y - 1);
01258 tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
01259 tdays -= leapdays;
01260 y = newy;
01261 }
01262
01263 seconds = tdays * SECSPERDAY + 0.5;
01264 tdays = seconds / SECSPERDAY;
01265 rem += seconds - tdays * SECSPERDAY;
01266
01267
01268
01269
01270 idays = tdays;
01271 rem += offset - corr;
01272 while (rem < 0) {
01273 rem += SECSPERDAY;
01274 --idays;
01275 }
01276 while (rem >= SECSPERDAY) {
01277 rem -= SECSPERDAY;
01278 ++idays;
01279 }
01280 while (idays < 0) {
01281 if (increment_overflow(&y, -1))
01282 return NULL;
01283 idays += year_lengths[isleap(y)];
01284 }
01285 while (idays >= year_lengths[isleap(y)]) {
01286 idays -= year_lengths[isleap(y)];
01287 if (increment_overflow(&y, 1))
01288 return NULL;
01289 }
01290 tmp->tm_year = y;
01291 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
01292 return NULL;
01293 tmp->tm_yday = idays;
01294
01295
01296
01297 tmp->tm_wday = EPOCH_WDAY +
01298 ((y - EPOCH_YEAR) % DAYSPERWEEK) *
01299 (DAYSPERNYEAR % DAYSPERWEEK) +
01300 leaps_thru_end_of(y - 1) -
01301 leaps_thru_end_of(EPOCH_YEAR - 1) +
01302 idays;
01303 tmp->tm_wday %= DAYSPERWEEK;
01304 if (tmp->tm_wday < 0)
01305 tmp->tm_wday += DAYSPERWEEK;
01306 tmp->tm_hour = (int) (rem / SECSPERHOUR);
01307 rem %= SECSPERHOUR;
01308 tmp->tm_min = (int) (rem / SECSPERMIN);
01309
01310
01311
01312
01313 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
01314 ip = mon_lengths[isleap(y)];
01315 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
01316 idays -= ip[tmp->tm_mon];
01317 tmp->tm_mday = (int) (idays + 1);
01318 tmp->tm_isdst = 0;
01319 #ifdef TM_GMTOFF
01320 tmp->TM_GMTOFF = offset;
01321 #endif
01322 return tmp;
01323 }
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338 static int increment_overflow(int *number, int delta)
01339 {
01340 int number0;
01341
01342 number0 = *number;
01343 *number += delta;
01344 return (*number < number0) != (delta < 0);
01345 }
01346
01347 static int long_increment_overflow(long *number, int delta)
01348 {
01349 long number0;
01350
01351 number0 = *number;
01352 *number += delta;
01353 return (*number < number0) != (delta < 0);
01354 }
01355
01356 static int normalize_overflow(int *tensptr, int *unitsptr, const int base)
01357 {
01358 int tensdelta;
01359
01360 tensdelta = (*unitsptr >= 0) ?
01361 (*unitsptr / base) :
01362 (-1 - (-1 - *unitsptr) / base);
01363 *unitsptr -= tensdelta * base;
01364 return increment_overflow(tensptr, tensdelta);
01365 }
01366
01367 static int long_normalize_overflow(long *tensptr, int *unitsptr, const int base)
01368 {
01369 int tensdelta;
01370
01371 tensdelta = (*unitsptr >= 0) ?
01372 (*unitsptr / base) :
01373 (-1 - (-1 - *unitsptr) / base);
01374 *unitsptr -= tensdelta * base;
01375 return long_increment_overflow(tensptr, tensdelta);
01376 }
01377
01378 static int tmcomp(const struct tm *atmp, const struct tm *btmp)
01379 {
01380 int result;
01381
01382 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
01383 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
01384 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
01385 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
01386 (result = (atmp->tm_min - btmp->tm_min)) == 0)
01387 result = atmp->tm_sec - btmp->tm_sec;
01388 return result;
01389 }
01390
01391 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)
01392 {
01393 int dir;
01394 int i, j;
01395 int saved_seconds;
01396 long li;
01397 time_t lo;
01398 time_t hi;
01399 long y;
01400 time_t newt;
01401 time_t t;
01402 struct tm yourtm, mytm;
01403
01404 *okayp = FALSE;
01405 yourtm = *tmp;
01406 if (do_norm_secs) {
01407 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
01408 SECSPERMIN))
01409 return WRONG;
01410 }
01411 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
01412 return WRONG;
01413 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
01414 return WRONG;
01415 y = yourtm.tm_year;
01416 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
01417 return WRONG;
01418
01419
01420
01421
01422 if (long_increment_overflow(&y, TM_YEAR_BASE))
01423 return WRONG;
01424 while (yourtm.tm_mday <= 0) {
01425 if (long_increment_overflow(&y, -1))
01426 return WRONG;
01427 li = y + (1 < yourtm.tm_mon);
01428 yourtm.tm_mday += year_lengths[isleap(li)];
01429 }
01430 while (yourtm.tm_mday > DAYSPERLYEAR) {
01431 li = y + (1 < yourtm.tm_mon);
01432 yourtm.tm_mday -= year_lengths[isleap(li)];
01433 if (long_increment_overflow(&y, 1))
01434 return WRONG;
01435 }
01436 for ( ; ; ) {
01437 i = mon_lengths[isleap(y)][yourtm.tm_mon];
01438 if (yourtm.tm_mday <= i)
01439 break;
01440 yourtm.tm_mday -= i;
01441 if (++yourtm.tm_mon >= MONSPERYEAR) {
01442 yourtm.tm_mon = 0;
01443 if (long_increment_overflow(&y, 1))
01444 return WRONG;
01445 }
01446 }
01447 if (long_increment_overflow(&y, -TM_YEAR_BASE))
01448 return WRONG;
01449 yourtm.tm_year = y;
01450 if (yourtm.tm_year != y)
01451 return WRONG;
01452 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
01453 saved_seconds = 0;
01454 else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
01455
01456
01457
01458
01459
01460
01461
01462
01463 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
01464 return WRONG;
01465 saved_seconds = yourtm.tm_sec;
01466 yourtm.tm_sec = SECSPERMIN - 1;
01467 } else {
01468 saved_seconds = yourtm.tm_sec;
01469 yourtm.tm_sec = 0;
01470 }
01471
01472
01473
01474 if (!TYPE_SIGNED(time_t)) {
01475 lo = 0;
01476 hi = lo - 1;
01477 } else if (!TYPE_INTEGRAL(time_t)) {
01478 if (sizeof(time_t) > sizeof(float))
01479 hi = (time_t) DBL_MAX;
01480 else hi = (time_t) FLT_MAX;
01481 lo = -hi;
01482 } else {
01483 lo = 1;
01484 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
01485 lo *= 2;
01486 hi = -(lo + 1);
01487 }
01488 for ( ; ; ) {
01489 t = lo / 2 + hi / 2;
01490 if (t < lo)
01491 t = lo;
01492 else if (t > hi)
01493 t = hi;
01494 if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
01495
01496
01497
01498
01499
01500 dir = (t > 0) ? 1 : -1;
01501 } else dir = tmcomp(&mytm, &yourtm);
01502 if (dir != 0) {
01503 if (t == lo) {
01504 ++t;
01505 if (t <= lo)
01506 return WRONG;
01507 ++lo;
01508 } else if (t == hi) {
01509 --t;
01510 if (t >= hi)
01511 return WRONG;
01512 --hi;
01513 }
01514 if (lo > hi)
01515 return WRONG;
01516 if (dir > 0)
01517 hi = t;
01518 else lo = t;
01519 continue;
01520 }
01521 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
01522 break;
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532 for (i = sp->typecnt - 1; i >= 0; --i) {
01533 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
01534 continue;
01535 for (j = sp->typecnt - 1; j >= 0; --j) {
01536 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
01537 continue;
01538 newt = t + sp->ttis[j].tt_gmtoff -
01539 sp->ttis[i].tt_gmtoff;
01540 if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
01541 continue;
01542 if (tmcomp(&mytm, &yourtm) != 0)
01543 continue;
01544 if (mytm.tm_isdst != yourtm.tm_isdst)
01545 continue;
01546
01547
01548
01549 t = newt;
01550 goto label;
01551 }
01552 }
01553 return WRONG;
01554 }
01555 label:
01556 newt = t + saved_seconds;
01557 if ((newt < t) != (saved_seconds < 0))
01558 return WRONG;
01559 t = newt;
01560 if ((*funcp)(&t, offset, tmp, sp))
01561 *okayp = TRUE;
01562 return t;
01563 }
01564
01565 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)
01566 {
01567 time_t t;
01568
01569
01570
01571
01572
01573
01574 t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
01575 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
01576 }
01577
01578 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)
01579 {
01580 time_t t;
01581 int samei, otheri;
01582 int sameind, otherind;
01583 int i;
01584 int nseen;
01585 int seen[TZ_MAX_TYPES];
01586 int types[TZ_MAX_TYPES];
01587 int okay;
01588
01589 if (tmp->tm_isdst > 1)
01590 tmp->tm_isdst = 1;
01591 t = time2(tmp, funcp, offset, &okay, sp);
01592 #ifdef PCTS
01593
01594
01595
01596 if (okay)
01597 return t;
01598 if (tmp->tm_isdst < 0)
01599 tmp->tm_isdst = 0;
01600 #endif
01601 #ifndef PCTS
01602 if (okay || tmp->tm_isdst < 0)
01603 return t;
01604 #endif
01605
01606
01607
01608
01609
01610
01611 if (sp == NULL)
01612 return WRONG;
01613 for (i = 0; i < sp->typecnt; ++i)
01614 seen[i] = FALSE;
01615 nseen = 0;
01616 for (i = sp->timecnt - 1; i >= 0; --i)
01617 if (!seen[sp->types[i]]) {
01618 seen[sp->types[i]] = TRUE;
01619 types[nseen++] = sp->types[i];
01620 }
01621 for (sameind = 0; sameind < nseen; ++sameind) {
01622 samei = types[sameind];
01623 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
01624 continue;
01625 for (otherind = 0; otherind < nseen; ++otherind) {
01626 otheri = types[otherind];
01627 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
01628 continue;
01629 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
01630 sp->ttis[samei].tt_gmtoff;
01631 tmp->tm_isdst = !tmp->tm_isdst;
01632 t = time2(tmp, funcp, offset, &okay, sp);
01633 if (okay)
01634 return t;
01635 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
01636 sp->ttis[samei].tt_gmtoff;
01637 tmp->tm_isdst = !tmp->tm_isdst;
01638 }
01639 }
01640 return WRONG;
01641 }
01642
01643 time_t ast_mktime(struct tm *tmp, const char *zone)
01644 {
01645 const struct state *sp;
01646 if (!(sp = ast_tzset(zone)))
01647 return 0;
01648 return time1(tmp, localsub, 0L, sp);
01649 }
01650