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