Thu Apr 28 2011 16:56:47

Asterisk developer's documentation


localtime.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * Most of this code is in the public domain, so clarified as of
00009  * June 5, 1996 by Arthur David Olson (arthur_david_olson@nih.gov).
00010  *
00011  * All modifications to this code to abstract timezones away from
00012  * the environment are by Tilghman Lesher, <tlesher@vcch.com>, with
00013  * the copyright assigned to Digium.
00014  *
00015  * See http://www.asterisk.org for more information about
00016  * the Asterisk project. Please do not directly contact
00017  * any of the maintainers of this project for assistance;
00018  * the project provides a web site, mailing lists and IRC
00019  * channels for your use.
00020  *
00021  * This program is free software, distributed under the terms of
00022  * the GNU General Public License Version 2. See the LICENSE file
00023  * at the top of the source tree.
00024  */
00025 
00026 /*! \file
00027  *
00028  * Multi-timezone Localtime code
00029  *
00030  * The original source from this file may be obtained from ftp://elsie.nci.nih.gov/pub/
00031  */
00032 
00033 /*
00034 ** This file is in the public domain, so clarified as of
00035 ** 1996-06-05 by Arthur David Olson.
00036 */
00037 
00038 /*
00039 ** Leap second handling from Bradley White.
00040 ** POSIX-style TZ environment variable handling from Guy Harris.
00041 */
00042 
00043 /* #define DEBUG */
00044 
00045 /*LINTLIBRARY*/
00046 
00047 #include "asterisk.h"
00048 
00049 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 253620 $")
00050 
00051 #include <signal.h>
00052 #include <sys/stat.h>
00053 #include <fcntl.h>
00054 #include <float.h>
00055 #ifdef HAVE_INOTIFY
00056 #include <sys/inotify.h>
00057 #endif
00058 
00059 #include "private.h"
00060 #include "tzfile.h"
00061 
00062 #include "asterisk/lock.h"
00063 #include "asterisk/localtime.h"
00064 #include "asterisk/strings.h"
00065 #include "asterisk/linkedlists.h"
00066 #include "asterisk/utils.h"
00067 
00068 #ifndef lint
00069 #ifndef NOID
00070 static char __attribute__((unused)) elsieid[] = "@(#)localtime.c  8.5";
00071 #endif /* !defined NOID */
00072 #endif /* !defined lint */
00073 
00074 #ifndef TZ_ABBR_MAX_LEN
00075 #define TZ_ABBR_MAX_LEN 16
00076 #endif /* !defined TZ_ABBR_MAX_LEN */
00077 
00078 #ifndef TZ_ABBR_CHAR_SET
00079 #define TZ_ABBR_CHAR_SET \
00080    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
00081 #endif /* !defined TZ_ABBR_CHAR_SET */
00082 
00083 #ifndef TZ_ABBR_ERR_CHAR
00084 #define TZ_ABBR_ERR_CHAR   '_'
00085 #endif /* !defined TZ_ABBR_ERR_CHAR */
00086 
00087 /*
00088 ** SunOS 4.1.1 headers lack O_BINARY.
00089 */
00090 
00091 #ifdef O_BINARY
00092 #define OPEN_MODE (O_RDONLY | O_BINARY)
00093 #endif /* defined O_BINARY */
00094 #ifndef O_BINARY
00095 #define OPEN_MODE O_RDONLY
00096 #endif /* !defined O_BINARY */
00097 
00098 static const char gmt[] = "GMT";
00099 static const struct timeval WRONG = { 0, 0 };
00100 
00101 /*! \note
00102  * The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
00103  * We default to US rules as of 1999-08-17.
00104  * POSIX 1003.1 section 8.1.1 says that the default DST rules are
00105  * implementation dependent; for historical reasons, US rules are a
00106  * common default.
00107  */
00108 #ifndef TZDEFRULESTRING
00109 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
00110 #endif /* !defined TZDEFDST */
00111 
00112 /*!< \brief time type information */
00113 struct ttinfo {            /* time type information */
00114    long     tt_gmtoff;  /* UTC offset in seconds */
00115    int      tt_isdst;   /* used to set tm_isdst */
00116    int      tt_abbrind; /* abbreviation list index */
00117    int      tt_ttisstd; /* TRUE if transition is std time */
00118    int      tt_ttisgmt; /* TRUE if transition is UTC */
00119 };
00120 
00121 /*! \brief leap second information */
00122 struct lsinfo {            /* leap second information */
00123    time_t      ls_trans;   /* transition time */
00124    long     ls_corr; /* correction to apply */
00125 };
00126 
00127 #define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
00128 
00129 #ifdef TZNAME_MAX
00130 #define MY_TZNAME_MAX   TZNAME_MAX
00131 #endif /* defined TZNAME_MAX */
00132 #ifndef TZNAME_MAX
00133 #define MY_TZNAME_MAX   255
00134 #endif /* !defined TZNAME_MAX */
00135 #ifndef TZ_STRLEN_MAX
00136 #define TZ_STRLEN_MAX   255
00137 #endif /* !defined TZ_STRLEN_MAX */
00138 
00139 struct state {
00140    /*! Name of the file that this references */
00141    char    name[TZ_STRLEN_MAX + 1];
00142    int      leapcnt;
00143    int      timecnt;
00144    int      typecnt;
00145    int      charcnt;
00146    int      goback;
00147    int      goahead;
00148    time_t      ats[TZ_MAX_TIMES];
00149    unsigned char  types[TZ_MAX_TIMES];
00150    struct ttinfo  ttis[TZ_MAX_TYPES];
00151    char     chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
00152             (2 * (MY_TZNAME_MAX + 1)))];
00153    struct lsinfo  lsis[TZ_MAX_LEAPS];
00154 #ifdef HAVE_INOTIFY
00155    int wd[2];
00156 #else
00157    time_t  mtime[2];
00158 #endif
00159    AST_LIST_ENTRY(state) list;
00160 };
00161 
00162 struct rule {
00163    int      r_type;     /* type of rule--see below */
00164    int      r_day;      /* day number of rule */
00165    int      r_week;     /* week number of rule */
00166    int      r_mon;      /* month number of rule */
00167    long     r_time;     /* transition time of rule */
00168 };
00169 
00170 #define JULIAN_DAY      0  /* Jn - Julian day */
00171 #define DAY_OF_YEAR     1  /* n - day of year */
00172 #define MONTH_NTH_DAY_OF_WEEK 2  /* Mm.n.d - month, week, day of week */
00173 
00174 /*
00175 ** Prototypes for static functions.
00176 */
00177 
00178 static long    detzcode P((const char * codep));
00179 static time_t     detzcode64 P((const char * codep));
00180 static int     differ_by_repeat P((time_t t1, time_t t0));
00181 static const char *  getzname P((const char * strp));
00182 static const char *  getqzname P((const char * strp, const int delim));
00183 static const char *  getnum P((const char * strp, int * nump, int min,
00184             int max));
00185 static const char *  getsecs P((const char * strp, long * secsp));
00186 static const char *  getoffset P((const char * strp, long * offsetp));
00187 static const char *  getrule P((const char * strp, struct rule * rulep));
00188 static int     gmtload P((struct state * sp));
00189 static struct ast_tm *  gmtsub P((const struct timeval * timep, long offset,
00190             struct ast_tm * tmp));
00191 static struct ast_tm *  localsub P((const struct timeval * timep, long offset,
00192             struct ast_tm * tmp, const struct state *sp));
00193 static int     increment_overflow P((int * number, int delta));
00194 static int     leaps_thru_end_of P((int y));
00195 static int     long_increment_overflow P((long * number, int delta));
00196 static int     long_normalize_overflow P((long * tensptr,
00197             int * unitsptr, const int base));
00198 static int     normalize_overflow P((int * tensptr, int * unitsptr,
00199             const int base));
00200 static struct timeval   time1 P((struct ast_tm * tmp,
00201             struct ast_tm * (*funcp) P((const struct timeval *,
00202             long, struct ast_tm *, const struct state *sp)),
00203             long offset, const struct state *sp));
00204 static struct timeval   time2 P((struct ast_tm *tmp,
00205             struct ast_tm * (*funcp) P((const struct timeval *,
00206             long, struct ast_tm*, const struct state *sp)),
00207             long offset, int * okayp, const struct state *sp));
00208 static struct timeval   time2sub P((struct ast_tm *tmp,
00209             struct ast_tm * (*funcp) (const struct timeval *,
00210             long, struct ast_tm*, const struct state *sp),
00211             long offset, int * okayp, int do_norm_secs, const struct state *sp));
00212 static struct ast_tm *  timesub P((const struct timeval * timep, long offset,
00213             const struct state * sp, struct ast_tm * tmp));
00214 static int     tmcomp P((const struct ast_tm * atmp,
00215             const struct ast_tm * btmp));
00216 static time_t     transtime P((time_t janfirst, int year,
00217             const struct rule * rulep, long offset));
00218 static int     tzload P((const char * name, struct state * sp,
00219             int doextend));
00220 static int     tzparse P((const char * name, struct state * sp,
00221             int lastditch));
00222 
00223 static AST_LIST_HEAD_STATIC(zonelist, state);
00224 
00225 #ifndef TZ_STRLEN_MAX
00226 #define TZ_STRLEN_MAX 255
00227 #endif /* !defined TZ_STRLEN_MAX */
00228 
00229 static pthread_t inotify_thread = AST_PTHREADT_NULL;
00230 static ast_cond_t initialization;
00231 static ast_mutex_t initialization_lock;
00232 #ifdef HAVE_INOTIFY
00233 static int inotify_fd = -1;
00234 
00235 static void *inotify_daemon(void *data)
00236 {
00237    struct {
00238       struct inotify_event iev;
00239       char name[FILENAME_MAX + 1];
00240    } buf;
00241    ssize_t res;
00242    struct state *cur;
00243    struct timespec ten_seconds = { 10, 0 };
00244 
00245    inotify_fd = inotify_init();
00246 
00247    ast_mutex_lock(&initialization_lock);
00248    ast_cond_signal(&initialization);
00249    ast_mutex_unlock(&initialization_lock);
00250 
00251    if (inotify_fd < 0) {
00252       ast_log(LOG_ERROR, "Cannot initialize file notification service: %s (%d)\n", strerror(errno), errno);
00253       inotify_thread = AST_PTHREADT_NULL;
00254       return NULL;
00255    }
00256 
00257    for (;/*ever*/;) {
00258       /* This read should block, most of the time. */
00259       if ((res = read(inotify_fd, &buf, sizeof(buf))) < sizeof(buf.iev) && res > 0) {
00260          /* This should never happen */
00261          ast_log(LOG_ERROR, "Inotify read less than a full event (%zd < %zd)?!!\n", res, sizeof(buf.iev));
00262          break;
00263       } else if (res < 0) {
00264          if (errno == EINTR || errno == EAGAIN) {
00265             /* If read fails, then wait a bit, then continue */
00266             nanosleep(&ten_seconds, NULL);
00267             continue;
00268          }
00269          /* Sanity check -- this should never happen, either */
00270          ast_log(LOG_ERROR, "Inotify failed: %s\n", strerror(errno));
00271          break;
00272       }
00273       AST_LIST_LOCK(&zonelist);
00274       AST_LIST_TRAVERSE_SAFE_BEGIN(&zonelist, cur, list) {
00275          if (cur->wd[0] == buf.iev.wd || cur->wd[1] == buf.iev.wd) {
00276             AST_LIST_REMOVE_CURRENT(list);
00277             ast_free(cur);
00278             break;
00279          }
00280       }
00281       AST_LIST_TRAVERSE_SAFE_END
00282       AST_LIST_UNLOCK(&zonelist);
00283    }
00284    close(inotify_fd);
00285    inotify_thread = AST_PTHREADT_NULL;
00286    return NULL;
00287 }
00288 
00289 static void add_notify(struct state *sp, const char *path)
00290 {
00291    if (inotify_thread == AST_PTHREADT_NULL) {
00292       ast_cond_init(&initialization, NULL);
00293       ast_mutex_init(&initialization_lock);
00294       ast_mutex_lock(&initialization_lock);
00295       if (!(ast_pthread_create_background(&inotify_thread, NULL, inotify_daemon, NULL))) {
00296          /* Give the thread a chance to initialize */
00297          ast_cond_wait(&initialization, &initialization_lock);
00298       } else {
00299          ast_log(LOG_ERROR, "Unable to start notification thread\n");
00300          ast_mutex_unlock(&initialization_lock);
00301          return;
00302       }
00303       ast_mutex_unlock(&initialization_lock);
00304    }
00305 
00306    if (inotify_fd > -1) {
00307       char fullpath[FILENAME_MAX + 1] = "";
00308       if (readlink(path, fullpath, sizeof(fullpath) - 1) != -1) {
00309          /* If file the symlink points to changes */
00310          sp->wd[1] = inotify_add_watch(inotify_fd, fullpath, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE );
00311       } else {
00312          sp->wd[1] = -1;
00313       }
00314       /* or if the symlink itself changes (or the real file is here, if path is not a symlink) */
00315       sp->wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE
00316 #ifdef IN_DONT_FOLLOW   /* Only defined in glibc 2.5 and above */
00317          | IN_DONT_FOLLOW
00318 #endif
00319       );
00320    }
00321 }
00322 #else
00323 static void *notify_daemon(void *data)
00324 {
00325    struct stat st, lst;
00326    struct state *cur;
00327    struct timespec sixty_seconds = { 60, 0 };
00328 
00329    ast_mutex_lock(&initialization_lock);
00330    ast_cond_signal(&initialization);
00331    ast_mutex_unlock(&initialization_lock);
00332 
00333    for (;/*ever*/;) {
00334       char     fullname[FILENAME_MAX + 1];
00335 
00336       nanosleep(&sixty_seconds, NULL);
00337       AST_LIST_LOCK(&zonelist);
00338       AST_LIST_TRAVERSE_SAFE_BEGIN(&zonelist, cur, list) {
00339          char *name = cur->name;
00340 
00341          if (name[0] == ':')
00342             ++name;
00343          if (name[0] != '/') {
00344             (void) strcpy(fullname, TZDIR "/");
00345             (void) strcat(fullname, name);
00346             name = fullname;
00347          }
00348          stat(name, &st);
00349          lstat(name, &lst);
00350          if (st.st_mtime > cur->mtime[0] || lst.st_mtime > cur->mtime[1]) {
00351             AST_LIST_REMOVE_CURRENT(list);
00352             ast_free(cur);
00353             continue;
00354          }
00355       }
00356       AST_LIST_TRAVERSE_SAFE_END
00357       AST_LIST_UNLOCK(&zonelist);
00358    }
00359    inotify_thread = AST_PTHREADT_NULL;
00360    return NULL;
00361 }
00362 
00363 static void add_notify(struct state *sp, const char *path)
00364 {
00365    struct stat st;
00366 
00367    if (inotify_thread == AST_PTHREADT_NULL) {
00368       ast_cond_init(&initialization, NULL);
00369       ast_mutex_init(&initialization_lock);
00370       ast_mutex_lock(&initialization_lock);
00371       if (!(ast_pthread_create_background(&inotify_thread, NULL, notify_daemon, NULL))) {
00372          /* Give the thread a chance to initialize */
00373          ast_cond_wait(&initialization, &initialization_lock);
00374       }
00375       ast_mutex_unlock(&initialization_lock);
00376    }
00377 
00378    stat(path, &st);
00379    sp->mtime[0] = st.st_mtime;
00380    lstat(path, &st);
00381    sp->mtime[1] = st.st_mtime;
00382 }
00383 #endif
00384 
00385 /*! \note
00386 ** Section 4.12.3 of X3.159-1989 requires that
00387 ** Except for the strftime function, these functions [asctime,
00388 ** ctime, gmtime, localtime] return values in one of two static
00389 ** objects: a broken-down time structure and an array of char.
00390 ** Thanks to Paul Eggert for noting this.
00391 */
00392 
00393 static long detzcode(const char * const codep)
00394 {
00395    long  result;
00396    int   i;
00397 
00398    result = (codep[0] & 0x80) ? ~0L : 0;
00399    for (i = 0; i < 4; ++i)
00400       result = (result << 8) | (codep[i] & 0xff);
00401    return result;
00402 }
00403 
00404 static time_t detzcode64(const char * const codep)
00405 {
00406    time_t   result;
00407    int   i;
00408 
00409    result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
00410    for (i = 0; i < 8; ++i)
00411       result = result * 256 + (codep[i] & 0xff);
00412    return result;
00413 }
00414 
00415 static int differ_by_repeat(const time_t t1, const time_t t0)
00416 {
00417    const long long at1 = t1, at0 = t0;
00418    if (TYPE_INTEGRAL(time_t) &&
00419       TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
00420          return 0;
00421    return at1 - at0 == SECSPERREPEAT;
00422 }
00423 
00424 static int tzload(const char *name, struct state * const sp, const int doextend)
00425 {
00426    const char *      p;
00427    int         i;
00428    int         fid;
00429    int         stored;
00430    int         nread;
00431    union {
00432       struct tzhead  tzhead;
00433       char     buf[2 * sizeof(struct tzhead) +
00434                2 * sizeof *sp +
00435                4 * TZ_MAX_TIMES];
00436    } u;
00437 
00438    if (name == NULL && (name = TZDEFAULT) == NULL)
00439       return -1;
00440    {
00441       int   doaccess;
00442       /*
00443       ** Section 4.9.1 of the C standard says that
00444       ** "FILENAME_MAX expands to an integral constant expression
00445       ** that is the size needed for an array of char large enough
00446       ** to hold the longest file name string that the implementation
00447       ** guarantees can be opened."
00448       */
00449       char     fullname[FILENAME_MAX + 1];
00450 
00451       if (name[0] == ':')
00452          ++name;
00453       doaccess = name[0] == '/';
00454       if (!doaccess) {
00455          if ((p = TZDIR) == NULL)
00456             return -1;
00457          if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
00458             return -1;
00459          (void) strcpy(fullname, p);
00460          (void) strcat(fullname, "/");
00461          (void) strcat(fullname, name);
00462          /*
00463          ** Set doaccess if '.' (as in "../") shows up in name.
00464          */
00465          if (strchr(name, '.') != NULL)
00466             doaccess = TRUE;
00467          name = fullname;
00468       }
00469       if (doaccess && access(name, R_OK) != 0)
00470          return -1;
00471       if ((fid = open(name, OPEN_MODE)) == -1)
00472          return -1;
00473       add_notify(sp, name);
00474    }
00475    nread = read(fid, u.buf, sizeof u.buf);
00476    if (close(fid) < 0 || nread <= 0)
00477       return -1;
00478    for (stored = 4; stored <= 8; stored *= 2) {
00479       int      ttisstdcnt;
00480       int      ttisgmtcnt;
00481 
00482       ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
00483       ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
00484       sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
00485       sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
00486       sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
00487       sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
00488       p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
00489       if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
00490          sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
00491          sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
00492          sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
00493          (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
00494          (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
00495             return -1;
00496       if (nread - (p - u.buf) <
00497          sp->timecnt * stored +     /* ats */
00498          sp->timecnt +        /* types */
00499          sp->typecnt * 6 +    /* ttinfos */
00500          sp->charcnt +        /* chars */
00501          sp->leapcnt * (stored + 4) +  /* lsinfos */
00502          ttisstdcnt +         /* ttisstds */
00503          ttisgmtcnt)       /* ttisgmts */
00504             return -1;
00505       for (i = 0; i < sp->timecnt; ++i) {
00506          sp->ats[i] = (stored == 4) ?
00507             detzcode(p) : detzcode64(p);
00508          p += stored;
00509       }
00510       for (i = 0; i < sp->timecnt; ++i) {
00511          sp->types[i] = (unsigned char) *p++;
00512          if (sp->types[i] >= sp->typecnt)
00513             return -1;
00514       }
00515       for (i = 0; i < sp->typecnt; ++i) {
00516          struct ttinfo *   ttisp;
00517 
00518          ttisp = &sp->ttis[i];
00519          ttisp->tt_gmtoff = detzcode(p);
00520          p += 4;
00521          ttisp->tt_isdst = (unsigned char) *p++;
00522          if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
00523             return -1;
00524          ttisp->tt_abbrind = (unsigned char) *p++;
00525          if (ttisp->tt_abbrind < 0 ||
00526             ttisp->tt_abbrind > sp->charcnt)
00527                return -1;
00528       }
00529       for (i = 0; i < sp->charcnt; ++i)
00530          sp->chars[i] = *p++;
00531       sp->chars[i] = '\0'; /* ensure '\0' at end */
00532       for (i = 0; i < sp->leapcnt; ++i) {
00533          struct lsinfo *   lsisp;
00534 
00535          lsisp = &sp->lsis[i];
00536          lsisp->ls_trans = (stored == 4) ?
00537             detzcode(p) : detzcode64(p);
00538          p += stored;
00539          lsisp->ls_corr = detzcode(p);
00540          p += 4;
00541       }
00542       for (i = 0; i < sp->typecnt; ++i) {
00543          struct ttinfo *   ttisp;
00544 
00545          ttisp = &sp->ttis[i];
00546          if (ttisstdcnt == 0)
00547             ttisp->tt_ttisstd = FALSE;
00548          else {
00549             ttisp->tt_ttisstd = *p++;
00550             if (ttisp->tt_ttisstd != TRUE &&
00551                ttisp->tt_ttisstd != FALSE)
00552                   return -1;
00553          }
00554       }
00555       for (i = 0; i < sp->typecnt; ++i) {
00556          struct ttinfo *   ttisp;
00557 
00558          ttisp = &sp->ttis[i];
00559          if (ttisgmtcnt == 0)
00560             ttisp->tt_ttisgmt = FALSE;
00561          else {
00562             ttisp->tt_ttisgmt = *p++;
00563             if (ttisp->tt_ttisgmt != TRUE &&
00564                ttisp->tt_ttisgmt != FALSE)
00565                   return -1;
00566          }
00567       }
00568       /*
00569       ** Out-of-sort ats should mean we're running on a
00570       ** signed time_t system but using a data file with
00571       ** unsigned values (or vice versa).
00572       */
00573       for (i = 0; i < sp->timecnt - 2; ++i)
00574          if (sp->ats[i] > sp->ats[i + 1]) {
00575             ++i;
00576             if (TYPE_SIGNED(time_t)) {
00577                /*
00578                ** Ignore the end (easy).
00579                */
00580                sp->timecnt = i;
00581             } else {
00582                /*
00583                ** Ignore the beginning (harder).
00584                */
00585                int   j;
00586 
00587                for (j = 0; j + i < sp->timecnt; ++j) {
00588                   sp->ats[j] = sp->ats[j + i];
00589                   sp->types[j] = sp->types[j + i];
00590                }
00591                sp->timecnt = j;
00592             }
00593             break;
00594          }
00595       /*
00596       ** If this is an old file, we're done.
00597       */
00598       if (u.tzhead.tzh_version[0] == '\0')
00599          break;
00600       nread -= p - u.buf;
00601       for (i = 0; i < nread; ++i)
00602          u.buf[i] = p[i];
00603       /*
00604       ** If this is a narrow integer time_t system, we're done.
00605       */
00606       if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
00607          break;
00608    }
00609    if (doextend && nread > 2 &&
00610       u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
00611       sp->typecnt + 2 <= TZ_MAX_TYPES) {
00612          struct state   ts;
00613          int   result;
00614 
00615          u.buf[nread - 1] = '\0';
00616          result = tzparse(&u.buf[1], &ts, FALSE);
00617          if (result == 0 && ts.typecnt == 2 &&
00618             sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
00619                for (i = 0; i < 2; ++i)
00620                   ts.ttis[i].tt_abbrind +=
00621                      sp->charcnt;
00622                for (i = 0; i < ts.charcnt; ++i)
00623                   sp->chars[sp->charcnt++] =
00624                      ts.chars[i];
00625                i = 0;
00626                while (i < ts.timecnt &&
00627                   ts.ats[i] <=
00628                   sp->ats[sp->timecnt - 1])
00629                      ++i;
00630                while (i < ts.timecnt &&
00631                    sp->timecnt < TZ_MAX_TIMES) {
00632                   sp->ats[sp->timecnt] =
00633                      ts.ats[i];
00634                   sp->types[sp->timecnt] =
00635                      sp->typecnt +
00636                      ts.types[i];
00637                   ++sp->timecnt;
00638                   ++i;
00639                }
00640                sp->ttis[sp->typecnt++] = ts.ttis[0];
00641                sp->ttis[sp->typecnt++] = ts.ttis[1];
00642          }
00643    }
00644    i = 2 * YEARSPERREPEAT;
00645    sp->goback = sp->goahead = sp->timecnt > i;
00646    sp->goback = sp->goback && sp->types[i] == sp->types[0] &&
00647       differ_by_repeat(sp->ats[i], sp->ats[0]);
00648    sp->goahead = sp->goahead &&
00649       sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
00650       differ_by_repeat(sp->ats[sp->timecnt - 1],
00651           sp->ats[sp->timecnt - 1 - i]);
00652    return 0;
00653 }
00654 
00655 static const int  mon_lengths[2][MONSPERYEAR] = {
00656    { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
00657    { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
00658 };
00659 
00660 static const int  year_lengths[2] = {
00661    DAYSPERNYEAR, DAYSPERLYEAR
00662 };
00663 
00664 /*! \brief
00665 ** Given a pointer into a time zone string, scan until a character that is not
00666 ** a valid character in a zone name is found. Return a pointer to that
00667 ** character.
00668 */
00669 
00670 static const char * getzname(const char *strp)
00671 {
00672    char  c;
00673 
00674    while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
00675       c != '+')
00676          ++strp;
00677    return strp;
00678 }
00679 
00680 /*! \brief
00681 ** Given a pointer into an extended time zone string, scan until the ending
00682 ** delimiter of the zone name is located. Return a pointer to the delimiter.
00683 **
00684 ** As with getzname above, the legal character set is actually quite
00685 ** restricted, with other characters producing undefined results.
00686 ** We don't do any checking here; checking is done later in common-case code.
00687 */
00688 
00689 static const char * getqzname(const char *strp, const int delim)
00690 {
00691    int   c;
00692 
00693    while ((c = *strp) != '\0' && c != delim)
00694       ++strp;
00695    return strp;
00696 }
00697 
00698 /*! \brief
00699 ** Given a pointer into a time zone string, extract a number from that string.
00700 ** Check that the number is within a specified range; if it is not, return
00701 ** NULL.
00702 ** Otherwise, return a pointer to the first character not part of the number.
00703 */
00704 
00705 static const char *getnum(const char *strp, int *nump, const int min, const int max)
00706 {
00707    char  c;
00708    int   num;
00709 
00710    if (strp == NULL || !is_digit(c = *strp))
00711       return NULL;
00712    num = 0;
00713    do {
00714       num = num * 10 + (c - '0');
00715       if (num > max)
00716          return NULL;   /* illegal value */
00717       c = *++strp;
00718    } while (is_digit(c));
00719    if (num < min)
00720       return NULL;      /* illegal value */
00721    *nump = num;
00722    return strp;
00723 }
00724 
00725 /*! \brief
00726 ** Given a pointer into a time zone string, extract a number of seconds,
00727 ** in hh[:mm[:ss]] form, from the string.
00728 ** If any error occurs, return NULL.
00729 ** Otherwise, return a pointer to the first character not part of the number
00730 ** of seconds.
00731 */
00732 
00733 static const char *getsecs(const char *strp, long * const secsp)
00734 {
00735    int   num;
00736 
00737    /*
00738    ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
00739    ** "M10.4.6/26", which does not conform to Posix,
00740    ** but which specifies the equivalent of
00741    ** ``02:00 on the first Sunday on or after 23 Oct''.
00742    */
00743    strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
00744    if (strp == NULL)
00745       return NULL;
00746    *secsp = num * (long) SECSPERHOUR;
00747    if (*strp == ':') {
00748       ++strp;
00749       strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
00750       if (strp == NULL)
00751          return NULL;
00752       *secsp += num * SECSPERMIN;
00753       if (*strp == ':') {
00754          ++strp;
00755          /* `SECSPERMIN' allows for leap seconds. */
00756          strp = getnum(strp, &num, 0, SECSPERMIN);
00757          if (strp == NULL)
00758             return NULL;
00759          *secsp += num;
00760       }
00761    }
00762    return strp;
00763 }
00764 
00765 /*! \brief
00766 ** Given a pointer into a time zone string, extract an offset, in
00767 ** [+-]hh[:mm[:ss]] form, from the string.
00768 ** If any error occurs, return NULL.
00769 ** Otherwise, return a pointer to the first character not part of the time.
00770 */
00771 
00772 static const char *getoffset(const char *strp, long *offsetp)
00773 {
00774    int   neg = 0;
00775 
00776    if (*strp == '-') {
00777       neg = 1;
00778       ++strp;
00779    } else if (*strp == '+')
00780       ++strp;
00781    strp = getsecs(strp, offsetp);
00782    if (strp == NULL)
00783       return NULL;      /* illegal time */
00784    if (neg)
00785       *offsetp = -*offsetp;
00786    return strp;
00787 }
00788 
00789 /*! \brief
00790 ** Given a pointer into a time zone string, extract a rule in the form
00791 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
00792 ** If a valid rule is not found, return NULL.
00793 ** Otherwise, return a pointer to the first character not part of the rule.
00794 */
00795 
00796 static const char *getrule(const char *strp, struct rule *rulep)
00797 {
00798    if (*strp == 'J') {
00799       /*
00800       ** Julian day.
00801       */
00802       rulep->r_type = JULIAN_DAY;
00803       ++strp;
00804       strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
00805    } else if (*strp == 'M') {
00806       /*
00807       ** Month, week, day.
00808       */
00809       rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
00810       ++strp;
00811       strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
00812       if (strp == NULL)
00813          return NULL;
00814       if (*strp++ != '.')
00815          return NULL;
00816       strp = getnum(strp, &rulep->r_week, 1, 5);
00817       if (strp == NULL)
00818          return NULL;
00819       if (*strp++ != '.')
00820          return NULL;
00821       strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
00822    } else if (is_digit(*strp)) {
00823       /*
00824       ** Day of year.
00825       */
00826       rulep->r_type = DAY_OF_YEAR;
00827       strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
00828    } else   return NULL;      /* invalid format */
00829    if (strp == NULL)
00830       return NULL;
00831    if (*strp == '/') {
00832       /*
00833       ** Time specified.
00834       */
00835       ++strp;
00836       strp = getsecs(strp, &rulep->r_time);
00837    } else   rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
00838    return strp;
00839 }
00840 
00841 /*! \brief
00842 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
00843 ** year, a rule, and the offset from UTC at the time that rule takes effect,
00844 ** calculate the Epoch-relative time that rule takes effect.
00845 */
00846 
00847 static time_t transtime(const time_t janfirst, const int year, const struct rule *rulep, const long offset)
00848 {
00849    int   leapyear;
00850    time_t   value;
00851    int   i;
00852    int      d, m1, yy0, yy1, yy2, dow;
00853 
00854    INITIALIZE(value);
00855    leapyear = isleap(year);
00856    switch (rulep->r_type) {
00857 
00858    case JULIAN_DAY:
00859       /*
00860       ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
00861       ** years.
00862       ** In non-leap years, or if the day number is 59 or less, just
00863       ** add SECSPERDAY times the day number-1 to the time of
00864       ** January 1, midnight, to get the day.
00865       */
00866       value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
00867       if (leapyear && rulep->r_day >= 60)
00868          value += SECSPERDAY;
00869       break;
00870 
00871    case DAY_OF_YEAR:
00872       /*
00873       ** n - day of year.
00874       ** Just add SECSPERDAY times the day number to the time of
00875       ** January 1, midnight, to get the day.
00876       */
00877       value = janfirst + rulep->r_day * SECSPERDAY;
00878       break;
00879 
00880    case MONTH_NTH_DAY_OF_WEEK:
00881       /*
00882       ** Mm.n.d - nth "dth day" of month m.
00883       */
00884       value = janfirst;
00885       for (i = 0; i < rulep->r_mon - 1; ++i)
00886          value += mon_lengths[leapyear][i] * SECSPERDAY;
00887 
00888       /*
00889       ** Use Zeller's Congruence to get day-of-week of first day of
00890       ** month.
00891       */
00892       m1 = (rulep->r_mon + 9) % 12 + 1;
00893       yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
00894       yy1 = yy0 / 100;
00895       yy2 = yy0 % 100;
00896       dow = ((26 * m1 - 2) / 10 +
00897          1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
00898       if (dow < 0)
00899          dow += DAYSPERWEEK;
00900 
00901       /*
00902       ** "dow" is the day-of-week of the first day of the month. Get
00903       ** the day-of-month (zero-origin) of the first "dow" day of the
00904       ** month.
00905       */
00906       d = rulep->r_day - dow;
00907       if (d < 0)
00908          d += DAYSPERWEEK;
00909       for (i = 1; i < rulep->r_week; ++i) {
00910          if (d + DAYSPERWEEK >=
00911             mon_lengths[leapyear][rulep->r_mon - 1])
00912                break;
00913          d += DAYSPERWEEK;
00914       }
00915 
00916       /*
00917       ** "d" is the day-of-month (zero-origin) of the day we want.
00918       */
00919       value += d * SECSPERDAY;
00920       break;
00921    }
00922 
00923    /*
00924    ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
00925    ** question. To get the Epoch-relative time of the specified local
00926    ** time on that day, add the transition time and the current offset
00927    ** from UTC.
00928    */
00929    return value + rulep->r_time + offset;
00930 }
00931 
00932 /*! \note
00933 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
00934 ** appropriate.
00935 */
00936 
00937 static int tzparse(const char *name, struct state *sp, const int lastditch)
00938 {
00939    const char *         stdname;
00940    const char *         dstname;
00941    size_t            stdlen;
00942    size_t            dstlen;
00943    long           stdoffset;
00944    long           dstoffset;
00945    time_t *    atp;
00946    unsigned char *   typep;
00947    char *         cp;
00948    int         load_result;
00949 
00950    INITIALIZE(dstname);
00951    stdname = name;
00952    if (lastditch) {
00953       stdlen = strlen(name);  /* length of standard zone name */
00954       name += stdlen;
00955       if (stdlen >= sizeof sp->chars)
00956          stdlen = (sizeof sp->chars) - 1;
00957       stdoffset = 0;
00958    } else {
00959       if (*name == '<') {
00960          name++;
00961          stdname = name;
00962          name = getqzname(name, '>');
00963          if (*name != '>')
00964             return -1;
00965          stdlen = name - stdname;
00966          name++;
00967       } else {
00968          name = getzname(name);
00969          stdlen = name - stdname;
00970       }
00971       if (*name == '\0')
00972          return -1;
00973       name = getoffset(name, &stdoffset);
00974       if (name == NULL)
00975          return -1;
00976    }
00977    load_result = tzload(TZDEFRULES, sp, FALSE);
00978    if (load_result != 0)
00979       sp->leapcnt = 0;     /* so, we're off a little */
00980    if (*name != '\0') {
00981       if (*name == '<') {
00982          dstname = ++name;
00983          name = getqzname(name, '>');
00984          if (*name != '>')
00985             return -1;
00986          dstlen = name - dstname;
00987          name++;
00988       } else {
00989          dstname = name;
00990          name = getzname(name);
00991          dstlen = name - dstname; /* length of DST zone name */
00992       }
00993       if (*name != '\0' && *name != ',' && *name != ';') {
00994          name = getoffset(name, &dstoffset);
00995          if (name == NULL)
00996             return -1;
00997       } else   dstoffset = stdoffset - SECSPERHOUR;
00998       if (*name == '\0' && load_result != 0)
00999          name = TZDEFRULESTRING;
01000       if (*name == ',' || *name == ';') {
01001          struct rule start;
01002          struct rule end;
01003          int   year;
01004          time_t   janfirst;
01005          time_t      starttime;
01006          time_t      endtime;
01007 
01008          ++name;
01009          if ((name = getrule(name, &start)) == NULL)
01010             return -1;
01011          if (*name++ != ',')
01012             return -1;
01013          if ((name = getrule(name, &end)) == NULL)
01014             return -1;
01015          if (*name != '\0')
01016             return -1;
01017          sp->typecnt = 2;  /* standard time and DST */
01018          /*
01019          ** Two transitions per year, from EPOCH_YEAR forward.
01020          */
01021          sp->ttis[0].tt_gmtoff = -dstoffset;
01022          sp->ttis[0].tt_isdst = 1;
01023          sp->ttis[0].tt_abbrind = stdlen + 1;
01024          sp->ttis[1].tt_gmtoff = -stdoffset;
01025          sp->ttis[1].tt_isdst = 0;
01026          sp->ttis[1].tt_abbrind = 0;
01027          atp = sp->ats;
01028          typep = sp->types;
01029          janfirst = 0;
01030          sp->timecnt = 0;
01031          for (year = EPOCH_YEAR;
01032              sp->timecnt + 2 <= TZ_MAX_TIMES;
01033              ++year) {
01034                time_t   newfirst;
01035 
01036             starttime = transtime(janfirst, year, &start,
01037                stdoffset);
01038             endtime = transtime(janfirst, year, &end,
01039                dstoffset);
01040             if (starttime > endtime) {
01041                *atp++ = endtime;
01042                *typep++ = 1;  /* DST ends */
01043                *atp++ = starttime;
01044                *typep++ = 0;  /* DST begins */
01045             } else {
01046                *atp++ = starttime;
01047                *typep++ = 0;  /* DST begins */
01048                *atp++ = endtime;
01049                *typep++ = 1;  /* DST ends */
01050             }
01051             sp->timecnt += 2;
01052             newfirst = janfirst;
01053             newfirst += year_lengths[isleap(year)] *
01054                SECSPERDAY;
01055             if (newfirst <= janfirst)
01056                break;
01057             janfirst = newfirst;
01058          }
01059       } else {
01060          long  theirstdoffset;
01061          long  theirdstoffset;
01062          long  theiroffset;
01063          int   isdst;
01064          int   i;
01065          int   j;
01066 
01067          if (*name != '\0')
01068             return -1;
01069          /*
01070          ** Initial values of theirstdoffset and theirdstoffset.
01071          */
01072          theirstdoffset = 0;
01073          for (i = 0; i < sp->timecnt; ++i) {
01074             j = sp->types[i];
01075             if (!sp->ttis[j].tt_isdst) {
01076                theirstdoffset =
01077                   -sp->ttis[j].tt_gmtoff;
01078                break;
01079             }
01080          }
01081          theirdstoffset = 0;
01082          for (i = 0; i < sp->timecnt; ++i) {
01083             j = sp->types[i];
01084             if (sp->ttis[j].tt_isdst) {
01085                theirdstoffset =
01086                   -sp->ttis[j].tt_gmtoff;
01087                break;
01088             }
01089          }
01090          /*
01091          ** Initially we're assumed to be in standard time.
01092          */
01093          isdst = FALSE;
01094          theiroffset = theirstdoffset;
01095          /*
01096          ** Now juggle transition times and types
01097          ** tracking offsets as you do.
01098          */
01099          for (i = 0; i < sp->timecnt; ++i) {
01100             j = sp->types[i];
01101             sp->types[i] = sp->ttis[j].tt_isdst;
01102             if (sp->ttis[j].tt_ttisgmt) {
01103                /* No adjustment to transition time */
01104             } else {
01105                /*
01106                ** If summer time is in effect, and the
01107                ** transition time was not specified as
01108                ** standard time, add the summer time
01109                ** offset to the transition time;
01110                ** otherwise, add the standard time
01111                ** offset to the transition time.
01112                */
01113                /*
01114                ** Transitions from DST to DDST
01115                ** will effectively disappear since
01116                ** POSIX provides for only one DST
01117                ** offset.
01118                */
01119                if (isdst && !sp->ttis[j].tt_ttisstd) {
01120                   sp->ats[i] += dstoffset -
01121                      theirdstoffset;
01122                } else {
01123                   sp->ats[i] += stdoffset -
01124                      theirstdoffset;
01125                }
01126             }
01127             theiroffset = -sp->ttis[j].tt_gmtoff;
01128             if (sp->ttis[j].tt_isdst)
01129                theirdstoffset = theiroffset;
01130             else  theirstdoffset = theiroffset;
01131          }
01132          /*
01133          ** Finally, fill in ttis.
01134          ** ttisstd and ttisgmt need not be handled.
01135          */
01136          sp->ttis[0].tt_gmtoff = -stdoffset;
01137          sp->ttis[0].tt_isdst = FALSE;
01138          sp->ttis[0].tt_abbrind = 0;
01139          sp->ttis[1].tt_gmtoff = -dstoffset;
01140          sp->ttis[1].tt_isdst = TRUE;
01141          sp->ttis[1].tt_abbrind = stdlen + 1;
01142          sp->typecnt = 2;
01143       }
01144    } else {
01145       dstlen = 0;
01146       sp->typecnt = 1;     /* only standard time */
01147       sp->timecnt = 0;
01148       sp->ttis[0].tt_gmtoff = -stdoffset;
01149       sp->ttis[0].tt_isdst = 0;
01150       sp->ttis[0].tt_abbrind = 0;
01151    }
01152    sp->charcnt = stdlen + 1;
01153    if (dstlen != 0)
01154       sp->charcnt += dstlen + 1;
01155    if ((size_t) sp->charcnt > sizeof sp->chars)
01156       return -1;
01157    cp = sp->chars;
01158    (void) strncpy(cp, stdname, stdlen);
01159    cp += stdlen;
01160    *cp++ = '\0';
01161    if (dstlen != 0) {
01162       (void) strncpy(cp, dstname, dstlen);
01163       *(cp + dstlen) = '\0';
01164    }
01165    return 0;
01166 }
01167 
01168 static int gmtload(struct state *sp)
01169 {
01170    if (tzload(gmt, sp, TRUE) != 0)
01171       return tzparse(gmt, sp, TRUE);
01172    else
01173       return -1;
01174 }
01175 
01176 static const struct state *ast_tzset(const char *zone)
01177 {
01178    struct state *sp;
01179 
01180    if (ast_strlen_zero(zone))
01181       zone = "/etc/localtime";
01182 
01183    AST_LIST_LOCK(&zonelist);
01184    AST_LIST_TRAVERSE(&zonelist, sp, list) {
01185       if (!strcmp(sp->name, zone)) {
01186          AST_LIST_UNLOCK(&zonelist);
01187          return sp;
01188       }
01189    }
01190    AST_LIST_UNLOCK(&zonelist);
01191 
01192    if (!(sp = ast_calloc(1, sizeof *sp)))
01193       return NULL;
01194 
01195    if (tzload(zone, sp, TRUE) != 0) {
01196       if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0)
01197          (void) gmtload(sp);
01198    }
01199    ast_copy_string(sp->name, zone, sizeof(sp->name));
01200    AST_LIST_LOCK(&zonelist);
01201    AST_LIST_INSERT_TAIL(&zonelist, sp, list);
01202    AST_LIST_UNLOCK(&zonelist);
01203    return sp;
01204 }
01205 
01206 /*! \note
01207 ** The easy way to behave "as if no library function calls" localtime
01208 ** is to not call it--so we drop its guts into "localsub", which can be
01209 ** freely called. (And no, the PANS doesn't require the above behavior--
01210 ** but it *is* desirable.)
01211 **
01212 ** The unused offset argument is for the benefit of mktime variants.
01213 */
01214 
01215 static struct ast_tm *localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
01216 {
01217    const struct ttinfo *   ttisp;
01218    int         i;
01219    struct ast_tm *      result;
01220    struct timeval t;
01221    memcpy(&t, timep, sizeof(t));
01222 
01223    if (sp == NULL)
01224       return gmtsub(timep, offset, tmp);
01225    if ((sp->goback && t.tv_sec < sp->ats[0]) ||
01226       (sp->goahead && t.tv_sec > sp->ats[sp->timecnt - 1])) {
01227          struct timeval newt = t;
01228          time_t      seconds;
01229          time_t      tcycles;
01230          int_fast64_t   icycles;
01231 
01232          if (t.tv_sec < sp->ats[0])
01233             seconds = sp->ats[0] - t.tv_sec;
01234          else  seconds = t.tv_sec - sp->ats[sp->timecnt - 1];
01235          --seconds;
01236          tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
01237          ++tcycles;
01238          icycles = tcycles;
01239          if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
01240             return NULL;
01241          seconds = icycles;
01242          seconds *= YEARSPERREPEAT;
01243          seconds *= AVGSECSPERYEAR;
01244          if (t.tv_sec < sp->ats[0])
01245             newt.tv_sec += seconds;
01246          else  newt.tv_sec -= seconds;
01247          if (newt.tv_sec < sp->ats[0] ||
01248             newt.tv_sec > sp->ats[sp->timecnt - 1])
01249                return NULL;   /* "cannot happen" */
01250          result = localsub(&newt, offset, tmp, sp);
01251          if (result == tmp) {
01252             time_t   newy;
01253 
01254             newy = tmp->tm_year;
01255             if (t.tv_sec < sp->ats[0])
01256                newy -= icycles * YEARSPERREPEAT;
01257             else
01258                newy += icycles * YEARSPERREPEAT;
01259             tmp->tm_year = newy;
01260             if (tmp->tm_year != newy)
01261                return NULL;
01262          }
01263          return result;
01264    }
01265    if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) {
01266       i = 0;
01267       while (sp->ttis[i].tt_isdst) {
01268          if (++i >= sp->typecnt) {
01269             i = 0;
01270             break;
01271          }
01272       }
01273    } else {
01274       int   lo = 1;
01275       int   hi = sp->timecnt;
01276 
01277       while (lo < hi) {
01278          int   mid = (lo + hi) >> 1;
01279 
01280          if (t.tv_sec < sp->ats[mid])
01281             hi = mid;
01282          else
01283             lo = mid + 1;
01284       }
01285       i = (int) sp->types[lo - 1];
01286    }
01287    ttisp = &sp->ttis[i];
01288    /*
01289    ** To get (wrong) behavior that's compatible with System V Release 2.0
01290    ** you'd replace the statement below with
01291    ** t += ttisp->tt_gmtoff;
01292    ** timesub(&t, 0L, sp, tmp);
01293    */
01294    result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
01295    tmp->tm_isdst = ttisp->tt_isdst;
01296 #ifndef SOLARIS /* Solaris doesn't have this element */
01297    tmp->tm_gmtoff = ttisp->tt_gmtoff;
01298 #endif
01299 #ifdef TM_ZONE
01300    tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
01301 #endif /* defined TM_ZONE */
01302    tmp->tm_usec = timep->tv_usec;
01303    return result;
01304 }
01305 
01306 struct ast_tm *ast_localtime(const struct timeval *timep, struct ast_tm *tmp, const char *zone)
01307 {
01308    const struct state *sp = ast_tzset(zone);
01309    memset(tmp, 0, sizeof(*tmp));
01310    return sp ? localsub(timep, 0L, tmp, sp) : NULL;
01311 }
01312 
01313 /*
01314 ** This function provides informaton about daylight savings time 
01315 ** for the given timezone.  This includes whether it can determine 
01316 ** if daylight savings is used for this timezone, the UTC times for 
01317 ** when daylight savings transitions, and the offset in seconds from 
01318 ** UTC. 
01319 */
01320 
01321 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)
01322 {
01323    int i;   
01324    int transition1 = -1;
01325    int transition2 = -1;
01326    time_t      seconds;
01327    int  bounds_exceeded = 0;
01328    time_t  t = *timep;
01329    const struct state *sp;
01330    
01331    if (NULL == dst_enabled)
01332       return;
01333    *dst_enabled = 0;
01334 
01335    if (NULL == dst_start || NULL == dst_end || NULL == gmt_off)
01336       return;
01337 
01338    *gmt_off = 0; 
01339    
01340    sp = ast_tzset(zone);
01341    if (NULL == sp) 
01342       return;
01343    
01344    /* If the desired time exceeds the bounds of the defined time transitions  
01345    * then give give up on determining DST info and simply look for gmt offset 
01346    * This requires that I adjust the given time using increments of Gregorian 
01347    * repeats to place the time within the defined time transitions in the 
01348    * timezone structure.  
01349    */
01350    if ((sp->goback && t < sp->ats[0]) ||
01351          (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
01352       time_t      tcycles;
01353       int_fast64_t   icycles;
01354 
01355       if (t < sp->ats[0])
01356          seconds = sp->ats[0] - t;
01357       else  seconds = t - sp->ats[sp->timecnt - 1];
01358       --seconds;
01359       tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
01360       ++tcycles;
01361       icycles = tcycles;
01362       if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
01363          return;
01364       seconds = icycles;
01365       seconds *= YEARSPERREPEAT;
01366       seconds *= AVGSECSPERYEAR;
01367       if (t < sp->ats[0])
01368          t += seconds;
01369       else
01370          t -= seconds;
01371       
01372       if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1])
01373          return;  /* "cannot happen" */
01374 
01375       bounds_exceeded = 1;
01376    }
01377 
01378    if (sp->timecnt == 0 || t < sp->ats[0]) {
01379       /* I have no transition times or I'm before time */
01380       *dst_enabled = 0;
01381       /* Find where I can get gmtoff */
01382       i = 0;
01383       while (sp->ttis[i].tt_isdst)
01384          if (++i >= sp->typecnt) {
01385          i = 0;
01386          break;
01387          }
01388          *gmt_off = sp->ttis[i].tt_gmtoff;
01389          return;
01390    } 
01391 
01392    for (i = 1; i < sp->timecnt; ++i) {
01393       if (t < sp->ats[i]) {
01394          transition1 = sp->types[i - 1];
01395          transition2 = sp->types[i];
01396          break;
01397       } 
01398    }
01399    /* if I found transition times that do not bounded the given time and these correspond to 
01400       or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */
01401    if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 ||
01402          (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) {
01403       *dst_enabled = 0;
01404       *gmt_off     = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff;
01405    } else {
01406       /* I have valid daylight savings information. */
01407       if(sp->ttis[transition2].tt_isdst) 
01408          *gmt_off = sp->ttis[transition1].tt_gmtoff;
01409       else 
01410          *gmt_off = sp->ttis[transition2].tt_gmtoff;
01411 
01412       /* If I adjusted the time earlier, indicate that the dst is invalid */
01413       if (!bounds_exceeded) {
01414          *dst_enabled = 1;
01415          /* Determine which of the bounds is the start of daylight savings and which is the end */
01416          if(sp->ttis[transition2].tt_isdst) {
01417             *dst_start = sp->ats[i];
01418             *dst_end = sp->ats[i -1];
01419          } else {
01420             *dst_start = sp->ats[i -1];
01421             *dst_end = sp->ats[i];
01422          }
01423       }
01424    }  
01425    return;
01426 }
01427 
01428 /*
01429 ** gmtsub is to gmtime as localsub is to localtime.
01430 */
01431 
01432 static struct ast_tm *gmtsub(const struct timeval *timep, const long offset, struct ast_tm *tmp)
01433 {
01434    struct ast_tm *   result;
01435    struct state *sp;
01436 
01437    AST_LIST_LOCK(&zonelist);
01438    AST_LIST_TRAVERSE(&zonelist, sp, list) {
01439       if (!strcmp(sp->name, "UTC"))
01440          break;
01441    }
01442 
01443    if (!sp) {
01444       if (!(sp = (struct state *) ast_calloc(1, sizeof *sp)))
01445          return NULL;
01446       gmtload(sp);
01447       AST_LIST_INSERT_TAIL(&zonelist, sp, list);
01448    }
01449    AST_LIST_UNLOCK(&zonelist);
01450 
01451    result = timesub(timep, offset, sp, tmp);
01452 #ifdef TM_ZONE
01453    /*
01454    ** Could get fancy here and deliver something such as
01455    ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
01456    ** but this is no time for a treasure hunt.
01457    */
01458    if (offset != 0)
01459       tmp->TM_ZONE = "    ";
01460    else
01461       tmp->TM_ZONE = sp->chars;
01462 #endif /* defined TM_ZONE */
01463    return result;
01464 }
01465 
01466 /*! \brief
01467 ** Return the number of leap years through the end of the given year
01468 ** where, to make the math easy, the answer for year zero is defined as zero.
01469 */
01470 
01471 static int leaps_thru_end_of(const int y)
01472 {
01473    return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
01474       -(leaps_thru_end_of(-(y + 1)) + 1);
01475 }
01476 
01477 static struct ast_tm *timesub(const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
01478 {
01479    const struct lsinfo *   lp;
01480    time_t         tdays;
01481    int         idays;   /* unsigned would be so 2003 */
01482    long        rem;
01483    int            y;
01484    const int *    ip;
01485    long        corr;
01486    int         hit;
01487    int         i;
01488    long  seconds;
01489 
01490 
01491    corr = 0;
01492    hit = 0;
01493    i = (sp == NULL) ? 0 : sp->leapcnt;
01494    while (--i >= 0) {
01495       lp = &sp->lsis[i];
01496       if (timep->tv_sec >= lp->ls_trans) {
01497          if (timep->tv_sec == lp->ls_trans) {
01498             hit = ((i == 0 && lp->ls_corr > 0) ||
01499                lp->ls_corr > sp->lsis[i - 1].ls_corr);
01500             if (hit)
01501                while (i > 0 &&
01502                   sp->lsis[i].ls_trans ==
01503                   sp->lsis[i - 1].ls_trans + 1 &&
01504                   sp->lsis[i].ls_corr ==
01505                   sp->lsis[i - 1].ls_corr + 1) {
01506                      ++hit;
01507                      --i;
01508                }
01509          }
01510          corr = lp->ls_corr;
01511          break;
01512       }
01513    }
01514    y = EPOCH_YEAR;
01515    tdays = timep->tv_sec / SECSPERDAY;
01516    rem = timep->tv_sec - tdays * SECSPERDAY;
01517    while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
01518       int      newy;
01519       time_t   tdelta;
01520       int   idelta;
01521       int   leapdays;
01522 
01523       tdelta = tdays / DAYSPERLYEAR;
01524       idelta = tdelta;
01525       if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
01526          return NULL;
01527       if (idelta == 0)
01528          idelta = (tdays < 0) ? -1 : 1;
01529       newy = y;
01530       if (increment_overflow(&newy, idelta))
01531          return NULL;
01532       leapdays = leaps_thru_end_of(newy - 1) -
01533          leaps_thru_end_of(y - 1);
01534       tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
01535       tdays -= leapdays;
01536       y = newy;
01537    }
01538 
01539    seconds = tdays * SECSPERDAY + 0.5;
01540    tdays = seconds / SECSPERDAY;
01541    rem += seconds - tdays * SECSPERDAY;
01542 
01543    /*
01544    ** Given the range, we can now fearlessly cast...
01545    */
01546    idays = tdays;
01547    rem += offset - corr;
01548    while (rem < 0) {
01549       rem += SECSPERDAY;
01550       --idays;
01551    }
01552    while (rem >= SECSPERDAY) {
01553       rem -= SECSPERDAY;
01554       ++idays;
01555    }
01556    while (idays < 0) {
01557       if (increment_overflow(&y, -1))
01558          return NULL;
01559       idays += year_lengths[isleap(y)];
01560    }
01561    while (idays >= year_lengths[isleap(y)]) {
01562       idays -= year_lengths[isleap(y)];
01563       if (increment_overflow(&y, 1))
01564          return NULL;
01565    }
01566    tmp->tm_year = y;
01567    if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
01568       return NULL;
01569    tmp->tm_yday = idays;
01570    /*
01571    ** The "extra" mods below avoid overflow problems.
01572    */
01573    tmp->tm_wday = EPOCH_WDAY +
01574       ((y - EPOCH_YEAR) % DAYSPERWEEK) *
01575       (DAYSPERNYEAR % DAYSPERWEEK) +
01576       leaps_thru_end_of(y - 1) -
01577       leaps_thru_end_of(EPOCH_YEAR - 1) +
01578       idays;
01579    tmp->tm_wday %= DAYSPERWEEK;
01580    if (tmp->tm_wday < 0)
01581       tmp->tm_wday += DAYSPERWEEK;
01582    tmp->tm_hour = (int) (rem / SECSPERHOUR);
01583    rem %= SECSPERHOUR;
01584    tmp->tm_min = (int) (rem / SECSPERMIN);
01585    /*
01586    ** A positive leap second requires a special
01587    ** representation. This uses "... ??:59:60" et seq.
01588    */
01589    tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
01590    ip = mon_lengths[isleap(y)];
01591    for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
01592       idays -= ip[tmp->tm_mon];
01593    tmp->tm_mday = (int) (idays + 1);
01594    tmp->tm_isdst = 0;
01595 #ifdef TM_GMTOFF
01596    tmp->TM_GMTOFF = offset;
01597 #endif /* defined TM_GMTOFF */
01598    tmp->tm_usec = timep->tv_usec;
01599    return tmp;
01600 }
01601 
01602 /*! \note
01603 ** Adapted from code provided by Robert Elz, who writes:
01604 ** The "best" way to do mktime I think is based on an idea of Bob
01605 ** Kridle's (so its said...) from a long time ago.
01606 ** It does a binary search of the time_t space. Since time_t's are
01607 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
01608 ** would still be very reasonable).
01609 */
01610 
01611 /*! \brief
01612 ** Simplified normalize logic courtesy Paul Eggert.
01613 */
01614 
01615 static int increment_overflow(int *number, int delta)
01616 {
01617    int   number0;
01618 
01619    number0 = *number;
01620    *number += delta;
01621    return (*number < number0) != (delta < 0);
01622 }
01623 
01624 static int long_increment_overflow(long *number, int delta)
01625 {
01626    long  number0;
01627 
01628    number0 = *number;
01629    *number += delta;
01630    return (*number < number0) != (delta < 0);
01631 }
01632 
01633 static int normalize_overflow(int *tensptr, int *unitsptr, const int base)
01634 {
01635    int   tensdelta;
01636 
01637    tensdelta = (*unitsptr >= 0) ?
01638       (*unitsptr / base) :
01639       (-1 - (-1 - *unitsptr) / base);
01640    *unitsptr -= tensdelta * base;
01641    return increment_overflow(tensptr, tensdelta);
01642 }
01643 
01644 static int long_normalize_overflow(long *tensptr, int *unitsptr, const int base)
01645 {
01646    int   tensdelta;
01647 
01648    tensdelta = (*unitsptr >= 0) ?
01649       (*unitsptr / base) :
01650       (-1 - (-1 - *unitsptr) / base);
01651    *unitsptr -= tensdelta * base;
01652    return long_increment_overflow(tensptr, tensdelta);
01653 }
01654 
01655 static int tmcomp(const struct ast_tm *atmp, const struct ast_tm *btmp)
01656 {
01657    int   result;
01658 
01659    if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
01660       (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
01661       (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
01662       (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
01663       (result = (atmp->tm_min - btmp->tm_min)) == 0 &&
01664       (result = (atmp->tm_sec - btmp->tm_sec)) == 0)
01665          result = atmp->tm_usec - btmp->tm_usec;
01666    return result;
01667 }
01668 
01669 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)
01670 {
01671    int         dir;
01672    int         i, j;
01673    int         saved_seconds;
01674    long        li;
01675    time_t         lo;
01676    time_t         hi;
01677    long           y;
01678    struct timeval       newt = { 0, 0 };
01679    struct timeval       t = { 0, 0 };
01680    struct ast_tm        yourtm, mytm;
01681 
01682    *okayp = FALSE;
01683    yourtm = *tmp;
01684    if (do_norm_secs) {
01685       if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
01686          SECSPERMIN))
01687             return WRONG;
01688    }
01689    if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
01690       return WRONG;
01691    if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
01692       return WRONG;
01693    y = yourtm.tm_year;
01694    if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
01695       return WRONG;
01696    /*
01697    ** Turn y into an actual year number for now.
01698    ** It is converted back to an offset from TM_YEAR_BASE later.
01699    */
01700    if (long_increment_overflow(&y, TM_YEAR_BASE))
01701       return WRONG;
01702    while (yourtm.tm_mday <= 0) {
01703       if (long_increment_overflow(&y, -1))
01704          return WRONG;
01705       li = y + (1 < yourtm.tm_mon);
01706       yourtm.tm_mday += year_lengths[isleap(li)];
01707    }
01708    while (yourtm.tm_mday > DAYSPERLYEAR) {
01709       li = y + (1 < yourtm.tm_mon);
01710       yourtm.tm_mday -= year_lengths[isleap(li)];
01711       if (long_increment_overflow(&y, 1))
01712          return WRONG;
01713    }
01714    for ( ; ; ) {
01715       i = mon_lengths[isleap(y)][yourtm.tm_mon];
01716       if (yourtm.tm_mday <= i)
01717          break;
01718       yourtm.tm_mday -= i;
01719       if (++yourtm.tm_mon >= MONSPERYEAR) {
01720          yourtm.tm_mon = 0;
01721          if (long_increment_overflow(&y, 1))
01722             return WRONG;
01723       }
01724    }
01725    if (long_increment_overflow(&y, -TM_YEAR_BASE))
01726       return WRONG;
01727    yourtm.tm_year = y;
01728    if (yourtm.tm_year != y)
01729       return WRONG;
01730    if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
01731       saved_seconds = 0;
01732    else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
01733       /*
01734       ** We can't set tm_sec to 0, because that might push the
01735       ** time below the minimum representable time.
01736       ** Set tm_sec to 59 instead.
01737       ** This assumes that the minimum representable time is
01738       ** not in the same minute that a leap second was deleted from,
01739       ** which is a safer assumption than using 58 would be.
01740       */
01741       if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
01742          return WRONG;
01743       saved_seconds = yourtm.tm_sec;
01744       yourtm.tm_sec = SECSPERMIN - 1;
01745    } else {
01746       saved_seconds = yourtm.tm_sec;
01747       yourtm.tm_sec = 0;
01748    }
01749    /*
01750    ** Do a binary search (this works whatever time_t's type is).
01751    */
01752    if (!TYPE_SIGNED(time_t)) {
01753       lo = 0;
01754       hi = lo - 1;
01755    } else if (!TYPE_INTEGRAL(time_t)) {
01756       if (sizeof(time_t) > sizeof(float))
01757          hi = (time_t) DBL_MAX;
01758       else  hi = (time_t) FLT_MAX;
01759       lo = -hi;
01760    } else {
01761       lo = 1;
01762       for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
01763          lo *= 2;
01764       hi = -(lo + 1);
01765    }
01766    for ( ; ; ) {
01767       t.tv_sec = lo / 2 + hi / 2;
01768       if (t.tv_sec < lo)
01769          t.tv_sec = lo;
01770       else if (t.tv_sec > hi)
01771          t.tv_sec = hi;
01772       if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
01773          /*
01774          ** Assume that t is too extreme to be represented in
01775          ** a struct ast_tm; arrange things so that it is less
01776          ** extreme on the next pass.
01777          */
01778          dir = (t.tv_sec > 0) ? 1 : -1;
01779       } else   dir = tmcomp(&mytm, &yourtm);
01780       if (dir != 0) {
01781          if (t.tv_sec == lo) {
01782             ++t.tv_sec;
01783             if (t.tv_sec <= lo)
01784                return WRONG;
01785             ++lo;
01786          } else if (t.tv_sec == hi) {
01787             --t.tv_sec;
01788             if (t.tv_sec >= hi)
01789                return WRONG;
01790             --hi;
01791          }
01792          if (lo > hi)
01793             return WRONG;
01794          if (dir > 0)
01795             hi = t.tv_sec;
01796          else  lo = t.tv_sec;
01797          continue;
01798       }
01799       if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
01800          break;
01801       /*
01802       ** Right time, wrong type.
01803       ** Hunt for right time, right type.
01804       ** It's okay to guess wrong since the guess
01805       ** gets checked.
01806       */
01807       /*
01808       ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
01809       */
01810       for (i = sp->typecnt - 1; i >= 0; --i) {
01811          if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
01812             continue;
01813          for (j = sp->typecnt - 1; j >= 0; --j) {
01814             if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
01815                continue;
01816             newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff -
01817                sp->ttis[i].tt_gmtoff;
01818             if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
01819                continue;
01820             if (tmcomp(&mytm, &yourtm) != 0)
01821                continue;
01822             if (mytm.tm_isdst != yourtm.tm_isdst)
01823                continue;
01824             /*
01825             ** We have a match.
01826             */
01827             t = newt;
01828             goto label;
01829          }
01830       }
01831       return WRONG;
01832    }
01833 label:
01834    newt.tv_sec = t.tv_sec + saved_seconds;
01835    if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0))
01836       return WRONG;
01837    t.tv_sec = newt.tv_sec;
01838    if ((*funcp)(&t, offset, tmp, sp))
01839       *okayp = TRUE;
01840    return t;
01841 }
01842 
01843 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)
01844 {
01845    struct timeval t;
01846 
01847    /*! \note
01848    ** First try without normalization of seconds
01849    ** (in case tm_sec contains a value associated with a leap second).
01850    ** If that fails, try with normalization of seconds.
01851    */
01852    t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
01853    return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
01854 }
01855 
01856 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)
01857 {
01858    struct timeval       t;
01859    int         samei, otheri;
01860    int         sameind, otherind;
01861    int         i;
01862    int         nseen;
01863    int            seen[TZ_MAX_TYPES];
01864    int            types[TZ_MAX_TYPES];
01865    int            okay;
01866 
01867    if (tmp->tm_isdst > 1)
01868       tmp->tm_isdst = 1;
01869    t = time2(tmp, funcp, offset, &okay, sp);
01870 #ifdef PCTS
01871    /*
01872    ** PCTS code courtesy Grant Sullivan.
01873    */
01874    if (okay)
01875       return t;
01876    if (tmp->tm_isdst < 0)
01877       tmp->tm_isdst = 0;   /* reset to std and try again */
01878 #endif /* defined PCTS */
01879 #ifndef PCTS
01880    if (okay || tmp->tm_isdst < 0)
01881       return t;
01882 #endif /* !defined PCTS */
01883    /*
01884    ** We're supposed to assume that somebody took a time of one type
01885    ** and did some math on it that yielded a "struct ast_tm" that's bad.
01886    ** We try to divine the type they started from and adjust to the
01887    ** type they need.
01888    */
01889    if (sp == NULL)
01890       return WRONG;
01891    for (i = 0; i < sp->typecnt; ++i)
01892       seen[i] = FALSE;
01893    nseen = 0;
01894    for (i = sp->timecnt - 1; i >= 0; --i)
01895       if (!seen[sp->types[i]]) {
01896          seen[sp->types[i]] = TRUE;
01897          types[nseen++] = sp->types[i];
01898       }
01899    for (sameind = 0; sameind < nseen; ++sameind) {
01900       samei = types[sameind];
01901       if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
01902          continue;
01903       for (otherind = 0; otherind < nseen; ++otherind) {
01904          otheri = types[otherind];
01905          if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
01906             continue;
01907          tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
01908                sp->ttis[samei].tt_gmtoff;
01909          tmp->tm_isdst = !tmp->tm_isdst;
01910          t = time2(tmp, funcp, offset, &okay, sp);
01911          if (okay)
01912             return t;
01913          tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
01914                sp->ttis[samei].tt_gmtoff;
01915          tmp->tm_isdst = !tmp->tm_isdst;
01916       }
01917    }
01918    return WRONG;
01919 }
01920 
01921 struct timeval ast_mktime(struct ast_tm *tmp, const char *zone)
01922 {
01923    const struct state *sp;
01924    if (!(sp = ast_tzset(zone)))
01925       return WRONG;
01926    return time1(tmp, localsub, 0L, sp);
01927 }
01928 
01929 int ast_strftime(char *buf, size_t len, const char *tmp, const struct ast_tm *tm)
01930 {
01931    size_t fmtlen = strlen(tmp) + 1;
01932    char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt;
01933    int decimals = -1, i, res;
01934    long fraction;
01935 
01936    if (!format)
01937       return -1;
01938    for (; *tmp; tmp++) {
01939       if (*tmp == '%') {
01940          switch (tmp[1]) {
01941          case '1':
01942          case '2':
01943          case '3':
01944          case '4':
01945          case '5':
01946          case '6':
01947             if (tmp[2] != 'q')
01948                goto defcase;
01949             decimals = tmp[1] - '0';
01950             tmp++;
01951             /* Fall through */
01952          case 'q': /* Milliseconds */
01953             if (decimals == -1)
01954                decimals = 3;
01955 
01956             /* Juggle some memory to fit the item */
01957             newfmt = ast_realloc(format, fmtlen + decimals);
01958             if (!newfmt) {
01959                ast_free(format);
01960                return -1;
01961             }
01962             fptr = fptr - format + newfmt;
01963             format = newfmt;
01964             fmtlen += decimals;
01965 
01966             /* Reduce the fraction of time to the accuracy needed */
01967             for (i = 6, fraction = tm->tm_usec; i > decimals; i--)
01968                fraction /= 10;
01969             fptr += sprintf(fptr, "%0*ld", decimals, fraction);
01970 
01971             /* Reset, in case more than one 'q' specifier exists */
01972             decimals = -1;
01973             tmp++;
01974             break;
01975          default:
01976             goto defcase;
01977          }
01978       } else
01979 defcase: *fptr++ = *tmp;
01980    }
01981    *fptr = '\0';
01982 #undef strftime
01983    res = (int)strftime(buf, len, format, (struct tm *)tm);
01984    ast_free(format);
01985    return res;
01986 }
01987 
01988 char *ast_strptime(const char *s, const char *format, struct ast_tm *tm)
01989 {
01990    struct tm tm2 = { 0, };
01991    char *res = strptime(s, format, &tm2);
01992    memcpy(tm, &tm2, sizeof(*tm));
01993    tm->tm_usec = 0;
01994    /* strptime(3) doesn't set .tm_isdst correctly, so to force ast_mktime(3)
01995     * to deal with it correctly, we set it to -1. */
01996    tm->tm_isdst = -1;
01997    return res;
01998 }
01999