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