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