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