Wed Jan 8 2020 09:49:48

Asterisk developer's documentation


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