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