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