2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2010, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * Most of this code is in the public domain, so clarified as of
9 * June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
11 * All modifications to this code to abstract timezones away from
12 * the environment are by Tilghman Lesher, <tlesher@vcch.com>, with
13 * the copyright assigned to Digium.
15 * See http://www.asterisk.org for more information about
16 * the Asterisk project. Please do not directly contact
17 * any of the maintainers of this project for assistance;
18 * the project provides a web site, mailing lists and IRC
19 * channels for your use.
21 * This program is free software, distributed under the terms of
22 * the GNU General Public License Version 2. See the LICENSE file
23 * at the top of the source tree.
28 * Multi-timezone Localtime code
30 * The original source from this file may be obtained from ftp://elsie.nci.nih.gov/pub/
34 ** This file is in the public domain, so clarified as of
35 ** 1996-06-05 by Arthur David Olson.
39 ** Leap second handling from Bradley White.
40 ** POSIX-style TZ environment variable handling from Guy Harris.
49 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
56 #include <sys/inotify.h>
57 #elif defined(HAVE_KQUEUE)
58 #include <sys/types.h>
60 #include <sys/event.h>
69 #include "asterisk/lock.h"
70 #include "asterisk/localtime.h"
71 #include "asterisk/strings.h"
72 #include "asterisk/linkedlists.h"
73 #include "asterisk/utils.h"
77 static char __attribute__((unused)) elsieid[] = "@(#)localtime.c 8.5";
78 #endif /* !defined NOID */
79 #endif /* !defined lint */
81 #ifndef TZ_ABBR_MAX_LEN
82 #define TZ_ABBR_MAX_LEN 16
83 #endif /* !defined TZ_ABBR_MAX_LEN */
85 #ifndef TZ_ABBR_CHAR_SET
86 #define TZ_ABBR_CHAR_SET \
87 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
88 #endif /* !defined TZ_ABBR_CHAR_SET */
90 #ifndef TZ_ABBR_ERR_CHAR
91 #define TZ_ABBR_ERR_CHAR '_'
92 #endif /* !defined TZ_ABBR_ERR_CHAR */
95 ** SunOS 4.1.1 headers lack O_BINARY.
99 #define OPEN_MODE (O_RDONLY | O_BINARY)
100 #endif /* defined O_BINARY */
102 #define OPEN_MODE O_RDONLY
103 #endif /* !defined O_BINARY */
105 static const char gmt[] = "GMT";
106 static const struct timeval WRONG = { 0, 0 };
109 * The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
110 * We default to US rules as of 1999-08-17.
111 * POSIX 1003.1 section 8.1.1 says that the default DST rules are
112 * implementation dependent; for historical reasons, US rules are a
115 #ifndef TZDEFRULESTRING
116 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
117 #endif /* !defined TZDEFDST */
119 /*!< \brief time type information */
120 struct ttinfo { /* time type information */
121 long tt_gmtoff; /* UTC offset in seconds */
122 int tt_isdst; /* used to set tm_isdst */
123 int tt_abbrind; /* abbreviation list index */
124 int tt_ttisstd; /* TRUE if transition is std time */
125 int tt_ttisgmt; /* TRUE if transition is UTC */
128 /*! \brief leap second information */
129 struct lsinfo { /* leap second information */
130 time_t ls_trans; /* transition time */
131 long ls_corr; /* correction to apply */
134 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
137 #define MY_TZNAME_MAX TZNAME_MAX
138 #endif /* defined TZNAME_MAX */
140 #define MY_TZNAME_MAX 255
141 #endif /* !defined TZNAME_MAX */
142 #ifndef TZ_STRLEN_MAX
143 #define TZ_STRLEN_MAX 255
144 #endif /* !defined TZ_STRLEN_MAX */
147 /*! Name of the file that this references */
148 char name[TZ_STRLEN_MAX + 1];
155 time_t ats[TZ_MAX_TIMES];
156 unsigned char types[TZ_MAX_TIMES];
157 struct ttinfo ttis[TZ_MAX_TYPES];
158 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
159 (2 * (MY_TZNAME_MAX + 1)))];
160 struct lsinfo lsis[TZ_MAX_LEAPS];
163 #elif defined(HAVE_KQUEUE)
165 # ifdef HAVE_O_SYMLINK
169 # endif /* defined(HAVE_O_SYMLINK) */
173 AST_LIST_ENTRY(state) list;
177 int r_type; /* type of rule--see below */
178 int r_day; /* day number of rule */
179 int r_week; /* week number of rule */
180 int r_mon; /* month number of rule */
181 long r_time; /* transition time of rule */
184 #define JULIAN_DAY 0 /* Jn - Julian day */
185 #define DAY_OF_YEAR 1 /* n - day of year */
186 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
189 ** Prototypes for static functions.
192 static long detzcode P((const char * codep));
193 static time_t detzcode64 P((const char * codep));
194 static int differ_by_repeat P((time_t t1, time_t t0));
195 static const char * getzname P((const char * strp));
196 static const char * getqzname P((const char * strp, const int delim));
197 static const char * getnum P((const char * strp, int * nump, int min,
199 static const char * getsecs P((const char * strp, long * secsp));
200 static const char * getoffset P((const char * strp, long * offsetp));
201 static const char * getrule P((const char * strp, struct rule * rulep));
202 static int gmtload P((struct state * sp));
203 static struct ast_tm * gmtsub P((const struct timeval * timep, long offset,
204 struct ast_tm * tmp));
205 static struct ast_tm * localsub P((const struct timeval * timep, long offset,
206 struct ast_tm * tmp, const struct state *sp));
207 static int increment_overflow P((int * number, int delta));
208 static int leaps_thru_end_of P((int y));
209 static int long_increment_overflow P((long * number, int delta));
210 static int long_normalize_overflow P((long * tensptr,
211 int * unitsptr, const int base));
212 static int normalize_overflow P((int * tensptr, int * unitsptr,
214 static struct timeval time1 P((struct ast_tm * tmp,
215 struct ast_tm * (*funcp) P((const struct timeval *,
216 long, struct ast_tm *, const struct state *sp)),
217 long offset, const struct state *sp));
218 static struct timeval time2 P((struct ast_tm *tmp,
219 struct ast_tm * (*funcp) P((const struct timeval *,
220 long, struct ast_tm*, const struct state *sp)),
221 long offset, int * okayp, const struct state *sp));
222 static struct timeval time2sub P((struct ast_tm *tmp,
223 struct ast_tm * (*funcp) (const struct timeval *,
224 long, struct ast_tm*, const struct state *sp),
225 long offset, int * okayp, int do_norm_secs, const struct state *sp));
226 static struct ast_tm * timesub P((const struct timeval * timep, long offset,
227 const struct state * sp, struct ast_tm * tmp));
228 static int tmcomp P((const struct ast_tm * atmp,
229 const struct ast_tm * btmp));
230 static time_t transtime P((time_t janfirst, int year,
231 const struct rule * rulep, long offset));
232 static int tzload P((const char * name, struct state * sp,
234 static int tzparse P((const char * name, struct state * sp,
237 static AST_LIST_HEAD_STATIC(zonelist, state);
239 #ifndef TZ_STRLEN_MAX
240 #define TZ_STRLEN_MAX 255
241 #endif /* !defined TZ_STRLEN_MAX */
243 static pthread_t inotify_thread = AST_PTHREADT_NULL;
244 static ast_cond_t initialization;
245 static ast_mutex_t initialization_lock;
247 static int inotify_fd = -1;
249 static void *inotify_daemon(void *data)
252 struct inotify_event iev;
253 char name[FILENAME_MAX + 1];
258 inotify_fd = inotify_init();
260 ast_mutex_lock(&initialization_lock);
261 ast_cond_broadcast(&initialization);
262 ast_mutex_unlock(&initialization_lock);
264 if (inotify_fd < 0) {
265 ast_log(LOG_ERROR, "Cannot initialize file notification service: %s (%d)\n", strerror(errno), errno);
266 inotify_thread = AST_PTHREADT_NULL;
271 /* This read should block, most of the time. */
272 if ((res = read(inotify_fd, &buf, sizeof(buf))) < sizeof(buf.iev) && res > 0) {
273 /* This should never happen */
274 ast_log(LOG_ERROR, "Inotify read less than a full event (%zd < %zd)?!!\n", res, sizeof(buf.iev));
276 } else if (res < 0) {
277 if (errno == EINTR || errno == EAGAIN) {
278 /* If read fails, try again */
279 AST_LIST_LOCK(&zonelist);
280 ast_cond_broadcast(&initialization);
281 AST_LIST_UNLOCK(&zonelist);
284 /* Sanity check -- this should never happen, either */
285 ast_log(LOG_ERROR, "Inotify failed: %s\n", strerror(errno));
288 AST_LIST_LOCK(&zonelist);
289 AST_LIST_TRAVERSE_SAFE_BEGIN(&zonelist, cur, list) {
290 if (cur->wd[0] == buf.iev.wd || cur->wd[1] == buf.iev.wd) {
291 AST_LIST_REMOVE_CURRENT(list);
296 AST_LIST_TRAVERSE_SAFE_END
297 ast_cond_broadcast(&initialization);
298 AST_LIST_UNLOCK(&zonelist);
301 inotify_thread = AST_PTHREADT_NULL;
305 static void add_notify(struct state *sp, const char *path)
307 if (inotify_thread == AST_PTHREADT_NULL) {
308 ast_cond_init(&initialization, NULL);
309 ast_mutex_init(&initialization_lock);
310 ast_mutex_lock(&initialization_lock);
311 if (!(ast_pthread_create_background(&inotify_thread, NULL, inotify_daemon, NULL))) {
312 /* Give the thread a chance to initialize */
313 ast_cond_wait(&initialization, &initialization_lock);
315 fprintf(stderr, "Unable to start notification thread\n");
316 ast_mutex_unlock(&initialization_lock);
319 ast_mutex_unlock(&initialization_lock);
322 if (inotify_fd > -1) {
323 char fullpath[FILENAME_MAX + 1] = "";
324 if (readlink(path, fullpath, sizeof(fullpath) - 1) != -1) {
325 /* If file the symlink points to changes */
326 sp->wd[1] = inotify_add_watch(inotify_fd, fullpath, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE );
330 /* or if the symlink itself changes (or the real file is here, if path is not a symlink) */
331 sp->wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE
332 #ifdef IN_DONT_FOLLOW /* Only defined in glibc 2.5 and above */
338 #elif defined(HAVE_KQUEUE)
339 static int queue_fd = -1;
341 static void *kqueue_daemon(void *data)
345 struct timespec no_wait = { 0, 1 };
347 ast_mutex_lock(&initialization_lock);
348 if ((queue_fd = kqueue()) < 0) {
349 /* ast_log uses us to format messages, so if we called ast_log, we'd be
350 * in for a nasty loop (seen already in testing) */
351 fprintf(stderr, "Unable to initialize kqueue(): %s\n", strerror(errno));
352 inotify_thread = AST_PTHREADT_NULL;
354 /* Okay to proceed */
355 ast_cond_signal(&initialization);
356 ast_mutex_unlock(&initialization_lock);
360 ast_cond_signal(&initialization);
361 ast_mutex_unlock(&initialization_lock);
364 if (kevent(queue_fd, NULL, 0, &kev, 1, NULL) < 0) {
365 AST_LIST_LOCK(&zonelist);
366 ast_cond_broadcast(&initialization);
367 AST_LIST_UNLOCK(&zonelist);
374 * If the file event fired, then the file was removed, so we'll need
375 * to reparse the entry. The directory event is a bit more
376 * interesting. Unfortunately, the queue doesn't contain information
377 * about the file that changed (only the directory itself), so unless
378 * we kept a record of the directory state before, it's not really
379 * possible to know what change occurred. But if we act paranoid and
380 * just purge the associated file, then it will get reparsed, and
381 * everything works fine. It may be more work, but it's a vast
382 * improvement over the alternative implementation, which is to stat
383 * the file repeatedly in what is essentially a busy loop. */
384 AST_LIST_LOCK(&zonelist);
385 AST_LIST_REMOVE(&zonelist, sp, list);
386 AST_LIST_UNLOCK(&zonelist);
388 /* If the directory event fired, remove the file event */
389 EV_SET(&kev, sp->fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
390 kevent(queue_fd, &kev, 1, NULL, 0, &no_wait);
393 #ifdef HAVE_O_SYMLINK
395 /* If the file event fired, remove the symlink event */
396 EV_SET(&kev, sp->fds, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
397 kevent(queue_fd, &kev, 1, NULL, 0, &no_wait);
402 /* If the file event fired, remove the directory event */
403 EV_SET(&kev, dirfd(sp->dir), EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
404 kevent(queue_fd, &kev, 1, NULL, 0, &no_wait);
410 /* Just in case the signal was sent late */
411 AST_LIST_LOCK(&zonelist);
412 ast_cond_broadcast(&initialization);
413 AST_LIST_UNLOCK(&zonelist);
417 static void add_notify(struct state *sp, const char *path)
420 struct timespec no_wait = { 0, 1 };
421 char watchdir[PATH_MAX + 1] = "";
423 if (inotify_thread == AST_PTHREADT_NULL) {
424 ast_cond_init(&initialization, NULL);
425 ast_mutex_init(&initialization_lock);
426 ast_mutex_lock(&initialization_lock);
427 if (!(ast_pthread_create_background(&inotify_thread, NULL, kqueue_daemon, NULL))) {
428 /* Give the thread a chance to initialize */
429 ast_cond_wait(&initialization, &initialization_lock);
431 ast_mutex_unlock(&initialization_lock);
435 /* Error already sent */
439 #ifdef HAVE_O_SYMLINK
440 if (readlink(path, watchdir, sizeof(watchdir) - 1) != -1 && (sp->fds = open(path, O_RDONLY | O_SYMLINK
441 # ifdef HAVE_O_EVTONLY
445 EV_SET(&kev, sp->fds, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, NOTE_WRITE | NOTE_EXTEND | NOTE_DELETE | NOTE_REVOKE | NOTE_ATTRIB, 0, sp);
446 if (kevent(queue_fd, &kev, 1, NULL, 0, &no_wait) < 0 && errno != 0) {
447 /* According to the API docs, we may get -1 return value, due to the
448 * NULL space for a returned event, but errno should be 0 unless
449 * there's a real error. Otherwise, kevent will return 0 to indicate
450 * that the time limit expired. */
451 fprintf(stderr, "Unable to watch '%s': %s\n", path, strerror(errno));
457 if (readlink(path, watchdir, sizeof(watchdir) - 1) != -1) {
458 /* Special -- watch the directory for changes, because we cannot directly watch a symlink */
461 ast_copy_string(watchdir, path, sizeof(watchdir));
463 if ((slash = strrchr(watchdir, '/'))) {
466 if (!(sp->dir = opendir(watchdir))) {
467 fprintf(stderr, "Unable to watch directory with symlink '%s': %s\n", path, strerror(errno));
472 * You may be wondering about whether there is a potential conflict
473 * with the kqueue interface, because we might be watching the same
474 * directory for multiple zones. The answer is no, because kqueue
475 * looks at the descriptor to know if there's a duplicate. Since we
476 * (may) have opened the directory multiple times, each represents a
477 * different event, so no replacement of an existing event will occur.
478 * Likewise, there's no potential leak of a descriptor.
480 EV_SET(&kev, dirfd(sp->dir), EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
481 NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_REVOKE | NOTE_ATTRIB, 0, sp);
482 if (kevent(queue_fd, &kev, 1, NULL, 0, &no_wait) < 0 && errno != 0) {
483 fprintf(stderr, "Unable to watch '%s': %s\n", watchdir, strerror(errno));
492 if ((sp->fd = open(path, O_RDONLY
493 # ifdef HAVE_O_EVTONLY
497 fprintf(stderr, "Unable to watch '%s' for changes: %s\n", path, strerror(errno));
501 EV_SET(&kev, sp->fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, NOTE_WRITE | NOTE_EXTEND | NOTE_DELETE | NOTE_REVOKE | NOTE_ATTRIB, 0, sp);
502 if (kevent(queue_fd, &kev, 1, NULL, 0, &no_wait) < 0 && errno != 0) {
503 /* According to the API docs, we may get -1 return value, due to the
504 * NULL space for a returned event, but errno should be 0 unless
505 * there's a real error. Otherwise, kevent will return 0 to indicate
506 * that the time limit expired. */
507 fprintf(stderr, "Unable to watch '%s': %s\n", path, strerror(errno));
513 static void *notify_daemon(void *data)
517 struct timespec sixty_seconds = { 60, 0 };
519 ast_mutex_lock(&initialization_lock);
520 ast_cond_broadcast(&initialization);
521 ast_mutex_unlock(&initialization_lock);
524 char fullname[FILENAME_MAX + 1];
526 nanosleep(&sixty_seconds, NULL);
527 AST_LIST_LOCK(&zonelist);
528 AST_LIST_TRAVERSE_SAFE_BEGIN(&zonelist, cur, list) {
529 char *name = cur->name;
533 if (name[0] != '/') {
534 (void) strcpy(fullname, TZDIR "/");
535 (void) strcat(fullname, name);
540 if (st.st_mtime > cur->mtime[0] || lst.st_mtime > cur->mtime[1]) {
541 ast_log(LOG_NOTICE, "Removing cached TZ entry '%s' because underlying file changed.\n", name);
542 AST_LIST_REMOVE_CURRENT(list);
547 AST_LIST_TRAVERSE_SAFE_END
548 ast_cond_broadcast(&initialization);
549 AST_LIST_UNLOCK(&zonelist);
551 inotify_thread = AST_PTHREADT_NULL;
555 static void add_notify(struct state *sp, const char *path)
559 if (inotify_thread == AST_PTHREADT_NULL) {
560 ast_cond_init(&initialization, NULL);
561 ast_mutex_init(&initialization_lock);
562 ast_mutex_lock(&initialization_lock);
563 if (!(ast_pthread_create_background(&inotify_thread, NULL, notify_daemon, NULL))) {
564 /* Give the thread a chance to initialize */
565 ast_cond_wait(&initialization, &initialization_lock);
567 ast_mutex_unlock(&initialization_lock);
571 sp->mtime[0] = st.st_mtime;
573 sp->mtime[1] = st.st_mtime;
577 void ast_localtime_wakeup_monitor(void)
579 if (inotify_thread != AST_PTHREADT_NULL) {
580 AST_LIST_LOCK(&zonelist);
581 pthread_kill(inotify_thread, SIGURG);
582 ast_cond_wait(&initialization, &(&zonelist)->lock);
583 AST_LIST_UNLOCK(&zonelist);
588 ** Section 4.12.3 of X3.159-1989 requires that
589 ** Except for the strftime function, these functions [asctime,
590 ** ctime, gmtime, localtime] return values in one of two static
591 ** objects: a broken-down time structure and an array of char.
592 ** Thanks to Paul Eggert for noting this.
595 static long detzcode(const char * const codep)
600 result = (codep[0] & 0x80) ? ~0L : 0;
601 for (i = 0; i < 4; ++i)
602 result = (result << 8) | (codep[i] & 0xff);
606 static time_t detzcode64(const char * const codep)
611 result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
612 for (i = 0; i < 8; ++i)
613 result = result * 256 + (codep[i] & 0xff);
617 static int differ_by_repeat(const time_t t1, const time_t t0)
619 const long long at1 = t1, at0 = t0;
620 if (TYPE_INTEGRAL(time_t) &&
621 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
623 return at1 - at0 == SECSPERREPEAT;
626 static int tzload(const char *name, struct state * const sp, const int doextend)
634 struct tzhead tzhead;
635 char buf[2 * sizeof(struct tzhead) +
640 if (name == NULL && (name = TZDEFAULT) == NULL)
645 ** Section 4.9.1 of the C standard says that
646 ** "FILENAME_MAX expands to an integral constant expression
647 ** that is the size needed for an array of char large enough
648 ** to hold the longest file name string that the implementation
649 ** guarantees can be opened."
651 char fullname[FILENAME_MAX + 1];
655 doaccess = name[0] == '/';
657 if ((p = TZDIR) == NULL)
659 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
661 (void) strcpy(fullname, p);
662 (void) strcat(fullname, "/");
663 (void) strcat(fullname, name);
665 ** Set doaccess if '.' (as in "../") shows up in name.
667 if (strchr(name, '.') != NULL)
671 if (doaccess && access(name, R_OK) != 0)
673 if ((fid = open(name, OPEN_MODE)) == -1)
675 add_notify(sp, name);
677 nread = read(fid, u.buf, sizeof u.buf);
678 if (close(fid) < 0 || nread <= 0)
680 for (stored = 4; stored <= 8; stored *= 2) {
684 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
685 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
686 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
687 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
688 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
689 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
690 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
691 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
692 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
693 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
694 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
695 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
696 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
698 if (nread - (p - u.buf) <
699 sp->timecnt * stored + /* ats */
700 sp->timecnt + /* types */
701 sp->typecnt * 6 + /* ttinfos */
702 sp->charcnt + /* chars */
703 sp->leapcnt * (stored + 4) + /* lsinfos */
704 ttisstdcnt + /* ttisstds */
705 ttisgmtcnt) /* ttisgmts */
707 for (i = 0; i < sp->timecnt; ++i) {
708 sp->ats[i] = (stored == 4) ?
709 detzcode(p) : detzcode64(p);
712 for (i = 0; i < sp->timecnt; ++i) {
713 sp->types[i] = (unsigned char) *p++;
714 if (sp->types[i] >= sp->typecnt)
717 for (i = 0; i < sp->typecnt; ++i) {
718 struct ttinfo * ttisp;
720 ttisp = &sp->ttis[i];
721 ttisp->tt_gmtoff = detzcode(p);
723 ttisp->tt_isdst = (unsigned char) *p++;
724 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
726 ttisp->tt_abbrind = (unsigned char) *p++;
727 if (ttisp->tt_abbrind < 0 ||
728 ttisp->tt_abbrind > sp->charcnt)
731 for (i = 0; i < sp->charcnt; ++i)
733 sp->chars[i] = '\0'; /* ensure '\0' at end */
734 for (i = 0; i < sp->leapcnt; ++i) {
735 struct lsinfo * lsisp;
737 lsisp = &sp->lsis[i];
738 lsisp->ls_trans = (stored == 4) ?
739 detzcode(p) : detzcode64(p);
741 lsisp->ls_corr = detzcode(p);
744 for (i = 0; i < sp->typecnt; ++i) {
745 struct ttinfo * ttisp;
747 ttisp = &sp->ttis[i];
749 ttisp->tt_ttisstd = FALSE;
751 ttisp->tt_ttisstd = *p++;
752 if (ttisp->tt_ttisstd != TRUE &&
753 ttisp->tt_ttisstd != FALSE)
757 for (i = 0; i < sp->typecnt; ++i) {
758 struct ttinfo * ttisp;
760 ttisp = &sp->ttis[i];
762 ttisp->tt_ttisgmt = FALSE;
764 ttisp->tt_ttisgmt = *p++;
765 if (ttisp->tt_ttisgmt != TRUE &&
766 ttisp->tt_ttisgmt != FALSE)
771 ** Out-of-sort ats should mean we're running on a
772 ** signed time_t system but using a data file with
773 ** unsigned values (or vice versa).
775 for (i = 0; i < sp->timecnt - 2; ++i)
776 if (sp->ats[i] > sp->ats[i + 1]) {
778 if (TYPE_SIGNED(time_t)) {
780 ** Ignore the end (easy).
785 ** Ignore the beginning (harder).
789 for (j = 0; j + i < sp->timecnt; ++j) {
790 sp->ats[j] = sp->ats[j + i];
791 sp->types[j] = sp->types[j + i];
798 ** If this is an old file, we're done.
800 if (u.tzhead.tzh_version[0] == '\0')
803 for (i = 0; i < nread; ++i)
806 ** If this is a narrow integer time_t system, we're done.
808 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
811 if (doextend && nread > 2 &&
812 u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
813 sp->typecnt + 2 <= TZ_MAX_TYPES) {
817 u.buf[nread - 1] = '\0';
818 result = tzparse(&u.buf[1], &ts, FALSE);
819 if (result == 0 && ts.typecnt == 2 &&
820 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
821 for (i = 0; i < 2; ++i)
822 ts.ttis[i].tt_abbrind +=
824 for (i = 0; i < ts.charcnt; ++i)
825 sp->chars[sp->charcnt++] =
828 while (i < ts.timecnt &&
830 sp->ats[sp->timecnt - 1])
832 while (i < ts.timecnt &&
833 sp->timecnt < TZ_MAX_TIMES) {
834 sp->ats[sp->timecnt] =
836 sp->types[sp->timecnt] =
842 sp->ttis[sp->typecnt++] = ts.ttis[0];
843 sp->ttis[sp->typecnt++] = ts.ttis[1];
846 i = 2 * YEARSPERREPEAT;
847 sp->goback = sp->goahead = sp->timecnt > i;
848 sp->goback = sp->goback && sp->types[i] == sp->types[0] &&
849 differ_by_repeat(sp->ats[i], sp->ats[0]);
850 sp->goahead = sp->goahead &&
851 sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
852 differ_by_repeat(sp->ats[sp->timecnt - 1],
853 sp->ats[sp->timecnt - 1 - i]);
857 static const int mon_lengths[2][MONSPERYEAR] = {
858 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
859 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
862 static const int year_lengths[2] = {
863 DAYSPERNYEAR, DAYSPERLYEAR
867 ** Given a pointer into a time zone string, scan until a character that is not
868 ** a valid character in a zone name is found. Return a pointer to that
872 static const char * getzname(const char *strp)
876 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
883 ** Given a pointer into an extended time zone string, scan until the ending
884 ** delimiter of the zone name is located. Return a pointer to the delimiter.
886 ** As with getzname above, the legal character set is actually quite
887 ** restricted, with other characters producing undefined results.
888 ** We don't do any checking here; checking is done later in common-case code.
891 static const char * getqzname(const char *strp, const int delim)
895 while ((c = *strp) != '\0' && c != delim)
901 ** Given a pointer into a time zone string, extract a number from that string.
902 ** Check that the number is within a specified range; if it is not, return
904 ** Otherwise, return a pointer to the first character not part of the number.
907 static const char *getnum(const char *strp, int *nump, const int min, const int max)
912 if (strp == NULL || !is_digit(c = *strp))
916 num = num * 10 + (c - '0');
918 return NULL; /* illegal value */
920 } while (is_digit(c));
922 return NULL; /* illegal value */
928 ** Given a pointer into a time zone string, extract a number of seconds,
929 ** in hh[:mm[:ss]] form, from the string.
930 ** If any error occurs, return NULL.
931 ** Otherwise, return a pointer to the first character not part of the number
935 static const char *getsecs(const char *strp, long * const secsp)
940 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
941 ** "M10.4.6/26", which does not conform to Posix,
942 ** but which specifies the equivalent of
943 ** ``02:00 on the first Sunday on or after 23 Oct''.
945 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
948 *secsp = num * (long) SECSPERHOUR;
951 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
954 *secsp += num * SECSPERMIN;
957 /* `SECSPERMIN' allows for leap seconds. */
958 strp = getnum(strp, &num, 0, SECSPERMIN);
968 ** Given a pointer into a time zone string, extract an offset, in
969 ** [+-]hh[:mm[:ss]] form, from the string.
970 ** If any error occurs, return NULL.
971 ** Otherwise, return a pointer to the first character not part of the time.
974 static const char *getoffset(const char *strp, long *offsetp)
981 } else if (*strp == '+')
983 strp = getsecs(strp, offsetp);
985 return NULL; /* illegal time */
987 *offsetp = -*offsetp;
992 ** Given a pointer into a time zone string, extract a rule in the form
993 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
994 ** If a valid rule is not found, return NULL.
995 ** Otherwise, return a pointer to the first character not part of the rule.
998 static const char *getrule(const char *strp, struct rule *rulep)
1004 rulep->r_type = JULIAN_DAY;
1006 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
1007 } else if (*strp == 'M') {
1009 ** Month, week, day.
1011 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
1013 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
1018 strp = getnum(strp, &rulep->r_week, 1, 5);
1023 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
1024 } else if (is_digit(*strp)) {
1028 rulep->r_type = DAY_OF_YEAR;
1029 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
1030 } else return NULL; /* invalid format */
1038 strp = getsecs(strp, &rulep->r_time);
1039 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
1044 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
1045 ** year, a rule, and the offset from UTC at the time that rule takes effect,
1046 ** calculate the Epoch-relative time that rule takes effect.
1049 static time_t transtime(const time_t janfirst, const int year, const struct rule *rulep, const long offset)
1054 int d, m1, yy0, yy1, yy2, dow;
1057 leapyear = isleap(year);
1058 switch (rulep->r_type) {
1062 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
1064 ** In non-leap years, or if the day number is 59 or less, just
1065 ** add SECSPERDAY times the day number-1 to the time of
1066 ** January 1, midnight, to get the day.
1068 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
1069 if (leapyear && rulep->r_day >= 60)
1070 value += SECSPERDAY;
1076 ** Just add SECSPERDAY times the day number to the time of
1077 ** January 1, midnight, to get the day.
1079 value = janfirst + rulep->r_day * SECSPERDAY;
1082 case MONTH_NTH_DAY_OF_WEEK:
1084 ** Mm.n.d - nth "dth day" of month m.
1087 for (i = 0; i < rulep->r_mon - 1; ++i)
1088 value += mon_lengths[leapyear][i] * SECSPERDAY;
1091 ** Use Zeller's Congruence to get day-of-week of first day of
1094 m1 = (rulep->r_mon + 9) % 12 + 1;
1095 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
1098 dow = ((26 * m1 - 2) / 10 +
1099 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1104 ** "dow" is the day-of-week of the first day of the month. Get
1105 ** the day-of-month (zero-origin) of the first "dow" day of the
1108 d = rulep->r_day - dow;
1111 for (i = 1; i < rulep->r_week; ++i) {
1112 if (d + DAYSPERWEEK >=
1113 mon_lengths[leapyear][rulep->r_mon - 1])
1119 ** "d" is the day-of-month (zero-origin) of the day we want.
1121 value += d * SECSPERDAY;
1126 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
1127 ** question. To get the Epoch-relative time of the specified local
1128 ** time on that day, add the transition time and the current offset
1131 return value + rulep->r_time + offset;
1135 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
1139 static int tzparse(const char *name, struct state *sp, const int lastditch)
1141 const char * stdname;
1142 const char * dstname;
1148 unsigned char * typep;
1152 INITIALIZE(dstname);
1155 stdlen = strlen(name); /* length of standard zone name */
1157 if (stdlen >= sizeof sp->chars)
1158 stdlen = (sizeof sp->chars) - 1;
1164 name = getqzname(name, '>');
1167 stdlen = name - stdname;
1170 name = getzname(name);
1171 stdlen = name - stdname;
1175 name = getoffset(name, &stdoffset);
1179 load_result = tzload(TZDEFRULES, sp, FALSE);
1180 if (load_result != 0)
1181 sp->leapcnt = 0; /* so, we're off a little */
1182 if (*name != '\0') {
1185 name = getqzname(name, '>');
1188 dstlen = name - dstname;
1192 name = getzname(name);
1193 dstlen = name - dstname; /* length of DST zone name */
1195 if (*name != '\0' && *name != ',' && *name != ';') {
1196 name = getoffset(name, &dstoffset);
1199 } else dstoffset = stdoffset - SECSPERHOUR;
1200 if (*name == '\0' && load_result != 0)
1201 name = TZDEFRULESTRING;
1202 if (*name == ',' || *name == ';') {
1211 if ((name = getrule(name, &start)) == NULL)
1215 if ((name = getrule(name, &end)) == NULL)
1219 sp->typecnt = 2; /* standard time and DST */
1221 ** Two transitions per year, from EPOCH_YEAR forward.
1223 sp->ttis[0].tt_gmtoff = -dstoffset;
1224 sp->ttis[0].tt_isdst = 1;
1225 sp->ttis[0].tt_abbrind = stdlen + 1;
1226 sp->ttis[1].tt_gmtoff = -stdoffset;
1227 sp->ttis[1].tt_isdst = 0;
1228 sp->ttis[1].tt_abbrind = 0;
1233 for (year = EPOCH_YEAR;
1234 sp->timecnt + 2 <= TZ_MAX_TIMES;
1238 starttime = transtime(janfirst, year, &start,
1240 endtime = transtime(janfirst, year, &end,
1242 if (starttime > endtime) {
1244 *typep++ = 1; /* DST ends */
1246 *typep++ = 0; /* DST begins */
1249 *typep++ = 0; /* DST begins */
1251 *typep++ = 1; /* DST ends */
1254 newfirst = janfirst;
1255 newfirst += year_lengths[isleap(year)] *
1257 if (newfirst <= janfirst)
1259 janfirst = newfirst;
1262 long theirstdoffset;
1263 long theirdstoffset;
1272 ** Initial values of theirstdoffset and theirdstoffset.
1275 for (i = 0; i < sp->timecnt; ++i) {
1277 if (!sp->ttis[j].tt_isdst) {
1279 -sp->ttis[j].tt_gmtoff;
1284 for (i = 0; i < sp->timecnt; ++i) {
1286 if (sp->ttis[j].tt_isdst) {
1288 -sp->ttis[j].tt_gmtoff;
1293 ** Initially we're assumed to be in standard time.
1296 theiroffset = theirstdoffset;
1298 ** Now juggle transition times and types
1299 ** tracking offsets as you do.
1301 for (i = 0; i < sp->timecnt; ++i) {
1303 sp->types[i] = sp->ttis[j].tt_isdst;
1304 if (sp->ttis[j].tt_ttisgmt) {
1305 /* No adjustment to transition time */
1308 ** If summer time is in effect, and the
1309 ** transition time was not specified as
1310 ** standard time, add the summer time
1311 ** offset to the transition time;
1312 ** otherwise, add the standard time
1313 ** offset to the transition time.
1316 ** Transitions from DST to DDST
1317 ** will effectively disappear since
1318 ** POSIX provides for only one DST
1321 if (isdst && !sp->ttis[j].tt_ttisstd) {
1322 sp->ats[i] += dstoffset -
1325 sp->ats[i] += stdoffset -
1329 theiroffset = -sp->ttis[j].tt_gmtoff;
1330 if (sp->ttis[j].tt_isdst)
1331 theirdstoffset = theiroffset;
1332 else theirstdoffset = theiroffset;
1335 ** Finally, fill in ttis.
1336 ** ttisstd and ttisgmt need not be handled.
1338 sp->ttis[0].tt_gmtoff = -stdoffset;
1339 sp->ttis[0].tt_isdst = FALSE;
1340 sp->ttis[0].tt_abbrind = 0;
1341 sp->ttis[1].tt_gmtoff = -dstoffset;
1342 sp->ttis[1].tt_isdst = TRUE;
1343 sp->ttis[1].tt_abbrind = stdlen + 1;
1348 sp->typecnt = 1; /* only standard time */
1350 sp->ttis[0].tt_gmtoff = -stdoffset;
1351 sp->ttis[0].tt_isdst = 0;
1352 sp->ttis[0].tt_abbrind = 0;
1354 sp->charcnt = stdlen + 1;
1356 sp->charcnt += dstlen + 1;
1357 if ((size_t) sp->charcnt > sizeof sp->chars)
1360 (void) strncpy(cp, stdname, stdlen);
1364 (void) strncpy(cp, dstname, dstlen);
1365 *(cp + dstlen) = '\0';
1370 static int gmtload(struct state *sp)
1372 if (tzload(gmt, sp, TRUE) != 0)
1373 return tzparse(gmt, sp, TRUE);
1378 static const struct state *ast_tzset(const char *zone)
1382 if (ast_strlen_zero(zone))
1383 zone = "/etc/localtime";
1385 AST_LIST_LOCK(&zonelist);
1386 AST_LIST_TRAVERSE(&zonelist, sp, list) {
1387 if (!strcmp(sp->name, zone)) {
1388 AST_LIST_UNLOCK(&zonelist);
1392 AST_LIST_UNLOCK(&zonelist);
1394 if (!(sp = ast_calloc(1, sizeof *sp)))
1397 if (tzload(zone, sp, TRUE) != 0) {
1398 if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0)
1401 ast_copy_string(sp->name, zone, sizeof(sp->name));
1402 AST_LIST_LOCK(&zonelist);
1403 AST_LIST_INSERT_TAIL(&zonelist, sp, list);
1404 AST_LIST_UNLOCK(&zonelist);
1409 ** The easy way to behave "as if no library function calls" localtime
1410 ** is to not call it--so we drop its guts into "localsub", which can be
1411 ** freely called. (And no, the PANS doesn't require the above behavior--
1412 ** but it *is* desirable.)
1414 ** The unused offset argument is for the benefit of mktime variants.
1417 static struct ast_tm *localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
1419 const struct ttinfo * ttisp;
1421 struct ast_tm * result;
1423 memcpy(&t, timep, sizeof(t));
1426 return gmtsub(timep, offset, tmp);
1427 if ((sp->goback && t.tv_sec < sp->ats[0]) ||
1428 (sp->goahead && t.tv_sec > sp->ats[sp->timecnt - 1])) {
1429 struct timeval newt = t;
1432 int_fast64_t icycles;
1434 if (t.tv_sec < sp->ats[0])
1435 seconds = sp->ats[0] - t.tv_sec;
1436 else seconds = t.tv_sec - sp->ats[sp->timecnt - 1];
1438 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1441 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1444 seconds *= YEARSPERREPEAT;
1445 seconds *= AVGSECSPERYEAR;
1446 if (t.tv_sec < sp->ats[0])
1447 newt.tv_sec += seconds;
1448 else newt.tv_sec -= seconds;
1449 if (newt.tv_sec < sp->ats[0] ||
1450 newt.tv_sec > sp->ats[sp->timecnt - 1])
1451 return NULL; /* "cannot happen" */
1452 result = localsub(&newt, offset, tmp, sp);
1453 if (result == tmp) {
1456 newy = tmp->tm_year;
1457 if (t.tv_sec < sp->ats[0])
1458 newy -= icycles * YEARSPERREPEAT;
1460 newy += icycles * YEARSPERREPEAT;
1461 tmp->tm_year = newy;
1462 if (tmp->tm_year != newy)
1467 if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) {
1469 while (sp->ttis[i].tt_isdst) {
1470 if (++i >= sp->typecnt) {
1477 int hi = sp->timecnt;
1480 int mid = (lo + hi) >> 1;
1482 if (t.tv_sec < sp->ats[mid])
1487 i = (int) sp->types[lo - 1];
1489 ttisp = &sp->ttis[i];
1491 ** To get (wrong) behavior that's compatible with System V Release 2.0
1492 ** you'd replace the statement below with
1493 ** t += ttisp->tt_gmtoff;
1494 ** timesub(&t, 0L, sp, tmp);
1496 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1497 tmp->tm_isdst = ttisp->tt_isdst;
1498 #ifndef SOLARIS /* Solaris doesn't have this element */
1499 tmp->tm_gmtoff = ttisp->tt_gmtoff;
1502 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
1503 #endif /* defined TM_ZONE */
1504 tmp->tm_usec = timep->tv_usec;
1508 struct ast_tm *ast_localtime(const struct timeval *timep, struct ast_tm *tmp, const char *zone)
1510 const struct state *sp = ast_tzset(zone);
1511 memset(tmp, 0, sizeof(*tmp));
1512 return sp ? localsub(timep, 0L, tmp, sp) : NULL;
1516 ** This function provides informaton about daylight savings time
1517 ** for the given timezone. This includes whether it can determine
1518 ** if daylight savings is used for this timezone, the UTC times for
1519 ** when daylight savings transitions, and the offset in seconds from
1523 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)
1526 int transition1 = -1;
1527 int transition2 = -1;
1529 int bounds_exceeded = 0;
1531 const struct state *sp;
1533 if (NULL == dst_enabled)
1537 if (NULL == dst_start || NULL == dst_end || NULL == gmt_off)
1542 sp = ast_tzset(zone);
1546 /* If the desired time exceeds the bounds of the defined time transitions
1547 * then give give up on determining DST info and simply look for gmt offset
1548 * This requires that I adjust the given time using increments of Gregorian
1549 * repeats to place the time within the defined time transitions in the
1550 * timezone structure.
1552 if ((sp->goback && t < sp->ats[0]) ||
1553 (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1555 int_fast64_t icycles;
1558 seconds = sp->ats[0] - t;
1559 else seconds = t - sp->ats[sp->timecnt - 1];
1561 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1564 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1567 seconds *= YEARSPERREPEAT;
1568 seconds *= AVGSECSPERYEAR;
1574 if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1])
1575 return; /* "cannot happen" */
1577 bounds_exceeded = 1;
1580 if (sp->timecnt == 0 || t < sp->ats[0]) {
1581 /* I have no transition times or I'm before time */
1583 /* Find where I can get gmtoff */
1585 while (sp->ttis[i].tt_isdst)
1586 if (++i >= sp->typecnt) {
1590 *gmt_off = sp->ttis[i].tt_gmtoff;
1594 for (i = 1; i < sp->timecnt; ++i) {
1595 if (t < sp->ats[i]) {
1596 transition1 = sp->types[i - 1];
1597 transition2 = sp->types[i];
1601 /* if I found transition times that do not bounded the given time and these correspond to
1602 or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */
1603 if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 ||
1604 (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) {
1606 *gmt_off = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff;
1608 /* I have valid daylight savings information. */
1609 if(sp->ttis[transition2].tt_isdst)
1610 *gmt_off = sp->ttis[transition1].tt_gmtoff;
1612 *gmt_off = sp->ttis[transition2].tt_gmtoff;
1614 /* If I adjusted the time earlier, indicate that the dst is invalid */
1615 if (!bounds_exceeded) {
1617 /* Determine which of the bounds is the start of daylight savings and which is the end */
1618 if(sp->ttis[transition2].tt_isdst) {
1619 *dst_start = sp->ats[i];
1620 *dst_end = sp->ats[i -1];
1622 *dst_start = sp->ats[i -1];
1623 *dst_end = sp->ats[i];
1631 ** gmtsub is to gmtime as localsub is to localtime.
1634 static struct ast_tm *gmtsub(const struct timeval *timep, const long offset, struct ast_tm *tmp)
1636 struct ast_tm * result;
1639 AST_LIST_LOCK(&zonelist);
1640 AST_LIST_TRAVERSE(&zonelist, sp, list) {
1641 if (!strcmp(sp->name, "UTC"))
1646 if (!(sp = (struct state *) ast_calloc(1, sizeof *sp)))
1649 AST_LIST_INSERT_TAIL(&zonelist, sp, list);
1651 AST_LIST_UNLOCK(&zonelist);
1653 result = timesub(timep, offset, sp, tmp);
1656 ** Could get fancy here and deliver something such as
1657 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1658 ** but this is no time for a treasure hunt.
1663 tmp->TM_ZONE = sp->chars;
1664 #endif /* defined TM_ZONE */
1669 ** Return the number of leap years through the end of the given year
1670 ** where, to make the math easy, the answer for year zero is defined as zero.
1673 static int leaps_thru_end_of(const int y)
1675 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1676 -(leaps_thru_end_of(-(y + 1)) + 1);
1679 static struct ast_tm *timesub(const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
1681 const struct lsinfo * lp;
1683 int idays; /* unsigned would be so 2003 */
1695 i = (sp == NULL) ? 0 : sp->leapcnt;
1698 if (timep->tv_sec >= lp->ls_trans) {
1699 if (timep->tv_sec == lp->ls_trans) {
1700 hit = ((i == 0 && lp->ls_corr > 0) ||
1701 lp->ls_corr > sp->lsis[i - 1].ls_corr);
1704 sp->lsis[i].ls_trans ==
1705 sp->lsis[i - 1].ls_trans + 1 &&
1706 sp->lsis[i].ls_corr ==
1707 sp->lsis[i - 1].ls_corr + 1) {
1717 tdays = timep->tv_sec / SECSPERDAY;
1718 rem = timep->tv_sec - tdays * SECSPERDAY;
1719 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
1725 tdelta = tdays / DAYSPERLYEAR;
1727 if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
1730 idelta = (tdays < 0) ? -1 : 1;
1732 if (increment_overflow(&newy, idelta))
1734 leapdays = leaps_thru_end_of(newy - 1) -
1735 leaps_thru_end_of(y - 1);
1736 tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
1741 seconds = tdays * SECSPERDAY + 0.5;
1742 tdays = seconds / SECSPERDAY;
1743 rem += seconds - tdays * SECSPERDAY;
1746 ** Given the range, we can now fearlessly cast...
1749 rem += offset - corr;
1754 while (rem >= SECSPERDAY) {
1759 if (increment_overflow(&y, -1))
1761 idays += year_lengths[isleap(y)];
1763 while (idays >= year_lengths[isleap(y)]) {
1764 idays -= year_lengths[isleap(y)];
1765 if (increment_overflow(&y, 1))
1769 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
1771 tmp->tm_yday = idays;
1773 ** The "extra" mods below avoid overflow problems.
1775 tmp->tm_wday = EPOCH_WDAY +
1776 ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1777 (DAYSPERNYEAR % DAYSPERWEEK) +
1778 leaps_thru_end_of(y - 1) -
1779 leaps_thru_end_of(EPOCH_YEAR - 1) +
1781 tmp->tm_wday %= DAYSPERWEEK;
1782 if (tmp->tm_wday < 0)
1783 tmp->tm_wday += DAYSPERWEEK;
1784 tmp->tm_hour = (int) (rem / SECSPERHOUR);
1786 tmp->tm_min = (int) (rem / SECSPERMIN);
1788 ** A positive leap second requires a special
1789 ** representation. This uses "... ??:59:60" et seq.
1791 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1792 ip = mon_lengths[isleap(y)];
1793 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1794 idays -= ip[tmp->tm_mon];
1795 tmp->tm_mday = (int) (idays + 1);
1798 tmp->TM_GMTOFF = offset;
1799 #endif /* defined TM_GMTOFF */
1800 tmp->tm_usec = timep->tv_usec;
1805 ** Adapted from code provided by Robert Elz, who writes:
1806 ** The "best" way to do mktime I think is based on an idea of Bob
1807 ** Kridle's (so its said...) from a long time ago.
1808 ** It does a binary search of the time_t space. Since time_t's are
1809 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1810 ** would still be very reasonable).
1814 ** Simplified normalize logic courtesy Paul Eggert.
1817 static int increment_overflow(int *number, int delta)
1823 return (*number < number0) != (delta < 0);
1826 static int long_increment_overflow(long *number, int delta)
1832 return (*number < number0) != (delta < 0);
1835 static int normalize_overflow(int *tensptr, int *unitsptr, const int base)
1839 tensdelta = (*unitsptr >= 0) ?
1840 (*unitsptr / base) :
1841 (-1 - (-1 - *unitsptr) / base);
1842 *unitsptr -= tensdelta * base;
1843 return increment_overflow(tensptr, tensdelta);
1846 static int long_normalize_overflow(long *tensptr, int *unitsptr, const int base)
1850 tensdelta = (*unitsptr >= 0) ?
1851 (*unitsptr / base) :
1852 (-1 - (-1 - *unitsptr) / base);
1853 *unitsptr -= tensdelta * base;
1854 return long_increment_overflow(tensptr, tensdelta);
1857 static int tmcomp(const struct ast_tm *atmp, const struct ast_tm *btmp)
1861 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1862 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1863 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1864 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1865 (result = (atmp->tm_min - btmp->tm_min)) == 0 &&
1866 (result = (atmp->tm_sec - btmp->tm_sec)) == 0)
1867 result = atmp->tm_usec - btmp->tm_usec;
1871 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)
1880 struct timeval newt = { 0, 0 };
1881 struct timeval t = { 0, 0 };
1882 struct ast_tm yourtm, mytm;
1887 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
1891 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
1893 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
1896 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
1899 ** Turn y into an actual year number for now.
1900 ** It is converted back to an offset from TM_YEAR_BASE later.
1902 if (long_increment_overflow(&y, TM_YEAR_BASE))
1904 while (yourtm.tm_mday <= 0) {
1905 if (long_increment_overflow(&y, -1))
1907 li = y + (1 < yourtm.tm_mon);
1908 yourtm.tm_mday += year_lengths[isleap(li)];
1910 while (yourtm.tm_mday > DAYSPERLYEAR) {
1911 li = y + (1 < yourtm.tm_mon);
1912 yourtm.tm_mday -= year_lengths[isleap(li)];
1913 if (long_increment_overflow(&y, 1))
1917 i = mon_lengths[isleap(y)][yourtm.tm_mon];
1918 if (yourtm.tm_mday <= i)
1920 yourtm.tm_mday -= i;
1921 if (++yourtm.tm_mon >= MONSPERYEAR) {
1923 if (long_increment_overflow(&y, 1))
1927 if (long_increment_overflow(&y, -TM_YEAR_BASE))
1930 if (yourtm.tm_year != y)
1932 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
1934 else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
1936 ** We can't set tm_sec to 0, because that might push the
1937 ** time below the minimum representable time.
1938 ** Set tm_sec to 59 instead.
1939 ** This assumes that the minimum representable time is
1940 ** not in the same minute that a leap second was deleted from,
1941 ** which is a safer assumption than using 58 would be.
1943 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
1945 saved_seconds = yourtm.tm_sec;
1946 yourtm.tm_sec = SECSPERMIN - 1;
1948 saved_seconds = yourtm.tm_sec;
1952 ** Do a binary search (this works whatever time_t's type is).
1954 if (!TYPE_SIGNED(time_t)) {
1957 } else if (!TYPE_INTEGRAL(time_t)) {
1958 if (sizeof(time_t) > sizeof(float))
1959 hi = (time_t) DBL_MAX;
1960 else hi = (time_t) FLT_MAX;
1964 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
1969 t.tv_sec = lo / 2 + hi / 2;
1972 else if (t.tv_sec > hi)
1974 if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
1976 ** Assume that t is too extreme to be represented in
1977 ** a struct ast_tm; arrange things so that it is less
1978 ** extreme on the next pass.
1980 dir = (t.tv_sec > 0) ? 1 : -1;
1981 } else dir = tmcomp(&mytm, &yourtm);
1983 if (t.tv_sec == lo) {
1988 } else if (t.tv_sec == hi) {
2001 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
2004 ** Right time, wrong type.
2005 ** Hunt for right time, right type.
2006 ** It's okay to guess wrong since the guess
2010 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
2012 for (i = sp->typecnt - 1; i >= 0; --i) {
2013 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
2015 for (j = sp->typecnt - 1; j >= 0; --j) {
2016 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
2018 newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff -
2019 sp->ttis[i].tt_gmtoff;
2020 if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
2022 if (tmcomp(&mytm, &yourtm) != 0)
2024 if (mytm.tm_isdst != yourtm.tm_isdst)
2036 newt.tv_sec = t.tv_sec + saved_seconds;
2037 if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0))
2039 t.tv_sec = newt.tv_sec;
2040 if ((*funcp)(&t, offset, tmp, sp))
2045 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)
2050 ** First try without normalization of seconds
2051 ** (in case tm_sec contains a value associated with a leap second).
2052 ** If that fails, try with normalization of seconds.
2054 t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
2055 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
2058 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)
2062 int sameind, otherind;
2065 int seen[TZ_MAX_TYPES];
2066 int types[TZ_MAX_TYPES];
2069 if (tmp->tm_isdst > 1)
2071 t = time2(tmp, funcp, offset, &okay, sp);
2074 ** PCTS code courtesy Grant Sullivan.
2078 if (tmp->tm_isdst < 0)
2079 tmp->tm_isdst = 0; /* reset to std and try again */
2080 #endif /* defined PCTS */
2082 if (okay || tmp->tm_isdst < 0)
2084 #endif /* !defined PCTS */
2086 ** We're supposed to assume that somebody took a time of one type
2087 ** and did some math on it that yielded a "struct ast_tm" that's bad.
2088 ** We try to divine the type they started from and adjust to the
2093 for (i = 0; i < sp->typecnt; ++i)
2096 for (i = sp->timecnt - 1; i >= 0; --i)
2097 if (!seen[sp->types[i]]) {
2098 seen[sp->types[i]] = TRUE;
2099 types[nseen++] = sp->types[i];
2101 for (sameind = 0; sameind < nseen; ++sameind) {
2102 samei = types[sameind];
2103 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2105 for (otherind = 0; otherind < nseen; ++otherind) {
2106 otheri = types[otherind];
2107 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2109 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
2110 sp->ttis[samei].tt_gmtoff;
2111 tmp->tm_isdst = !tmp->tm_isdst;
2112 t = time2(tmp, funcp, offset, &okay, sp);
2115 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
2116 sp->ttis[samei].tt_gmtoff;
2117 tmp->tm_isdst = !tmp->tm_isdst;
2123 struct timeval ast_mktime(struct ast_tm *tmp, const char *zone)
2125 const struct state *sp;
2126 if (!(sp = ast_tzset(zone)))
2128 return time1(tmp, localsub, 0L, sp);
2131 int ast_strftime(char *buf, size_t len, const char *tmp, const struct ast_tm *tm)
2133 size_t fmtlen = strlen(tmp) + 1;
2134 char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt;
2135 int decimals = -1, i, res;
2140 for (; *tmp; tmp++) {
2151 decimals = tmp[1] - '0';
2154 case 'q': /* Milliseconds */
2158 /* Juggle some memory to fit the item */
2159 newfmt = ast_realloc(format, fmtlen + decimals);
2164 fptr = fptr - format + newfmt;
2168 /* Reduce the fraction of time to the accuracy needed */
2169 for (i = 6, fraction = tm->tm_usec; i > decimals; i--)
2171 fptr += sprintf(fptr, "%0*ld", decimals, fraction);
2173 /* Reset, in case more than one 'q' specifier exists */
2181 defcase: *fptr++ = *tmp;
2185 res = (int)strftime(buf, len, format, (struct tm *)tm);
2190 char *ast_strptime(const char *s, const char *format, struct ast_tm *tm)
2192 struct tm tm2 = { 0, };
2193 char *res = strptime(s, format, &tm2);
2194 memcpy(tm, &tm2, sizeof(*tm));
2196 /* strptime(3) doesn't set .tm_isdst correctly, so to force ast_mktime(3)
2197 * to deal with it correctly, we set it to -1. */