Just in case of a race, send the signal on interrupt.
[asterisk/asterisk.git] / main / stdtime / localtime.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
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).
10  *
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.
14  *
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.
20  *
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.
24  */
25
26 /*! \file
27  *
28  * Multi-timezone Localtime code
29  *
30  * The original source from this file may be obtained from ftp://elsie.nci.nih.gov/pub/
31  */
32
33 /*
34 ** This file is in the public domain, so clarified as of
35 ** 1996-06-05 by Arthur David Olson.
36 */
37
38 /*
39 ** Leap second handling from Bradley White.
40 ** POSIX-style TZ environment variable handling from Guy Harris.
41 */
42
43 /* #define DEBUG */
44
45 /*LINTLIBRARY*/
46
47 #include "asterisk.h"
48
49 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
50
51 #include <sys/stat.h>
52 #include <fcntl.h>
53 #include <float.h>
54 #ifdef HAVE_INOTIFY
55 #include <sys/inotify.h>
56 #endif
57
58 #include "private.h"
59 #include "tzfile.h"
60
61 #include "asterisk/lock.h"
62 #include "asterisk/localtime.h"
63 #include "asterisk/strings.h"
64 #include "asterisk/linkedlists.h"
65 #include "asterisk/utils.h"
66
67 #ifndef lint
68 #ifndef NOID
69 static char     __attribute__((unused)) elsieid[] = "@(#)localtime.c    8.5";
70 #endif /* !defined NOID */
71 #endif /* !defined lint */
72
73 #ifndef TZ_ABBR_MAX_LEN
74 #define TZ_ABBR_MAX_LEN 16
75 #endif /* !defined TZ_ABBR_MAX_LEN */
76
77 #ifndef TZ_ABBR_CHAR_SET
78 #define TZ_ABBR_CHAR_SET \
79         "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
80 #endif /* !defined TZ_ABBR_CHAR_SET */
81
82 #ifndef TZ_ABBR_ERR_CHAR
83 #define TZ_ABBR_ERR_CHAR        '_'
84 #endif /* !defined TZ_ABBR_ERR_CHAR */
85
86 /*
87 ** SunOS 4.1.1 headers lack O_BINARY.
88 */
89
90 #ifdef O_BINARY
91 #define OPEN_MODE       (O_RDONLY | O_BINARY)
92 #endif /* defined O_BINARY */
93 #ifndef O_BINARY
94 #define OPEN_MODE       O_RDONLY
95 #endif /* !defined O_BINARY */
96
97 static const char       gmt[] = "GMT";
98 static const struct timeval WRONG = { 0, 0 };
99
100 /*! \note
101  * The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
102  * We default to US rules as of 1999-08-17.
103  * POSIX 1003.1 section 8.1.1 says that the default DST rules are
104  * implementation dependent; for historical reasons, US rules are a
105  * common default.
106  */
107 #ifndef TZDEFRULESTRING
108 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
109 #endif /* !defined TZDEFDST */
110
111 /*!< \brief time type information */
112 struct ttinfo {                         /* time type information */
113         long            tt_gmtoff;      /* UTC offset in seconds */
114         int             tt_isdst;       /* used to set tm_isdst */
115         int             tt_abbrind;     /* abbreviation list index */
116         int             tt_ttisstd;     /* TRUE if transition is std time */
117         int             tt_ttisgmt;     /* TRUE if transition is UTC */
118 };
119
120 /*! \brief leap second information */
121 struct lsinfo {                         /* leap second information */
122         time_t          ls_trans;       /* transition time */
123         long            ls_corr;        /* correction to apply */
124 };
125
126 #define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
127
128 #ifdef TZNAME_MAX
129 #define MY_TZNAME_MAX   TZNAME_MAX
130 #endif /* defined TZNAME_MAX */
131 #ifndef TZNAME_MAX
132 #define MY_TZNAME_MAX   255
133 #endif /* !defined TZNAME_MAX */
134 #ifndef TZ_STRLEN_MAX
135 #define TZ_STRLEN_MAX   255
136 #endif /* !defined TZ_STRLEN_MAX */
137
138 struct state {
139         /*! Name of the file that this references */
140         char    name[TZ_STRLEN_MAX + 1];
141         int             leapcnt;
142         int             timecnt;
143         int             typecnt;
144         int             charcnt;
145         int             goback;
146         int             goahead;
147         time_t          ats[TZ_MAX_TIMES];
148         unsigned char   types[TZ_MAX_TIMES];
149         struct ttinfo   ttis[TZ_MAX_TYPES];
150         char            chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
151                                 (2 * (MY_TZNAME_MAX + 1)))];
152         struct lsinfo   lsis[TZ_MAX_LEAPS];
153 #ifdef HAVE_INOTIFY
154         int wd[2];
155 #else
156         time_t  mtime[2];
157 #endif
158         AST_LIST_ENTRY(state) list;
159 };
160
161 struct rule {
162         int             r_type;         /* type of rule--see below */
163         int             r_day;          /* day number of rule */
164         int             r_week;         /* week number of rule */
165         int             r_mon;          /* month number of rule */
166         long            r_time;         /* transition time of rule */
167 };
168
169 #define JULIAN_DAY              0       /* Jn - Julian day */
170 #define DAY_OF_YEAR             1       /* n - day of year */
171 #define MONTH_NTH_DAY_OF_WEEK   2       /* Mm.n.d - month, week, day of week */
172
173 /*
174 ** Prototypes for static functions.
175 */
176
177 static long             detzcode P((const char * codep));
178 static time_t           detzcode64 P((const char * codep));
179 static int              differ_by_repeat P((time_t t1, time_t t0));
180 static const char *     getzname P((const char * strp));
181 static const char *     getqzname P((const char * strp, const int delim));
182 static const char *     getnum P((const char * strp, int * nump, int min,
183                                 int max));
184 static const char *     getsecs P((const char * strp, long * secsp));
185 static const char *     getoffset P((const char * strp, long * offsetp));
186 static const char *     getrule P((const char * strp, struct rule * rulep));
187 static int              gmtload P((struct state * sp));
188 static struct ast_tm *  gmtsub P((const struct timeval * timep, long offset,
189                                 struct ast_tm * tmp));
190 static struct ast_tm *  localsub P((const struct timeval * timep, long offset,
191                                 struct ast_tm * tmp, const struct state *sp));
192 static int              increment_overflow P((int * number, int delta));
193 static int              leaps_thru_end_of P((int y));
194 static int              long_increment_overflow P((long * number, int delta));
195 static int              long_normalize_overflow P((long * tensptr,
196                                 int * unitsptr, const int base));
197 static int              normalize_overflow P((int * tensptr, int * unitsptr,
198                                 const int base));
199 static struct timeval   time1 P((struct ast_tm * tmp,
200                                 struct ast_tm * (*funcp) P((const struct timeval *,
201                                 long, struct ast_tm *, const struct state *sp)),
202                                 long offset, const struct state *sp));
203 static struct timeval   time2 P((struct ast_tm *tmp,
204                                 struct ast_tm * (*funcp) P((const struct timeval *,
205                                 long, struct ast_tm*, const struct state *sp)),
206                                 long offset, int * okayp, const struct state *sp));
207 static struct timeval   time2sub P((struct ast_tm *tmp,
208                                 struct ast_tm * (*funcp) (const struct timeval *,
209                                 long, struct ast_tm*, const struct state *sp),
210                                 long offset, int * okayp, int do_norm_secs, const struct state *sp));
211 static struct ast_tm *  timesub P((const struct timeval * timep, long offset,
212                                 const struct state * sp, struct ast_tm * tmp));
213 static int              tmcomp P((const struct ast_tm * atmp,
214                                 const struct ast_tm * btmp));
215 static time_t           transtime P((time_t janfirst, int year,
216                                 const struct rule * rulep, long offset));
217 static int              tzload P((const char * name, struct state * sp,
218                                 int doextend));
219 static int              tzparse P((const char * name, struct state * sp,
220                                 int lastditch));
221
222 static AST_LIST_HEAD_STATIC(zonelist, state);
223
224 #ifndef TZ_STRLEN_MAX
225 #define TZ_STRLEN_MAX 255
226 #endif /* !defined TZ_STRLEN_MAX */
227
228 static pthread_t inotify_thread = AST_PTHREADT_NULL;
229 static ast_cond_t initialization;
230 static ast_mutex_t initialization_lock;
231 #ifdef HAVE_INOTIFY
232 static int inotify_fd = -1;
233
234 static void *inotify_daemon(void *data)
235 {
236         struct {
237                 struct inotify_event iev;
238                 char name[FILENAME_MAX + 1];
239         } buf;
240         ssize_t res;
241         struct state *cur;
242
243         inotify_fd = inotify_init();
244
245         ast_mutex_lock(&initialization_lock);
246         ast_cond_broadcast(&initialization);
247         ast_mutex_unlock(&initialization_lock);
248
249         if (inotify_fd < 0) {
250                 ast_log(LOG_ERROR, "Cannot initialize file notification service: %s (%d)\n", strerror(errno), errno);
251                 inotify_thread = AST_PTHREADT_NULL;
252                 return NULL;
253         }
254
255         for (;/*ever*/;) {
256                 /* This read should block, most of the time. */
257                 if ((res = read(inotify_fd, &buf, sizeof(buf))) < sizeof(buf.iev) && res > 0) {
258                         /* This should never happen */
259                         ast_log(LOG_ERROR, "Inotify read less than a full event (%zd < %zd)?!!\n", res, sizeof(buf.iev));
260                         break;
261                 } else if (res < 0) {
262                         if (errno == EINTR || errno == EAGAIN) {
263                                 /* If read fails, try again */
264                                 AST_LIST_LOCK(&zonelist);
265                                 ast_cond_broadcast(&initialization);
266                                 AST_LIST_UNLOCK(&zonelist);
267                                 continue;
268                         }
269                         /* Sanity check -- this should never happen, either */
270                         ast_log(LOG_ERROR, "Inotify failed: %s\n", strerror(errno));
271                         break;
272                 }
273                 AST_LIST_LOCK(&zonelist);
274                 AST_LIST_TRAVERSE_SAFE_BEGIN(&zonelist, cur, list) {
275                         if (cur->wd[0] == buf.iev.wd || cur->wd[1] == buf.iev.wd) {
276                                 AST_LIST_REMOVE_CURRENT(list);
277                                 ast_free(cur);
278                                 break;
279                         }
280                 }
281                 AST_LIST_TRAVERSE_SAFE_END
282                 ast_cond_broadcast(&initialization);
283                 AST_LIST_UNLOCK(&zonelist);
284         }
285         close(inotify_fd);
286         inotify_thread = AST_PTHREADT_NULL;
287         return NULL;
288 }
289
290 static void add_notify(struct state *sp, const char *path)
291 {
292         if (inotify_thread == AST_PTHREADT_NULL) {
293                 ast_cond_init(&initialization, NULL);
294                 ast_mutex_init(&initialization_lock);
295                 ast_mutex_lock(&initialization_lock);
296                 if (!(ast_pthread_create_background(&inotify_thread, NULL, inotify_daemon, NULL))) {
297                         /* Give the thread a chance to initialize */
298                         ast_cond_wait(&initialization, &initialization_lock);
299                 } else {
300                         ast_log(LOG_ERROR, "Unable to start notification thread\n");
301                         ast_mutex_unlock(&initialization_lock);
302                         return;
303                 }
304                 ast_mutex_unlock(&initialization_lock);
305         }
306
307         if (inotify_fd > -1) {
308                 char fullpath[FILENAME_MAX + 1] = "";
309                 if (readlink(path, fullpath, sizeof(fullpath) - 1) != -1) {
310                         /* If file the symlink points to changes */
311                         sp->wd[1] = inotify_add_watch(inotify_fd, fullpath, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE );
312                 } else {
313                         sp->wd[1] = -1;
314                 }
315                 /* or if the symlink itself changes (or the real file is here, if path is not a symlink) */
316                 sp->wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE
317 #ifdef IN_DONT_FOLLOW   /* Only defined in glibc 2.5 and above */
318                         | IN_DONT_FOLLOW
319 #endif
320                 );
321         }
322 }
323 #else
324 static void *notify_daemon(void *data)
325 {
326         struct stat st, lst;
327         struct state *cur;
328         struct timespec sixty_seconds = { 60, 0 };
329
330         ast_mutex_lock(&initialization_lock);
331         ast_cond_broadcast(&initialization);
332         ast_mutex_unlock(&initialization_lock);
333
334         for (;/*ever*/;) {
335                 char            fullname[FILENAME_MAX + 1];
336
337                 nanosleep(&sixty_seconds, NULL);
338                 AST_LIST_LOCK(&zonelist);
339                 AST_LIST_TRAVERSE_SAFE_BEGIN(&zonelist, cur, list) {
340                         char *name = cur->name;
341
342                         if (name[0] == ':')
343                                 ++name;
344                         if (name[0] != '/') {
345                                 (void) strcpy(fullname, TZDIR "/");
346                                 (void) strcat(fullname, name);
347                                 name = fullname;
348                         }
349                         stat(name, &st);
350                         lstat(name, &lst);
351                         if (st.st_mtime > cur->mtime[0] || lst.st_mtime > cur->mtime[1]) {
352                                 ast_log(LOG_NOTICE, "Removing cached TZ entry '%s' because underlying file changed.\n", name);
353                                 AST_LIST_REMOVE_CURRENT(list);
354                                 ast_free(cur);
355                                 continue;
356                         }
357                 }
358                 AST_LIST_TRAVERSE_SAFE_END
359                 ast_cond_broadcast(&initialization);
360                 AST_LIST_UNLOCK(&zonelist);
361         }
362         inotify_thread = AST_PTHREADT_NULL;
363         return NULL;
364 }
365
366 static void add_notify(struct state *sp, const char *path)
367 {
368         struct stat st;
369
370         if (inotify_thread == AST_PTHREADT_NULL) {
371                 ast_cond_init(&initialization, NULL);
372                 ast_mutex_init(&initialization_lock);
373                 ast_mutex_lock(&initialization_lock);
374                 if (!(ast_pthread_create_background(&inotify_thread, NULL, notify_daemon, NULL))) {
375                         /* Give the thread a chance to initialize */
376                         ast_cond_wait(&initialization, &initialization_lock);
377                 }
378                 ast_mutex_unlock(&initialization_lock);
379         }
380
381         stat(path, &st);
382         sp->mtime[0] = st.st_mtime;
383         lstat(path, &st);
384         sp->mtime[1] = st.st_mtime;
385 }
386 #endif
387
388 void ast_localtime_wakeup_monitor(void)
389 {
390         if (inotify_thread != AST_PTHREADT_NULL) {
391                 AST_LIST_LOCK(&zonelist);
392                 pthread_kill(inotify_thread, SIGURG);
393                 ast_cond_wait(&initialization, &(&zonelist)->lock);
394                 AST_LIST_UNLOCK(&zonelist);
395         }
396 }
397
398 /*! \note
399 ** Section 4.12.3 of X3.159-1989 requires that
400 **      Except for the strftime function, these functions [asctime,
401 **      ctime, gmtime, localtime] return values in one of two static
402 **      objects: a broken-down time structure and an array of char.
403 ** Thanks to Paul Eggert for noting this.
404 */
405
406 static long detzcode(const char * const codep)
407 {
408         long    result;
409         int     i;
410
411         result = (codep[0] & 0x80) ? ~0L : 0;
412         for (i = 0; i < 4; ++i)
413                 result = (result << 8) | (codep[i] & 0xff);
414         return result;
415 }
416
417 static time_t detzcode64(const char * const codep)
418 {
419         time_t  result;
420         int     i;
421
422         result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
423         for (i = 0; i < 8; ++i)
424                 result = result * 256 + (codep[i] & 0xff);
425         return result;
426 }
427
428 static int differ_by_repeat(const time_t t1, const time_t t0)
429 {
430         const long long at1 = t1, at0 = t0;
431         if (TYPE_INTEGRAL(time_t) &&
432                 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
433                         return 0;
434         return at1 - at0 == SECSPERREPEAT;
435 }
436
437 static int tzload(const char *name, struct state * const sp, const int doextend)
438 {
439         const char *            p;
440         int                     i;
441         int                     fid;
442         int                     stored;
443         int                     nread;
444         union {
445                 struct tzhead   tzhead;
446                 char            buf[2 * sizeof(struct tzhead) +
447                                         2 * sizeof *sp +
448                                         4 * TZ_MAX_TIMES];
449         } u;
450
451         if (name == NULL && (name = TZDEFAULT) == NULL)
452                 return -1;
453         {
454                 int     doaccess;
455                 /*
456                 ** Section 4.9.1 of the C standard says that
457                 ** "FILENAME_MAX expands to an integral constant expression
458                 ** that is the size needed for an array of char large enough
459                 ** to hold the longest file name string that the implementation
460                 ** guarantees can be opened."
461                 */
462                 char            fullname[FILENAME_MAX + 1];
463
464                 if (name[0] == ':')
465                         ++name;
466                 doaccess = name[0] == '/';
467                 if (!doaccess) {
468                         if ((p = TZDIR) == NULL)
469                                 return -1;
470                         if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
471                                 return -1;
472                         (void) strcpy(fullname, p);
473                         (void) strcat(fullname, "/");
474                         (void) strcat(fullname, name);
475                         /*
476                         ** Set doaccess if '.' (as in "../") shows up in name.
477                         */
478                         if (strchr(name, '.') != NULL)
479                                 doaccess = TRUE;
480                         name = fullname;
481                 }
482                 if (doaccess && access(name, R_OK) != 0)
483                         return -1;
484                 if ((fid = open(name, OPEN_MODE)) == -1)
485                         return -1;
486                 add_notify(sp, name);
487         }
488         nread = read(fid, u.buf, sizeof u.buf);
489         if (close(fid) < 0 || nread <= 0)
490                 return -1;
491         for (stored = 4; stored <= 8; stored *= 2) {
492                 int             ttisstdcnt;
493                 int             ttisgmtcnt;
494
495                 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
496                 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
497                 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
498                 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
499                 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
500                 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
501                 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
502                 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
503                         sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
504                         sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
505                         sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
506                         (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
507                         (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
508                                 return -1;
509                 if (nread - (p - u.buf) <
510                         sp->timecnt * stored +          /* ats */
511                         sp->timecnt +                   /* types */
512                         sp->typecnt * 6 +               /* ttinfos */
513                         sp->charcnt +                   /* chars */
514                         sp->leapcnt * (stored + 4) +    /* lsinfos */
515                         ttisstdcnt +                    /* ttisstds */
516                         ttisgmtcnt)                     /* ttisgmts */
517                                 return -1;
518                 for (i = 0; i < sp->timecnt; ++i) {
519                         sp->ats[i] = (stored == 4) ?
520                                 detzcode(p) : detzcode64(p);
521                         p += stored;
522                 }
523                 for (i = 0; i < sp->timecnt; ++i) {
524                         sp->types[i] = (unsigned char) *p++;
525                         if (sp->types[i] >= sp->typecnt)
526                                 return -1;
527                 }
528                 for (i = 0; i < sp->typecnt; ++i) {
529                         struct ttinfo * ttisp;
530
531                         ttisp = &sp->ttis[i];
532                         ttisp->tt_gmtoff = detzcode(p);
533                         p += 4;
534                         ttisp->tt_isdst = (unsigned char) *p++;
535                         if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
536                                 return -1;
537                         ttisp->tt_abbrind = (unsigned char) *p++;
538                         if (ttisp->tt_abbrind < 0 ||
539                                 ttisp->tt_abbrind > sp->charcnt)
540                                         return -1;
541                 }
542                 for (i = 0; i < sp->charcnt; ++i)
543                         sp->chars[i] = *p++;
544                 sp->chars[i] = '\0';    /* ensure '\0' at end */
545                 for (i = 0; i < sp->leapcnt; ++i) {
546                         struct lsinfo * lsisp;
547
548                         lsisp = &sp->lsis[i];
549                         lsisp->ls_trans = (stored == 4) ?
550                                 detzcode(p) : detzcode64(p);
551                         p += stored;
552                         lsisp->ls_corr = detzcode(p);
553                         p += 4;
554                 }
555                 for (i = 0; i < sp->typecnt; ++i) {
556                         struct ttinfo * ttisp;
557
558                         ttisp = &sp->ttis[i];
559                         if (ttisstdcnt == 0)
560                                 ttisp->tt_ttisstd = FALSE;
561                         else {
562                                 ttisp->tt_ttisstd = *p++;
563                                 if (ttisp->tt_ttisstd != TRUE &&
564                                         ttisp->tt_ttisstd != FALSE)
565                                                 return -1;
566                         }
567                 }
568                 for (i = 0; i < sp->typecnt; ++i) {
569                         struct ttinfo * ttisp;
570
571                         ttisp = &sp->ttis[i];
572                         if (ttisgmtcnt == 0)
573                                 ttisp->tt_ttisgmt = FALSE;
574                         else {
575                                 ttisp->tt_ttisgmt = *p++;
576                                 if (ttisp->tt_ttisgmt != TRUE &&
577                                         ttisp->tt_ttisgmt != FALSE)
578                                                 return -1;
579                         }
580                 }
581                 /*
582                 ** Out-of-sort ats should mean we're running on a
583                 ** signed time_t system but using a data file with
584                 ** unsigned values (or vice versa).
585                 */
586                 for (i = 0; i < sp->timecnt - 2; ++i)
587                         if (sp->ats[i] > sp->ats[i + 1]) {
588                                 ++i;
589                                 if (TYPE_SIGNED(time_t)) {
590                                         /*
591                                         ** Ignore the end (easy).
592                                         */
593                                         sp->timecnt = i;
594                                 } else {
595                                         /*
596                                         ** Ignore the beginning (harder).
597                                         */
598                                         int     j;
599
600                                         for (j = 0; j + i < sp->timecnt; ++j) {
601                                                 sp->ats[j] = sp->ats[j + i];
602                                                 sp->types[j] = sp->types[j + i];
603                                         }
604                                         sp->timecnt = j;
605                                 }
606                                 break;
607                         }
608                 /*
609                 ** If this is an old file, we're done.
610                 */
611                 if (u.tzhead.tzh_version[0] == '\0')
612                         break;
613                 nread -= p - u.buf;
614                 for (i = 0; i < nread; ++i)
615                         u.buf[i] = p[i];
616                 /*
617                 ** If this is a narrow integer time_t system, we're done.
618                 */
619                 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
620                         break;
621         }
622         if (doextend && nread > 2 &&
623                 u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
624                 sp->typecnt + 2 <= TZ_MAX_TYPES) {
625                         struct state    ts;
626                         int     result;
627
628                         u.buf[nread - 1] = '\0';
629                         result = tzparse(&u.buf[1], &ts, FALSE);
630                         if (result == 0 && ts.typecnt == 2 &&
631                                 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
632                                         for (i = 0; i < 2; ++i)
633                                                 ts.ttis[i].tt_abbrind +=
634                                                         sp->charcnt;
635                                         for (i = 0; i < ts.charcnt; ++i)
636                                                 sp->chars[sp->charcnt++] =
637                                                         ts.chars[i];
638                                         i = 0;
639                                         while (i < ts.timecnt &&
640                                                 ts.ats[i] <=
641                                                 sp->ats[sp->timecnt - 1])
642                                                         ++i;
643                                         while (i < ts.timecnt &&
644                                             sp->timecnt < TZ_MAX_TIMES) {
645                                                 sp->ats[sp->timecnt] =
646                                                         ts.ats[i];
647                                                 sp->types[sp->timecnt] =
648                                                         sp->typecnt +
649                                                         ts.types[i];
650                                                 ++sp->timecnt;
651                                                 ++i;
652                                         }
653                                         sp->ttis[sp->typecnt++] = ts.ttis[0];
654                                         sp->ttis[sp->typecnt++] = ts.ttis[1];
655                         }
656         }
657         i = 2 * YEARSPERREPEAT;
658         sp->goback = sp->goahead = sp->timecnt > i;
659         sp->goback = sp->goback && sp->types[i] == sp->types[0] &&
660                 differ_by_repeat(sp->ats[i], sp->ats[0]);
661         sp->goahead = sp->goahead &&
662                 sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
663                 differ_by_repeat(sp->ats[sp->timecnt - 1],
664                          sp->ats[sp->timecnt - 1 - i]);
665         return 0;
666 }
667
668 static const int        mon_lengths[2][MONSPERYEAR] = {
669         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
670         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
671 };
672
673 static const int        year_lengths[2] = {
674         DAYSPERNYEAR, DAYSPERLYEAR
675 };
676
677 /*! \brief
678 ** Given a pointer into a time zone string, scan until a character that is not
679 ** a valid character in a zone name is found. Return a pointer to that
680 ** character.
681 */
682
683 static const char * getzname(const char *strp)
684 {
685         char    c;
686
687         while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
688                 c != '+')
689                         ++strp;
690         return strp;
691 }
692
693 /*! \brief
694 ** Given a pointer into an extended time zone string, scan until the ending
695 ** delimiter of the zone name is located. Return a pointer to the delimiter.
696 **
697 ** As with getzname above, the legal character set is actually quite
698 ** restricted, with other characters producing undefined results.
699 ** We don't do any checking here; checking is done later in common-case code.
700 */
701
702 static const char * getqzname(const char *strp, const int delim)
703 {
704         int     c;
705
706         while ((c = *strp) != '\0' && c != delim)
707                 ++strp;
708         return strp;
709 }
710
711 /*! \brief
712 ** Given a pointer into a time zone string, extract a number from that string.
713 ** Check that the number is within a specified range; if it is not, return
714 ** NULL.
715 ** Otherwise, return a pointer to the first character not part of the number.
716 */
717
718 static const char *getnum(const char *strp, int *nump, const int min, const int max)
719 {
720         char    c;
721         int     num;
722
723         if (strp == NULL || !is_digit(c = *strp))
724                 return NULL;
725         num = 0;
726         do {
727                 num = num * 10 + (c - '0');
728                 if (num > max)
729                         return NULL;    /* illegal value */
730                 c = *++strp;
731         } while (is_digit(c));
732         if (num < min)
733                 return NULL;            /* illegal value */
734         *nump = num;
735         return strp;
736 }
737
738 /*! \brief
739 ** Given a pointer into a time zone string, extract a number of seconds,
740 ** in hh[:mm[:ss]] form, from the string.
741 ** If any error occurs, return NULL.
742 ** Otherwise, return a pointer to the first character not part of the number
743 ** of seconds.
744 */
745
746 static const char *getsecs(const char *strp, long * const secsp)
747 {
748         int     num;
749
750         /*
751         ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
752         ** "M10.4.6/26", which does not conform to Posix,
753         ** but which specifies the equivalent of
754         ** ``02:00 on the first Sunday on or after 23 Oct''.
755         */
756         strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
757         if (strp == NULL)
758                 return NULL;
759         *secsp = num * (long) SECSPERHOUR;
760         if (*strp == ':') {
761                 ++strp;
762                 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
763                 if (strp == NULL)
764                         return NULL;
765                 *secsp += num * SECSPERMIN;
766                 if (*strp == ':') {
767                         ++strp;
768                         /* `SECSPERMIN' allows for leap seconds. */
769                         strp = getnum(strp, &num, 0, SECSPERMIN);
770                         if (strp == NULL)
771                                 return NULL;
772                         *secsp += num;
773                 }
774         }
775         return strp;
776 }
777
778 /*! \brief
779 ** Given a pointer into a time zone string, extract an offset, in
780 ** [+-]hh[:mm[:ss]] form, from the string.
781 ** If any error occurs, return NULL.
782 ** Otherwise, return a pointer to the first character not part of the time.
783 */
784
785 static const char *getoffset(const char *strp, long *offsetp)
786 {
787         int     neg = 0;
788
789         if (*strp == '-') {
790                 neg = 1;
791                 ++strp;
792         } else if (*strp == '+')
793                 ++strp;
794         strp = getsecs(strp, offsetp);
795         if (strp == NULL)
796                 return NULL;            /* illegal time */
797         if (neg)
798                 *offsetp = -*offsetp;
799         return strp;
800 }
801
802 /*! \brief
803 ** Given a pointer into a time zone string, extract a rule in the form
804 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
805 ** If a valid rule is not found, return NULL.
806 ** Otherwise, return a pointer to the first character not part of the rule.
807 */
808
809 static const char *getrule(const char *strp, struct rule *rulep)
810 {
811         if (*strp == 'J') {
812                 /*
813                 ** Julian day.
814                 */
815                 rulep->r_type = JULIAN_DAY;
816                 ++strp;
817                 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
818         } else if (*strp == 'M') {
819                 /*
820                 ** Month, week, day.
821                 */
822                 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
823                 ++strp;
824                 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
825                 if (strp == NULL)
826                         return NULL;
827                 if (*strp++ != '.')
828                         return NULL;
829                 strp = getnum(strp, &rulep->r_week, 1, 5);
830                 if (strp == NULL)
831                         return NULL;
832                 if (*strp++ != '.')
833                         return NULL;
834                 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
835         } else if (is_digit(*strp)) {
836                 /*
837                 ** Day of year.
838                 */
839                 rulep->r_type = DAY_OF_YEAR;
840                 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
841         } else  return NULL;            /* invalid format */
842         if (strp == NULL)
843                 return NULL;
844         if (*strp == '/') {
845                 /*
846                 ** Time specified.
847                 */
848                 ++strp;
849                 strp = getsecs(strp, &rulep->r_time);
850         } else  rulep->r_time = 2 * SECSPERHOUR;        /* default = 2:00:00 */
851         return strp;
852 }
853
854 /*! \brief
855 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
856 ** year, a rule, and the offset from UTC at the time that rule takes effect,
857 ** calculate the Epoch-relative time that rule takes effect.
858 */
859
860 static time_t transtime(const time_t janfirst, const int year, const struct rule *rulep, const long offset)
861 {
862         int     leapyear;
863         time_t  value;
864         int     i;
865         int             d, m1, yy0, yy1, yy2, dow;
866
867         INITIALIZE(value);
868         leapyear = isleap(year);
869         switch (rulep->r_type) {
870
871         case JULIAN_DAY:
872                 /*
873                 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
874                 ** years.
875                 ** In non-leap years, or if the day number is 59 or less, just
876                 ** add SECSPERDAY times the day number-1 to the time of
877                 ** January 1, midnight, to get the day.
878                 */
879                 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
880                 if (leapyear && rulep->r_day >= 60)
881                         value += SECSPERDAY;
882                 break;
883
884         case DAY_OF_YEAR:
885                 /*
886                 ** n - day of year.
887                 ** Just add SECSPERDAY times the day number to the time of
888                 ** January 1, midnight, to get the day.
889                 */
890                 value = janfirst + rulep->r_day * SECSPERDAY;
891                 break;
892
893         case MONTH_NTH_DAY_OF_WEEK:
894                 /*
895                 ** Mm.n.d - nth "dth day" of month m.
896                 */
897                 value = janfirst;
898                 for (i = 0; i < rulep->r_mon - 1; ++i)
899                         value += mon_lengths[leapyear][i] * SECSPERDAY;
900
901                 /*
902                 ** Use Zeller's Congruence to get day-of-week of first day of
903                 ** month.
904                 */
905                 m1 = (rulep->r_mon + 9) % 12 + 1;
906                 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
907                 yy1 = yy0 / 100;
908                 yy2 = yy0 % 100;
909                 dow = ((26 * m1 - 2) / 10 +
910                         1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
911                 if (dow < 0)
912                         dow += DAYSPERWEEK;
913
914                 /*
915                 ** "dow" is the day-of-week of the first day of the month. Get
916                 ** the day-of-month (zero-origin) of the first "dow" day of the
917                 ** month.
918                 */
919                 d = rulep->r_day - dow;
920                 if (d < 0)
921                         d += DAYSPERWEEK;
922                 for (i = 1; i < rulep->r_week; ++i) {
923                         if (d + DAYSPERWEEK >=
924                                 mon_lengths[leapyear][rulep->r_mon - 1])
925                                         break;
926                         d += DAYSPERWEEK;
927                 }
928
929                 /*
930                 ** "d" is the day-of-month (zero-origin) of the day we want.
931                 */
932                 value += d * SECSPERDAY;
933                 break;
934         }
935
936         /*
937         ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
938         ** question. To get the Epoch-relative time of the specified local
939         ** time on that day, add the transition time and the current offset
940         ** from UTC.
941         */
942         return value + rulep->r_time + offset;
943 }
944
945 /*! \note
946 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
947 ** appropriate.
948 */
949
950 static int tzparse(const char *name, struct state *sp, const int lastditch)
951 {
952         const char *                    stdname;
953         const char *                    dstname;
954         size_t                          stdlen;
955         size_t                          dstlen;
956         long                            stdoffset;
957         long                            dstoffset;
958         time_t *                atp;
959         unsigned char * typep;
960         char *                  cp;
961         int                     load_result;
962
963         INITIALIZE(dstname);
964         stdname = name;
965         if (lastditch) {
966                 stdlen = strlen(name);  /* length of standard zone name */
967                 name += stdlen;
968                 if (stdlen >= sizeof sp->chars)
969                         stdlen = (sizeof sp->chars) - 1;
970                 stdoffset = 0;
971         } else {
972                 if (*name == '<') {
973                         name++;
974                         stdname = name;
975                         name = getqzname(name, '>');
976                         if (*name != '>')
977                                 return -1;
978                         stdlen = name - stdname;
979                         name++;
980                 } else {
981                         name = getzname(name);
982                         stdlen = name - stdname;
983                 }
984                 if (*name == '\0')
985                         return -1;
986                 name = getoffset(name, &stdoffset);
987                 if (name == NULL)
988                         return -1;
989         }
990         load_result = tzload(TZDEFRULES, sp, FALSE);
991         if (load_result != 0)
992                 sp->leapcnt = 0;                /* so, we're off a little */
993         if (*name != '\0') {
994                 if (*name == '<') {
995                         dstname = ++name;
996                         name = getqzname(name, '>');
997                         if (*name != '>')
998                                 return -1;
999                         dstlen = name - dstname;
1000                         name++;
1001                 } else {
1002                         dstname = name;
1003                         name = getzname(name);
1004                         dstlen = name - dstname; /* length of DST zone name */
1005                 }
1006                 if (*name != '\0' && *name != ',' && *name != ';') {
1007                         name = getoffset(name, &dstoffset);
1008                         if (name == NULL)
1009                                 return -1;
1010                 } else  dstoffset = stdoffset - SECSPERHOUR;
1011                 if (*name == '\0' && load_result != 0)
1012                         name = TZDEFRULESTRING;
1013                 if (*name == ',' || *name == ';') {
1014                         struct rule     start;
1015                         struct rule     end;
1016                         int     year;
1017                         time_t  janfirst;
1018                         time_t          starttime;
1019                         time_t          endtime;
1020
1021                         ++name;
1022                         if ((name = getrule(name, &start)) == NULL)
1023                                 return -1;
1024                         if (*name++ != ',')
1025                                 return -1;
1026                         if ((name = getrule(name, &end)) == NULL)
1027                                 return -1;
1028                         if (*name != '\0')
1029                                 return -1;
1030                         sp->typecnt = 2;        /* standard time and DST */
1031                         /*
1032                         ** Two transitions per year, from EPOCH_YEAR forward.
1033                         */
1034                         sp->ttis[0].tt_gmtoff = -dstoffset;
1035                         sp->ttis[0].tt_isdst = 1;
1036                         sp->ttis[0].tt_abbrind = stdlen + 1;
1037                         sp->ttis[1].tt_gmtoff = -stdoffset;
1038                         sp->ttis[1].tt_isdst = 0;
1039                         sp->ttis[1].tt_abbrind = 0;
1040                         atp = sp->ats;
1041                         typep = sp->types;
1042                         janfirst = 0;
1043                         sp->timecnt = 0;
1044                         for (year = EPOCH_YEAR;
1045                             sp->timecnt + 2 <= TZ_MAX_TIMES;
1046                             ++year) {
1047                                 time_t  newfirst;
1048
1049                                 starttime = transtime(janfirst, year, &start,
1050                                         stdoffset);
1051                                 endtime = transtime(janfirst, year, &end,
1052                                         dstoffset);
1053                                 if (starttime > endtime) {
1054                                         *atp++ = endtime;
1055                                         *typep++ = 1;   /* DST ends */
1056                                         *atp++ = starttime;
1057                                         *typep++ = 0;   /* DST begins */
1058                                 } else {
1059                                         *atp++ = starttime;
1060                                         *typep++ = 0;   /* DST begins */
1061                                         *atp++ = endtime;
1062                                         *typep++ = 1;   /* DST ends */
1063                                 }
1064                                 sp->timecnt += 2;
1065                                 newfirst = janfirst;
1066                                 newfirst += year_lengths[isleap(year)] *
1067                                         SECSPERDAY;
1068                                 if (newfirst <= janfirst)
1069                                         break;
1070                                 janfirst = newfirst;
1071                         }
1072                 } else {
1073                         long    theirstdoffset;
1074                         long    theirdstoffset;
1075                         long    theiroffset;
1076                         int     isdst;
1077                         int     i;
1078                         int     j;
1079
1080                         if (*name != '\0')
1081                                 return -1;
1082                         /*
1083                         ** Initial values of theirstdoffset and theirdstoffset.
1084                         */
1085                         theirstdoffset = 0;
1086                         for (i = 0; i < sp->timecnt; ++i) {
1087                                 j = sp->types[i];
1088                                 if (!sp->ttis[j].tt_isdst) {
1089                                         theirstdoffset =
1090                                                 -sp->ttis[j].tt_gmtoff;
1091                                         break;
1092                                 }
1093                         }
1094                         theirdstoffset = 0;
1095                         for (i = 0; i < sp->timecnt; ++i) {
1096                                 j = sp->types[i];
1097                                 if (sp->ttis[j].tt_isdst) {
1098                                         theirdstoffset =
1099                                                 -sp->ttis[j].tt_gmtoff;
1100                                         break;
1101                                 }
1102                         }
1103                         /*
1104                         ** Initially we're assumed to be in standard time.
1105                         */
1106                         isdst = FALSE;
1107                         theiroffset = theirstdoffset;
1108                         /*
1109                         ** Now juggle transition times and types
1110                         ** tracking offsets as you do.
1111                         */
1112                         for (i = 0; i < sp->timecnt; ++i) {
1113                                 j = sp->types[i];
1114                                 sp->types[i] = sp->ttis[j].tt_isdst;
1115                                 if (sp->ttis[j].tt_ttisgmt) {
1116                                         /* No adjustment to transition time */
1117                                 } else {
1118                                         /*
1119                                         ** If summer time is in effect, and the
1120                                         ** transition time was not specified as
1121                                         ** standard time, add the summer time
1122                                         ** offset to the transition time;
1123                                         ** otherwise, add the standard time
1124                                         ** offset to the transition time.
1125                                         */
1126                                         /*
1127                                         ** Transitions from DST to DDST
1128                                         ** will effectively disappear since
1129                                         ** POSIX provides for only one DST
1130                                         ** offset.
1131                                         */
1132                                         if (isdst && !sp->ttis[j].tt_ttisstd) {
1133                                                 sp->ats[i] += dstoffset -
1134                                                         theirdstoffset;
1135                                         } else {
1136                                                 sp->ats[i] += stdoffset -
1137                                                         theirstdoffset;
1138                                         }
1139                                 }
1140                                 theiroffset = -sp->ttis[j].tt_gmtoff;
1141                                 if (sp->ttis[j].tt_isdst)
1142                                         theirdstoffset = theiroffset;
1143                                 else    theirstdoffset = theiroffset;
1144                         }
1145                         /*
1146                         ** Finally, fill in ttis.
1147                         ** ttisstd and ttisgmt need not be handled.
1148                         */
1149                         sp->ttis[0].tt_gmtoff = -stdoffset;
1150                         sp->ttis[0].tt_isdst = FALSE;
1151                         sp->ttis[0].tt_abbrind = 0;
1152                         sp->ttis[1].tt_gmtoff = -dstoffset;
1153                         sp->ttis[1].tt_isdst = TRUE;
1154                         sp->ttis[1].tt_abbrind = stdlen + 1;
1155                         sp->typecnt = 2;
1156                 }
1157         } else {
1158                 dstlen = 0;
1159                 sp->typecnt = 1;                /* only standard time */
1160                 sp->timecnt = 0;
1161                 sp->ttis[0].tt_gmtoff = -stdoffset;
1162                 sp->ttis[0].tt_isdst = 0;
1163                 sp->ttis[0].tt_abbrind = 0;
1164         }
1165         sp->charcnt = stdlen + 1;
1166         if (dstlen != 0)
1167                 sp->charcnt += dstlen + 1;
1168         if ((size_t) sp->charcnt > sizeof sp->chars)
1169                 return -1;
1170         cp = sp->chars;
1171         (void) strncpy(cp, stdname, stdlen);
1172         cp += stdlen;
1173         *cp++ = '\0';
1174         if (dstlen != 0) {
1175                 (void) strncpy(cp, dstname, dstlen);
1176                 *(cp + dstlen) = '\0';
1177         }
1178         return 0;
1179 }
1180
1181 static int gmtload(struct state *sp)
1182 {
1183         if (tzload(gmt, sp, TRUE) != 0)
1184                 return tzparse(gmt, sp, TRUE);
1185         else
1186                 return -1;
1187 }
1188
1189 static const struct state *ast_tzset(const char *zone)
1190 {
1191         struct state *sp;
1192
1193         if (ast_strlen_zero(zone))
1194                 zone = "/etc/localtime";
1195
1196         AST_LIST_LOCK(&zonelist);
1197         AST_LIST_TRAVERSE(&zonelist, sp, list) {
1198                 if (!strcmp(sp->name, zone)) {
1199                         AST_LIST_UNLOCK(&zonelist);
1200                         return sp;
1201                 }
1202         }
1203         AST_LIST_UNLOCK(&zonelist);
1204
1205         if (!(sp = ast_calloc(1, sizeof *sp)))
1206                 return NULL;
1207
1208         if (tzload(zone, sp, TRUE) != 0) {
1209                 if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0)
1210                         (void) gmtload(sp);
1211         }
1212         ast_copy_string(sp->name, zone, sizeof(sp->name));
1213         AST_LIST_LOCK(&zonelist);
1214         AST_LIST_INSERT_TAIL(&zonelist, sp, list);
1215         AST_LIST_UNLOCK(&zonelist);
1216         return sp;
1217 }
1218
1219 /*! \note
1220 ** The easy way to behave "as if no library function calls" localtime
1221 ** is to not call it--so we drop its guts into "localsub", which can be
1222 ** freely called. (And no, the PANS doesn't require the above behavior--
1223 ** but it *is* desirable.)
1224 **
1225 ** The unused offset argument is for the benefit of mktime variants.
1226 */
1227
1228 static struct ast_tm *localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
1229 {
1230         const struct ttinfo *   ttisp;
1231         int                     i;
1232         struct ast_tm *         result;
1233         struct timeval  t;
1234         memcpy(&t, timep, sizeof(t));
1235
1236         if (sp == NULL)
1237                 return gmtsub(timep, offset, tmp);
1238         if ((sp->goback && t.tv_sec < sp->ats[0]) ||
1239                 (sp->goahead && t.tv_sec > sp->ats[sp->timecnt - 1])) {
1240                         struct timeval  newt = t;
1241                         time_t          seconds;
1242                         time_t          tcycles;
1243                         int_fast64_t    icycles;
1244
1245                         if (t.tv_sec < sp->ats[0])
1246                                 seconds = sp->ats[0] - t.tv_sec;
1247                         else    seconds = t.tv_sec - sp->ats[sp->timecnt - 1];
1248                         --seconds;
1249                         tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1250                         ++tcycles;
1251                         icycles = tcycles;
1252                         if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1253                                 return NULL;
1254                         seconds = icycles;
1255                         seconds *= YEARSPERREPEAT;
1256                         seconds *= AVGSECSPERYEAR;
1257                         if (t.tv_sec < sp->ats[0])
1258                                 newt.tv_sec += seconds;
1259                         else    newt.tv_sec -= seconds;
1260                         if (newt.tv_sec < sp->ats[0] ||
1261                                 newt.tv_sec > sp->ats[sp->timecnt - 1])
1262                                         return NULL;    /* "cannot happen" */
1263                         result = localsub(&newt, offset, tmp, sp);
1264                         if (result == tmp) {
1265                                 time_t  newy;
1266
1267                                 newy = tmp->tm_year;
1268                                 if (t.tv_sec < sp->ats[0])
1269                                         newy -= icycles * YEARSPERREPEAT;
1270                                 else
1271                                         newy += icycles * YEARSPERREPEAT;
1272                                 tmp->tm_year = newy;
1273                                 if (tmp->tm_year != newy)
1274                                         return NULL;
1275                         }
1276                         return result;
1277         }
1278         if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) {
1279                 i = 0;
1280                 while (sp->ttis[i].tt_isdst) {
1281                         if (++i >= sp->typecnt) {
1282                                 i = 0;
1283                                 break;
1284                         }
1285                 }
1286         } else {
1287                 int     lo = 1;
1288                 int     hi = sp->timecnt;
1289
1290                 while (lo < hi) {
1291                         int     mid = (lo + hi) >> 1;
1292
1293                         if (t.tv_sec < sp->ats[mid])
1294                                 hi = mid;
1295                         else
1296                                 lo = mid + 1;
1297                 }
1298                 i = (int) sp->types[lo - 1];
1299         }
1300         ttisp = &sp->ttis[i];
1301         /*
1302         ** To get (wrong) behavior that's compatible with System V Release 2.0
1303         ** you'd replace the statement below with
1304         **      t += ttisp->tt_gmtoff;
1305         **      timesub(&t, 0L, sp, tmp);
1306         */
1307         result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1308         tmp->tm_isdst = ttisp->tt_isdst;
1309 #ifndef SOLARIS /* Solaris doesn't have this element */
1310         tmp->tm_gmtoff = ttisp->tt_gmtoff;
1311 #endif
1312 #ifdef TM_ZONE
1313         tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
1314 #endif /* defined TM_ZONE */
1315         tmp->tm_usec = timep->tv_usec;
1316         return result;
1317 }
1318
1319 struct ast_tm *ast_localtime(const struct timeval *timep, struct ast_tm *tmp, const char *zone)
1320 {
1321         const struct state *sp = ast_tzset(zone);
1322         memset(tmp, 0, sizeof(*tmp));
1323         return sp ? localsub(timep, 0L, tmp, sp) : NULL;
1324 }
1325
1326 /*
1327 ** This function provides informaton about daylight savings time 
1328 ** for the given timezone.  This includes whether it can determine 
1329 ** if daylight savings is used for this timezone, the UTC times for 
1330 ** when daylight savings transitions, and the offset in seconds from 
1331 ** UTC. 
1332 */
1333
1334 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)
1335 {
1336         int i;  
1337         int transition1 = -1;
1338         int transition2 = -1;
1339         time_t          seconds;
1340         int  bounds_exceeded = 0;
1341         time_t  t = *timep;
1342         const struct state *sp;
1343         
1344         if (NULL == dst_enabled)
1345                 return;
1346         *dst_enabled = 0;
1347
1348         if (NULL == dst_start || NULL == dst_end || NULL == gmt_off)
1349                 return;
1350
1351         *gmt_off = 0; 
1352         
1353         sp = ast_tzset(zone);
1354         if (NULL == sp) 
1355                 return;
1356         
1357         /* If the desired time exceeds the bounds of the defined time transitions  
1358         * then give give up on determining DST info and simply look for gmt offset 
1359         * This requires that I adjust the given time using increments of Gregorian 
1360         * repeats to place the time within the defined time transitions in the 
1361         * timezone structure.  
1362         */
1363         if ((sp->goback && t < sp->ats[0]) ||
1364                         (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1365                 time_t          tcycles;
1366                 int_fast64_t    icycles;
1367
1368                 if (t < sp->ats[0])
1369                         seconds = sp->ats[0] - t;
1370                 else    seconds = t - sp->ats[sp->timecnt - 1];
1371                 --seconds;
1372                 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1373                 ++tcycles;
1374                 icycles = tcycles;
1375                 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1376                         return;
1377                 seconds = icycles;
1378                 seconds *= YEARSPERREPEAT;
1379                 seconds *= AVGSECSPERYEAR;
1380                 if (t < sp->ats[0])
1381                         t += seconds;
1382                 else
1383                         t -= seconds;
1384                 
1385                 if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1])
1386                         return; /* "cannot happen" */
1387
1388                 bounds_exceeded = 1;
1389         }
1390
1391         if (sp->timecnt == 0 || t < sp->ats[0]) {
1392                 /* I have no transition times or I'm before time */
1393                 *dst_enabled = 0;
1394                 /* Find where I can get gmtoff */
1395                 i = 0;
1396                 while (sp->ttis[i].tt_isdst)
1397                         if (++i >= sp->typecnt) {
1398                         i = 0;
1399                         break;
1400                         }
1401                         *gmt_off = sp->ttis[i].tt_gmtoff;
1402                         return;
1403         } 
1404
1405         for (i = 1; i < sp->timecnt; ++i) {
1406                 if (t < sp->ats[i]) {
1407                         transition1 = sp->types[i - 1];
1408                         transition2 = sp->types[i];
1409                         break;
1410                 } 
1411         }
1412         /* if I found transition times that do not bounded the given time and these correspond to 
1413                 or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */
1414         if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 ||
1415                         (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) {
1416                 *dst_enabled = 0;
1417                 *gmt_off         = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff;
1418         } else {
1419                 /* I have valid daylight savings information. */
1420                 if(sp->ttis[transition2].tt_isdst) 
1421                         *gmt_off = sp->ttis[transition1].tt_gmtoff;
1422                 else 
1423                         *gmt_off = sp->ttis[transition2].tt_gmtoff;
1424
1425                 /* If I adjusted the time earlier, indicate that the dst is invalid */
1426                 if (!bounds_exceeded) {
1427                         *dst_enabled = 1;
1428                         /* Determine which of the bounds is the start of daylight savings and which is the end */
1429                         if(sp->ttis[transition2].tt_isdst) {
1430                                 *dst_start = sp->ats[i];
1431                                 *dst_end = sp->ats[i -1];
1432                         } else {
1433                                 *dst_start = sp->ats[i -1];
1434                                 *dst_end = sp->ats[i];
1435                         }
1436                 }
1437         }       
1438         return;
1439 }
1440
1441 /*
1442 ** gmtsub is to gmtime as localsub is to localtime.
1443 */
1444
1445 static struct ast_tm *gmtsub(const struct timeval *timep, const long offset, struct ast_tm *tmp)
1446 {
1447         struct ast_tm * result;
1448         struct state *sp;
1449
1450         AST_LIST_LOCK(&zonelist);
1451         AST_LIST_TRAVERSE(&zonelist, sp, list) {
1452                 if (!strcmp(sp->name, "UTC"))
1453                         break;
1454         }
1455
1456         if (!sp) {
1457                 if (!(sp = (struct state *) ast_calloc(1, sizeof *sp)))
1458                         return NULL;
1459                 gmtload(sp);
1460                 AST_LIST_INSERT_TAIL(&zonelist, sp, list);
1461         }
1462         AST_LIST_UNLOCK(&zonelist);
1463
1464         result = timesub(timep, offset, sp, tmp);
1465 #ifdef TM_ZONE
1466         /*
1467         ** Could get fancy here and deliver something such as
1468         ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1469         ** but this is no time for a treasure hunt.
1470         */
1471         if (offset != 0)
1472                 tmp->TM_ZONE = "    ";
1473         else
1474                 tmp->TM_ZONE = sp->chars;
1475 #endif /* defined TM_ZONE */
1476         return result;
1477 }
1478
1479 /*! \brief
1480 ** Return the number of leap years through the end of the given year
1481 ** where, to make the math easy, the answer for year zero is defined as zero.
1482 */
1483
1484 static int leaps_thru_end_of(const int y)
1485 {
1486         return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1487                 -(leaps_thru_end_of(-(y + 1)) + 1);
1488 }
1489
1490 static struct ast_tm *timesub(const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
1491 {
1492         const struct lsinfo *   lp;
1493         time_t                  tdays;
1494         int                     idays;  /* unsigned would be so 2003 */
1495         long                    rem;
1496         int                             y;
1497         const int *             ip;
1498         long                    corr;
1499         int                     hit;
1500         int                     i;
1501         long    seconds;
1502
1503
1504         corr = 0;
1505         hit = 0;
1506         i = (sp == NULL) ? 0 : sp->leapcnt;
1507         while (--i >= 0) {
1508                 lp = &sp->lsis[i];
1509                 if (timep->tv_sec >= lp->ls_trans) {
1510                         if (timep->tv_sec == lp->ls_trans) {
1511                                 hit = ((i == 0 && lp->ls_corr > 0) ||
1512                                         lp->ls_corr > sp->lsis[i - 1].ls_corr);
1513                                 if (hit)
1514                                         while (i > 0 &&
1515                                                 sp->lsis[i].ls_trans ==
1516                                                 sp->lsis[i - 1].ls_trans + 1 &&
1517                                                 sp->lsis[i].ls_corr ==
1518                                                 sp->lsis[i - 1].ls_corr + 1) {
1519                                                         ++hit;
1520                                                         --i;
1521                                         }
1522                         }
1523                         corr = lp->ls_corr;
1524                         break;
1525                 }
1526         }
1527         y = EPOCH_YEAR;
1528         tdays = timep->tv_sec / SECSPERDAY;
1529         rem = timep->tv_sec - tdays * SECSPERDAY;
1530         while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
1531                 int             newy;
1532                 time_t  tdelta;
1533                 int     idelta;
1534                 int     leapdays;
1535
1536                 tdelta = tdays / DAYSPERLYEAR;
1537                 idelta = tdelta;
1538                 if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
1539                         return NULL;
1540                 if (idelta == 0)
1541                         idelta = (tdays < 0) ? -1 : 1;
1542                 newy = y;
1543                 if (increment_overflow(&newy, idelta))
1544                         return NULL;
1545                 leapdays = leaps_thru_end_of(newy - 1) -
1546                         leaps_thru_end_of(y - 1);
1547                 tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
1548                 tdays -= leapdays;
1549                 y = newy;
1550         }
1551
1552         seconds = tdays * SECSPERDAY + 0.5;
1553         tdays = seconds / SECSPERDAY;
1554         rem += seconds - tdays * SECSPERDAY;
1555
1556         /*
1557         ** Given the range, we can now fearlessly cast...
1558         */
1559         idays = tdays;
1560         rem += offset - corr;
1561         while (rem < 0) {
1562                 rem += SECSPERDAY;
1563                 --idays;
1564         }
1565         while (rem >= SECSPERDAY) {
1566                 rem -= SECSPERDAY;
1567                 ++idays;
1568         }
1569         while (idays < 0) {
1570                 if (increment_overflow(&y, -1))
1571                         return NULL;
1572                 idays += year_lengths[isleap(y)];
1573         }
1574         while (idays >= year_lengths[isleap(y)]) {
1575                 idays -= year_lengths[isleap(y)];
1576                 if (increment_overflow(&y, 1))
1577                         return NULL;
1578         }
1579         tmp->tm_year = y;
1580         if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
1581                 return NULL;
1582         tmp->tm_yday = idays;
1583         /*
1584         ** The "extra" mods below avoid overflow problems.
1585         */
1586         tmp->tm_wday = EPOCH_WDAY +
1587                 ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1588                 (DAYSPERNYEAR % DAYSPERWEEK) +
1589                 leaps_thru_end_of(y - 1) -
1590                 leaps_thru_end_of(EPOCH_YEAR - 1) +
1591                 idays;
1592         tmp->tm_wday %= DAYSPERWEEK;
1593         if (tmp->tm_wday < 0)
1594                 tmp->tm_wday += DAYSPERWEEK;
1595         tmp->tm_hour = (int) (rem / SECSPERHOUR);
1596         rem %= SECSPERHOUR;
1597         tmp->tm_min = (int) (rem / SECSPERMIN);
1598         /*
1599         ** A positive leap second requires a special
1600         ** representation. This uses "... ??:59:60" et seq.
1601         */
1602         tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1603         ip = mon_lengths[isleap(y)];
1604         for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1605                 idays -= ip[tmp->tm_mon];
1606         tmp->tm_mday = (int) (idays + 1);
1607         tmp->tm_isdst = 0;
1608 #ifdef TM_GMTOFF
1609         tmp->TM_GMTOFF = offset;
1610 #endif /* defined TM_GMTOFF */
1611         tmp->tm_usec = timep->tv_usec;
1612         return tmp;
1613 }
1614
1615 /*! \note
1616 ** Adapted from code provided by Robert Elz, who writes:
1617 **      The "best" way to do mktime I think is based on an idea of Bob
1618 **      Kridle's (so its said...) from a long time ago.
1619 **      It does a binary search of the time_t space. Since time_t's are
1620 **      just 32 bits, its a max of 32 iterations (even at 64 bits it
1621 **      would still be very reasonable).
1622 */
1623
1624 /*! \brief
1625 ** Simplified normalize logic courtesy Paul Eggert.
1626 */
1627
1628 static int increment_overflow(int *number, int delta)
1629 {
1630         int     number0;
1631
1632         number0 = *number;
1633         *number += delta;
1634         return (*number < number0) != (delta < 0);
1635 }
1636
1637 static int long_increment_overflow(long *number, int delta)
1638 {
1639         long    number0;
1640
1641         number0 = *number;
1642         *number += delta;
1643         return (*number < number0) != (delta < 0);
1644 }
1645
1646 static int normalize_overflow(int *tensptr, int *unitsptr, const int base)
1647 {
1648         int     tensdelta;
1649
1650         tensdelta = (*unitsptr >= 0) ?
1651                 (*unitsptr / base) :
1652                 (-1 - (-1 - *unitsptr) / base);
1653         *unitsptr -= tensdelta * base;
1654         return increment_overflow(tensptr, tensdelta);
1655 }
1656
1657 static int long_normalize_overflow(long *tensptr, int *unitsptr, const int base)
1658 {
1659         int     tensdelta;
1660
1661         tensdelta = (*unitsptr >= 0) ?
1662                 (*unitsptr / base) :
1663                 (-1 - (-1 - *unitsptr) / base);
1664         *unitsptr -= tensdelta * base;
1665         return long_increment_overflow(tensptr, tensdelta);
1666 }
1667
1668 static int tmcomp(const struct ast_tm *atmp, const struct ast_tm *btmp)
1669 {
1670         int     result;
1671
1672         if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1673                 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1674                 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1675                 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1676                 (result = (atmp->tm_min - btmp->tm_min)) == 0 &&
1677                 (result = (atmp->tm_sec - btmp->tm_sec)) == 0)
1678                         result = atmp->tm_usec - btmp->tm_usec;
1679         return result;
1680 }
1681
1682 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)
1683 {
1684         int                     dir;
1685         int                     i, j;
1686         int                     saved_seconds;
1687         long                    li;
1688         time_t                  lo;
1689         time_t                  hi;
1690         long                            y;
1691         struct timeval                  newt = { 0, 0 };
1692         struct timeval                  t = { 0, 0 };
1693         struct ast_tm                   yourtm, mytm;
1694
1695         *okayp = FALSE;
1696         yourtm = *tmp;
1697         if (do_norm_secs) {
1698                 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
1699                         SECSPERMIN))
1700                                 return WRONG;
1701         }
1702         if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
1703                 return WRONG;
1704         if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
1705                 return WRONG;
1706         y = yourtm.tm_year;
1707         if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
1708                 return WRONG;
1709         /*
1710         ** Turn y into an actual year number for now.
1711         ** It is converted back to an offset from TM_YEAR_BASE later.
1712         */
1713         if (long_increment_overflow(&y, TM_YEAR_BASE))
1714                 return WRONG;
1715         while (yourtm.tm_mday <= 0) {
1716                 if (long_increment_overflow(&y, -1))
1717                         return WRONG;
1718                 li = y + (1 < yourtm.tm_mon);
1719                 yourtm.tm_mday += year_lengths[isleap(li)];
1720         }
1721         while (yourtm.tm_mday > DAYSPERLYEAR) {
1722                 li = y + (1 < yourtm.tm_mon);
1723                 yourtm.tm_mday -= year_lengths[isleap(li)];
1724                 if (long_increment_overflow(&y, 1))
1725                         return WRONG;
1726         }
1727         for ( ; ; ) {
1728                 i = mon_lengths[isleap(y)][yourtm.tm_mon];
1729                 if (yourtm.tm_mday <= i)
1730                         break;
1731                 yourtm.tm_mday -= i;
1732                 if (++yourtm.tm_mon >= MONSPERYEAR) {
1733                         yourtm.tm_mon = 0;
1734                         if (long_increment_overflow(&y, 1))
1735                                 return WRONG;
1736                 }
1737         }
1738         if (long_increment_overflow(&y, -TM_YEAR_BASE))
1739                 return WRONG;
1740         yourtm.tm_year = y;
1741         if (yourtm.tm_year != y)
1742                 return WRONG;
1743         if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
1744                 saved_seconds = 0;
1745         else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
1746                 /*
1747                 ** We can't set tm_sec to 0, because that might push the
1748                 ** time below the minimum representable time.
1749                 ** Set tm_sec to 59 instead.
1750                 ** This assumes that the minimum representable time is
1751                 ** not in the same minute that a leap second was deleted from,
1752                 ** which is a safer assumption than using 58 would be.
1753                 */
1754                 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
1755                         return WRONG;
1756                 saved_seconds = yourtm.tm_sec;
1757                 yourtm.tm_sec = SECSPERMIN - 1;
1758         } else {
1759                 saved_seconds = yourtm.tm_sec;
1760                 yourtm.tm_sec = 0;
1761         }
1762         /*
1763         ** Do a binary search (this works whatever time_t's type is).
1764         */
1765         if (!TYPE_SIGNED(time_t)) {
1766                 lo = 0;
1767                 hi = lo - 1;
1768         } else if (!TYPE_INTEGRAL(time_t)) {
1769                 if (sizeof(time_t) > sizeof(float))
1770                         hi = (time_t) DBL_MAX;
1771                 else    hi = (time_t) FLT_MAX;
1772                 lo = -hi;
1773         } else {
1774                 lo = 1;
1775                 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
1776                         lo *= 2;
1777                 hi = -(lo + 1);
1778         }
1779         for ( ; ; ) {
1780                 t.tv_sec = lo / 2 + hi / 2;
1781                 if (t.tv_sec < lo)
1782                         t.tv_sec = lo;
1783                 else if (t.tv_sec > hi)
1784                         t.tv_sec = hi;
1785                 if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
1786                         /*
1787                         ** Assume that t is too extreme to be represented in
1788                         ** a struct ast_tm; arrange things so that it is less
1789                         ** extreme on the next pass.
1790                         */
1791                         dir = (t.tv_sec > 0) ? 1 : -1;
1792                 } else  dir = tmcomp(&mytm, &yourtm);
1793                 if (dir != 0) {
1794                         if (t.tv_sec == lo) {
1795                                 ++t.tv_sec;
1796                                 if (t.tv_sec <= lo)
1797                                         return WRONG;
1798                                 ++lo;
1799                         } else if (t.tv_sec == hi) {
1800                                 --t.tv_sec;
1801                                 if (t.tv_sec >= hi)
1802                                         return WRONG;
1803                                 --hi;
1804                         }
1805                         if (lo > hi)
1806                                 return WRONG;
1807                         if (dir > 0)
1808                                 hi = t.tv_sec;
1809                         else    lo = t.tv_sec;
1810                         continue;
1811                 }
1812                 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1813                         break;
1814                 /*
1815                 ** Right time, wrong type.
1816                 ** Hunt for right time, right type.
1817                 ** It's okay to guess wrong since the guess
1818                 ** gets checked.
1819                 */
1820                 /*
1821                 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1822                 */
1823                 for (i = sp->typecnt - 1; i >= 0; --i) {
1824                         if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
1825                                 continue;
1826                         for (j = sp->typecnt - 1; j >= 0; --j) {
1827                                 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
1828                                         continue;
1829                                 newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff -
1830                                         sp->ttis[i].tt_gmtoff;
1831                                 if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
1832                                         continue;
1833                                 if (tmcomp(&mytm, &yourtm) != 0)
1834                                         continue;
1835                                 if (mytm.tm_isdst != yourtm.tm_isdst)
1836                                         continue;
1837                                 /*
1838                                 ** We have a match.
1839                                 */
1840                                 t = newt;
1841                                 goto label;
1842                         }
1843                 }
1844                 return WRONG;
1845         }
1846 label:
1847         newt.tv_sec = t.tv_sec + saved_seconds;
1848         if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0))
1849                 return WRONG;
1850         t.tv_sec = newt.tv_sec;
1851         if ((*funcp)(&t, offset, tmp, sp))
1852                 *okayp = TRUE;
1853         return t;
1854 }
1855
1856 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)
1857 {
1858         struct timeval  t;
1859
1860         /*! \note
1861         ** First try without normalization of seconds
1862         ** (in case tm_sec contains a value associated with a leap second).
1863         ** If that fails, try with normalization of seconds.
1864         */
1865         t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
1866         return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
1867 }
1868
1869 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)
1870 {
1871         struct timeval                  t;
1872         int                     samei, otheri;
1873         int                     sameind, otherind;
1874         int                     i;
1875         int                     nseen;
1876         int                             seen[TZ_MAX_TYPES];
1877         int                             types[TZ_MAX_TYPES];
1878         int                             okay;
1879
1880         if (tmp->tm_isdst > 1)
1881                 tmp->tm_isdst = 1;
1882         t = time2(tmp, funcp, offset, &okay, sp);
1883 #ifdef PCTS
1884         /*
1885         ** PCTS code courtesy Grant Sullivan.
1886         */
1887         if (okay)
1888                 return t;
1889         if (tmp->tm_isdst < 0)
1890                 tmp->tm_isdst = 0;      /* reset to std and try again */
1891 #endif /* defined PCTS */
1892 #ifndef PCTS
1893         if (okay || tmp->tm_isdst < 0)
1894                 return t;
1895 #endif /* !defined PCTS */
1896         /*
1897         ** We're supposed to assume that somebody took a time of one type
1898         ** and did some math on it that yielded a "struct ast_tm" that's bad.
1899         ** We try to divine the type they started from and adjust to the
1900         ** type they need.
1901         */
1902         if (sp == NULL)
1903                 return WRONG;
1904         for (i = 0; i < sp->typecnt; ++i)
1905                 seen[i] = FALSE;
1906         nseen = 0;
1907         for (i = sp->timecnt - 1; i >= 0; --i)
1908                 if (!seen[sp->types[i]]) {
1909                         seen[sp->types[i]] = TRUE;
1910                         types[nseen++] = sp->types[i];
1911                 }
1912         for (sameind = 0; sameind < nseen; ++sameind) {
1913                 samei = types[sameind];
1914                 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
1915                         continue;
1916                 for (otherind = 0; otherind < nseen; ++otherind) {
1917                         otheri = types[otherind];
1918                         if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
1919                                 continue;
1920                         tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
1921                                         sp->ttis[samei].tt_gmtoff;
1922                         tmp->tm_isdst = !tmp->tm_isdst;
1923                         t = time2(tmp, funcp, offset, &okay, sp);
1924                         if (okay)
1925                                 return t;
1926                         tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
1927                                         sp->ttis[samei].tt_gmtoff;
1928                         tmp->tm_isdst = !tmp->tm_isdst;
1929                 }
1930         }
1931         return WRONG;
1932 }
1933
1934 struct timeval ast_mktime(struct ast_tm *tmp, const char *zone)
1935 {
1936         const struct state *sp;
1937         if (!(sp = ast_tzset(zone)))
1938                 return WRONG;
1939         return time1(tmp, localsub, 0L, sp);
1940 }
1941
1942 int ast_strftime(char *buf, size_t len, const char *tmp, const struct ast_tm *tm)
1943 {
1944         size_t fmtlen = strlen(tmp) + 1;
1945         char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt;
1946         int decimals = -1, i, res;
1947         long fraction;
1948
1949         if (!format)
1950                 return -1;
1951         for (; *tmp; tmp++) {
1952                 if (*tmp == '%') {
1953                         switch (tmp[1]) {
1954                         case '1':
1955                         case '2':
1956                         case '3':
1957                         case '4':
1958                         case '5':
1959                         case '6':
1960                                 if (tmp[2] != 'q')
1961                                         goto defcase;
1962                                 decimals = tmp[1] - '0';
1963                                 tmp++;
1964                                 /* Fall through */
1965                         case 'q': /* Milliseconds */
1966                                 if (decimals == -1)
1967                                         decimals = 3;
1968
1969                                 /* Juggle some memory to fit the item */
1970                                 newfmt = ast_realloc(format, fmtlen + decimals);
1971                                 if (!newfmt) {
1972                                         ast_free(format);
1973                                         return -1;
1974                                 }
1975                                 fptr = fptr - format + newfmt;
1976                                 format = newfmt;
1977                                 fmtlen += decimals;
1978
1979                                 /* Reduce the fraction of time to the accuracy needed */
1980                                 for (i = 6, fraction = tm->tm_usec; i > decimals; i--)
1981                                         fraction /= 10;
1982                                 fptr += sprintf(fptr, "%0*ld", decimals, fraction);
1983
1984                                 /* Reset, in case more than one 'q' specifier exists */
1985                                 decimals = -1;
1986                                 tmp++;
1987                                 break;
1988                         default:
1989                                 goto defcase;
1990                         }
1991                 } else
1992 defcase:        *fptr++ = *tmp;
1993         }
1994         *fptr = '\0';
1995 #undef strftime
1996         res = (int)strftime(buf, len, format, (struct tm *)tm);
1997         ast_free(format);
1998         return res;
1999 }
2000
2001 char *ast_strptime(const char *s, const char *format, struct ast_tm *tm)
2002 {
2003         struct tm tm2 = { 0, };
2004         char *res = strptime(s, format, &tm2);
2005         memcpy(tm, &tm2, sizeof(*tm));
2006         tm->tm_usec = 0;
2007         /* strptime(3) doesn't set .tm_isdst correctly, so to force ast_mktime(3)
2008          * to deal with it correctly, we set it to -1. */
2009         tm->tm_isdst = -1;
2010         return res;
2011 }
2012