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