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