Fri Aug 17 00:17:17 2018

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

Generated on 17 Aug 2018 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1