Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
localtime.c File Reference
#include "asterisk.h"
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <float.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include "private.h"
#include "tzfile.h"
#include "asterisk/_private.h"
#include "asterisk/lock.h"
#include "asterisk/localtime.h"
#include "asterisk/strings.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/test.h"
Include dependency graph for localtime.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  locale_entry
 
struct  localelist
 
struct  lsinfo
 leap second information More...
 
struct  rule
 
struct  state
 
struct  ttinfo
 time type information More...
 
struct  zonelist
 

Macros

#define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
 
#define DAY_OF_YEAR   1 /* n - day of year */
 
#define JULIAN_DAY   0 /* Jn - Julian day */
 
#define MONTH_NTH_DAY_OF_WEEK   2 /* Mm.n.d - month, week, day of week */
 
#define MY_TZNAME_MAX   255
 
#define OPEN_MODE   O_RDONLY
 
#define SP_HEAP_FREE(sp)   do {} while (0)
 
#define SP_HEAP_INIT(sp)
 
#define SP_STACK_CHECK(sp)   ((sp)->wd[0] == SP_STACK_FLAG)
 
#define SP_STACK_FLAG   INT_MIN
 
#define SP_STACK_INIT(sp)
 
#define TZ_ABBR_CHAR_SET   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
 
#define TZ_ABBR_ERR_CHAR   '_'
 
#define TZ_ABBR_MAX_LEN   16
 
#define TZ_STRLEN_MAX   255
 
#define TZDEFRULESTRING   ",M4.1.0,M10.5.0"
 

Functions

static void add_notify (struct state *sp, const char *path)
 
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)
 
struct ast_tmast_localtime (const struct timeval *timep, struct ast_tm *tmp, const char *zone)
 Timezone-independent version of localtime_r(3). More...
 
void ast_localtime_wakeup_monitor (struct ast_test *info)
 
struct timeval ast_mktime (struct ast_tm *tmp, const char *zone)
 Timezone-independent version of mktime(3). More...
 
const char * ast_setlocale (const char *locale)
 Set the thread-local representation of the current locale. More...
 
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 strftime(3), with the addition of q, which specifies microseconds. More...
 
int ast_strftime_locale (char *buf, size_t len, const char *tmp, const struct ast_tm *tm, const char *locale)
 
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. More...
 
char * ast_strptime_locale (const char *s, const char *format, struct ast_tm *tm, const char *locale)
 
static const struct stateast_tzset (const char *zone)
 
void clean_time_zones (void)
 
static void common_startup (void)
 
static long detzcode (const char *const codep)
 
static time_t detzcode64 (const char *const codep)
 
static int differ_by_repeat (const time_t t1, const time_t t0)
 
static struct locale_entryfind_by_locale (locale_t locale)
 
static struct locale_entryfind_by_name (const char *name)
 
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 within a specified range; if it is not, return NULL. Otherwise, return a pointer to the first character not part of the number. More...
 
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. More...
 
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 is located. Return a pointer to the delimiter. More...
 
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 for the format of "date" and "time". If a valid rule is not found, return NULL. Otherwise, return a pointer to the first character not part of the rule. More...
 
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, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the number of seconds. More...
 
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 zone name is found. Return a pointer to that character. More...
 
static int gmtload (struct state *sp)
 
static struct ast_tmgmtsub (const struct timeval *timep, const long offset, struct ast_tm *tmp)
 
static int increment_overflow (int *number, int delta)
 Simplified normalize logic courtesy Paul Eggert. More...
 
static void * inotify_daemon (void *data)
 
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, the answer for year zero is defined as zero. More...
 
static struct ast_tmlocalsub (const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
 
static int long_increment_overflow (long *number, int delta)
 
static int long_normalize_overflow (long *tensptr, int *unitsptr, const int base)
 
static int normalize_overflow (int *tensptr, int *unitsptr, const int base)
 
static long detzcode P ((const char *codep))
 
static int differ_by_repeat P ((time_t t1, time_t t0))
 
static const char *getzname P ((const char *strp))
 
static const char *getqzname P ((const char *strp, const int delim))
 
static const char *getnum P ((const char *strp, int *nump, int min, int max))
 
static const char *getsecs P ((const char *strp, long *secsp))
 
static const char *getoffset P ((const char *strp, long *offsetp))
 
static const char *getrule P ((const char *strp, struct rule *rulep))
 
static int gmtload P ((struct state *sp))
 
static struct ast_tm *gmtsub P ((const struct timeval *timep, long offset, struct ast_tm *tmp))
 
static struct ast_tm *localsub P ((const struct timeval *timep, long offset, struct ast_tm *tmp, const struct state *sp))
 
static int increment_overflow P ((int *number, int delta))
 
static int leaps_thru_end_of P ((int y))
 
static int long_increment_overflow P ((long *number, int delta))
 
static int long_normalize_overflow P ((long *tensptr, int *unitsptr, const int base))
 
static int normalize_overflow P ((int *tensptr, int *unitsptr, const int base))
 
static struct timeval time1 P ((struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, const struct state *sp))
 
static struct timeval time2sub P ((struct ast_tm *tmp, struct ast_tm *(*funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp))
 
static struct timeval time2 P ((struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp))
 
static struct ast_tm *timesub P ((const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp))
 
static int tmcomp P ((const struct ast_tm *atmp, const struct ast_tm *btmp))
 
static time_t transtime P ((time_t janfirst, int year, const struct rule *rulep, long offset))
 
static int tzload P ((const char *name, struct state *sp, int doextend))
 
static int tzparse P ((const char *name, struct state *sp, int lastditch))
 
static struct statesstate_alloc (void)
 
static void sstate_free (struct state *p)
 
static const char * store_by_locale (locale_t prevlocale)
 
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)
 
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)
 
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)
 
static struct ast_tmtimesub (const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
 
static int tmcomp (const struct ast_tm *atmp, const struct ast_tm *btmp)
 
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. More...
 
static int tzload (const char *name, struct state *const sp, const int doextend)
 
static int tzparse (const char *name, struct state *sp, const int lastditch)
 

Variables

static char elsieid [] = "@(#)localtime.c 8.5"
 
static const char gmt [] = "GMT"
 
static ast_cond_t initialization
 
static ast_mutex_t initialization_lock
 
static int inotify_fd = -1
 
static pthread_t inotify_thread = AST_PTHREADT_NULL
 
static struct localelist localelist = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static const int mon_lengths [2][MONSPERYEAR]
 
static struct ast_testtest = NULL
 
static const struct timeval WRONG = { 0, 0 }
 
static const int year_lengths [2]
 
static struct zonelist zonelist = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 

Detailed Description

Multi-timezone Localtime code

The original source from this file may be obtained from ftp://elsie.nci.nih.gov/pub/

Definition in file localtime.c.

Macro Definition Documentation

◆ BIGGEST

#define BIGGEST (   a,
  b 
)    (((a) > (b)) ? (a) : (b))

Definition at line 146 of file localtime.c.

◆ DAY_OF_YEAR

#define DAY_OF_YEAR   1 /* n - day of year */

Definition at line 257 of file localtime.c.

Referenced by getrule(), and transtime().

◆ JULIAN_DAY

#define JULIAN_DAY   0 /* Jn - Julian day */

Definition at line 256 of file localtime.c.

Referenced by getrule(), and transtime().

◆ MONTH_NTH_DAY_OF_WEEK

#define MONTH_NTH_DAY_OF_WEEK   2 /* Mm.n.d - month, week, day of week */

Definition at line 258 of file localtime.c.

Referenced by getrule(), and transtime().

◆ MY_TZNAME_MAX

#define MY_TZNAME_MAX   255

Definition at line 152 of file localtime.c.

◆ OPEN_MODE

#define OPEN_MODE   O_RDONLY

Definition at line 107 of file localtime.c.

Referenced by tzload().

◆ SP_HEAP_FREE

#define SP_HEAP_FREE (   sp)    do {} while (0)

Definition at line 199 of file localtime.c.

Referenced by sstate_free().

◆ SP_HEAP_INIT

#define SP_HEAP_INIT (   sp)
Value:
do { \
(sp)->wd[0] = -1; \
(sp)->wd[1] = -1; \
} while (0)

Definition at line 195 of file localtime.c.

Referenced by sstate_alloc().

◆ SP_STACK_CHECK

#define SP_STACK_CHECK (   sp)    ((sp)->wd[0] == SP_STACK_FLAG)

Definition at line 194 of file localtime.c.

Referenced by add_notify().

◆ SP_STACK_FLAG

#define SP_STACK_FLAG   INT_MIN

Definition at line 189 of file localtime.c.

◆ SP_STACK_INIT

#define SP_STACK_INIT (   sp)
Value:
do { \
(sp).wd[0] = SP_STACK_FLAG; \
} while (0)
#define SP_STACK_FLAG
Definition: localtime.c:189

Definition at line 191 of file localtime.c.

Referenced by tzload().

◆ TZ_ABBR_CHAR_SET

#define TZ_ABBR_CHAR_SET   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"

Definition at line 91 of file localtime.c.

◆ TZ_ABBR_ERR_CHAR

#define TZ_ABBR_ERR_CHAR   '_'

Definition at line 96 of file localtime.c.

◆ TZ_ABBR_MAX_LEN

#define TZ_ABBR_MAX_LEN   16

Definition at line 87 of file localtime.c.

◆ TZ_STRLEN_MAX

#define TZ_STRLEN_MAX   255

Definition at line 155 of file localtime.c.

◆ TZDEFRULESTRING

#define TZDEFRULESTRING   ",M4.1.0,M10.5.0"
Note
The DST rules to use if TZ has no rules and we can't load TZDEFRULES. We default to US rules as of 1999-08-17. POSIX 1003.1 section 8.1.1 says that the default DST rules are implementation dependent; for historical reasons, US rules are a common default.

Definition at line 128 of file localtime.c.

Referenced by tzparse().

Function Documentation

◆ add_notify()

static void add_notify ( struct state sp,
const char *  path 
)
static

Definition at line 411 of file localtime.c.

References ast_cond_broadcast, ast_cond_init, ast_cond_signal, ast_cond_wait, ast_copy_string(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_TRYLOCK, AST_LIST_UNLOCK, ast_log, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, ast_test_status_update, common_startup(), errno, FILENAME_MAX, inotify_daemon(), state::list, LOG_NOTICE, name, state::name, NULL, PATH_MAX, SP_STACK_CHECK, sstate_alloc(), sstate_free(), TZDEFRULES, TZDIR, and state::wd.

Referenced by common_startup(), and tzload().

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 
425  /* Give the thread a chance to initialize */
427  } else {
428  fprintf(stderr, "Unable to start notification thread\n");
430  return;
431  }
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 }
#define FILENAME_MAX
#define SP_STACK_CHECK(sp)
Definition: localtime.c:194
static ast_cond_t initialization
Definition: localtime.c:322
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
#define ast_cond_init(cond, attr)
Definition: lock.h:199
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
static int inotify_fd
Definition: localtime.c:351
#define AST_PTHREADT_NULL
Definition: lock.h:66
static ast_mutex_t initialization_lock
Definition: localtime.c:323
static void * inotify_daemon(void *data)
Definition: localtime.c:353
int wd[2]
Definition: localtime.c:174
#define ast_mutex_init(pmutex)
Definition: lock.h:184
static pthread_t inotify_thread
Definition: localtime.c:321
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ ast_get_dst_info()

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 at line 1754 of file localtime.c.

References ast_tzset(), state::ats, AVGSECSPERYEAR, state::goahead, state::goback, int_fast64_t, NULL, state::timecnt, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.

Referenced by set_timezone_variables().

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 }
int typecnt
Definition: localtime.c:163
#define NULL
Definition: resample.c:96
long tt_gmtoff
Definition: localtime.c:133
int goahead
Definition: localtime.c:166
int goback
Definition: localtime.c:165
#define YEARSPERREPEAT
int tt_isdst
Definition: localtime.c:134
#define AVGSECSPERYEAR
time_t ats[TZ_MAX_TIMES]
Definition: localtime.c:167
you may need to compile with DHAVE_STDINT_H typedef long int_fast64_t
unsigned char types[TZ_MAX_TIMES]
Definition: localtime.c:168
static const struct state * ast_tzset(const char *zone)
Definition: localtime.c:1601
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:169
int timecnt
Definition: localtime.c:162

◆ ast_localtime()

struct ast_tm* ast_localtime ( const struct timeval *  timep,
struct ast_tm p_tm,
const char *  zone 
)

Timezone-independent version of localtime_r(3).

Parameters
timepCurrent time, including microseconds
p_tmPointer to memory where the broken-out time will be stored
zoneText string of a standard system zoneinfo file. If NULL, the system localtime will be used.
Return values
p_tmis returned for convenience

Definition at line 1739 of file localtime.c.

References ast_tzset(), localsub(), and NULL.

Referenced by acf_strftime(), action_corestatus(), append_date(), ast_cel_fabricate_channel_from_event(), ast_check_timing2(), ast_http_send(), ast_json_timeval(), ast_queue_log(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_gr(), ast_say_date_he(), ast_say_date_hu(), ast_say_date_is(), ast_say_date_ja(), ast_say_date_ka(), ast_say_date_nl(), ast_say_date_pt(), ast_say_date_th(), ast_say_date_with_format_da(), ast_say_date_with_format_de(), ast_say_date_with_format_en(), ast_say_date_with_format_es(), ast_say_date_with_format_fr(), ast_say_date_with_format_gr(), ast_say_date_with_format_he(), ast_say_date_with_format_is(), ast_say_date_with_format_it(), ast_say_date_with_format_ja(), ast_say_date_with_format_nl(), ast_say_date_with_format_pl(), ast_say_date_with_format_pt(), ast_say_date_with_format_th(), ast_say_date_with_format_vi(), ast_say_date_with_format_zh(), ast_say_datetime_de(), ast_say_datetime_en(), ast_say_datetime_fr(), ast_say_datetime_from_now_en(), ast_say_datetime_from_now_fr(), ast_say_datetime_from_now_he(), ast_say_datetime_from_now_ka(), ast_say_datetime_from_now_pt(), ast_say_datetime_gr(), ast_say_datetime_he(), ast_say_datetime_hu(), ast_say_datetime_ja(), ast_say_datetime_ka(), ast_say_datetime_nl(), ast_say_datetime_pt(), ast_say_datetime_pt_BR(), ast_say_datetime_th(), ast_say_datetime_zh(), ast_say_time_de(), ast_say_time_en(), ast_say_time_fr(), ast_say_time_gr(), ast_say_time_he(), ast_say_time_hu(), ast_say_time_ja(), ast_say_time_ka(), ast_say_time_nl(), ast_say_time_pt(), ast_say_time_pt_BR(), ast_say_time_th(), ast_say_time_zh(), AST_TEST_DEFINE(), beanstalk_put(), build_device(), build_radius_record(), callerid_genmsg(), cdr_get_tv(), cdr_read_callback(), cel_bs_put(), cli_prompt(), cli_show_tasks(), conf_run(), enc_ie_date(), epoch_to_string(), exchangecal_get_events_between(), execute_cb(), find_conf_realtime(), format_log_message_ap(), get_date(), get_ewscal_ids_for(), handle_cli_odbc_show(), handle_cli_test_locales(), handle_minivm_show_stats(), handle_show_settings(), http_callback(), iax2_datetime(), isodate(), leave_voicemail(), main(), make_email_file(), make_logchannel(), manager_log(), mstime(), mysql_log(), odbc_log(), packdate(), pgsql_log(), phone_call(), play_message_datetime(), prep_email_sub_vars(), prometheus_show_status(), rt_extend_conf(), say_date_generic(), send_date_time(), send_date_time2(), send_date_time3(), sendmail(), set_header(), set_timezone_variables(), sip_show_registry(), sms_compose2(), sms_handleincoming_proto2(), static_callback(), timeout_write(), transmit_definetimedate(), transmit_notify_request_with_callerid(), vmu_tm(), write_history(), and write_metadata().

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 }
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 NULL
Definition: resample.c:96
static const struct state * ast_tzset(const char *zone)
Definition: localtime.c:1601

◆ ast_localtime_wakeup_monitor()

void ast_localtime_wakeup_monitor ( struct ast_test info)

Definition at line 795 of file localtime.c.

References ast_cond_timedwait, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, ast_tvnow(), sip_to_pjsip::info(), lock, and NULL.

Referenced by AST_TEST_DEFINE().

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 
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 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static ast_cond_t initialization
Definition: localtime.c:322
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
#define AST_PTHREADT_NULL
Definition: lock.h:66
ast_mutex_t lock
Definition: app_meetme.c:1091
def info(msg)
static pthread_t inotify_thread
Definition: localtime.c:321
#define ast_cond_timedwait(cond, mutex, time)
Definition: lock.h:204

◆ ast_mktime()

struct timeval ast_mktime ( struct ast_tm *const  tmp,
const char *  zone 
)

Timezone-independent version of mktime(3).

Parameters
tmpCurrent broken-out time, including microseconds
zoneText string of a standard system zoneinfo file. If NULL, the system localtime will be used.
Return values
Astructure containing both seconds and fractional thereof since January 1st, 1970 UTC

Definition at line 2357 of file localtime.c.

References ast_tzset(), localsub(), and time1().

Referenced by acf_strptime(), conf_run(), find_conf_realtime(), icalfloat_to_timet(), mstime_to_time_t(), rt_extend_conf(), sms_handleincoming_proto2(), sms_readfile(), testtime_write(), and unpackdate().

2358 {
2359  const struct state *sp;
2360  if (!(sp = ast_tzset(zone)))
2361  return WRONG;
2362  return time1(tmp, localsub, 0L, sp);
2363 }
static struct ast_tm * localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
Definition: localtime.c:1648
static const struct timeval WRONG
Definition: localtime.c:111
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
static const struct state * ast_tzset(const char *zone)
Definition: localtime.c:1601

◆ ast_setlocale()

const char* ast_setlocale ( const char *  locale)

Set the thread-local representation of the current locale.

Definition at line 2420 of file localtime.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, find_by_name(), locale_entry::list, locale_entry::locale, locale_entry::name, NULL, and store_by_locale().

Referenced by ast_strftime_locale(), ast_strptime_locale(), and handle_cli_test_locales().

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 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char name[0]
Definition: localtime.c:245
void * locale_t
Definition: localtime.h:32
static char locale[20]
#define NULL
Definition: resample.c:96
static struct locale_entry * find_by_name(const char *name)
Definition: localtime.c:2377
Definition: localtime.c:242
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
locale_t locale
Definition: localtime.c:244
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct locale_entry::@424 list
static const char * store_by_locale(locale_t prevlocale)
Definition: localtime.c:2388

◆ ast_strftime()

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 strftime(3), with the addition of q, which specifies microseconds.

Parameters
bufAddress in memory where the resulting string will be stored.
lenSize of the chunk of memory buf.
formatA string specifying the format of time to be placed into buf.
tmPointer to the broken out time to be used for the format.
Return values
Aninteger value specifying the number of bytes placed into buf or -1 on error.

Definition at line 2524 of file localtime.c.

References ast_strftime_locale(), and NULL.

Referenced by acf_strftime(), action_corestatus(), append_date(), ast_cel_fabricate_channel_from_event(), ast_http_send(), ast_json_timeval(), ast_queue_log(), beanstalk_put(), build_radius_record(), cdr_get_tv(), cdr_read_callback(), cel_bs_put(), cli_prompt(), cli_show_tasks(), conf_run(), dump_datetime(), epoch_to_string(), exchangecal_get_events_between(), execute_cb(), find_conf_realtime(), format_log_message_ap(), get_date(), get_ewscal_ids_for(), handle_cli_odbc_show(), handle_cli_test_locales(), handle_minivm_show_stats(), handle_show_settings(), http_callback(), isodate(), leave_voicemail(), make_email_file(), make_logchannel(), manager_log(), mstime(), mysql_log(), odbc_log(), pgsql_log(), prometheus_show_status(), rt_extend_conf(), sendmail(), sendpage(), set_header(), sip_show_registry(), static_callback(), timeout_write(), and write_metadata().

2525 {
2526  return ast_strftime_locale(buf, len, tmp, tm, NULL);
2527 }
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_strftime_locale(char *buf, size_t len, const char *tmp, const struct ast_tm *tm, const char *locale)
Definition: localtime.c:2452

◆ ast_strftime_locale()

int ast_strftime_locale ( char *  buf,
size_t  len,
const char *  tmp,
const struct ast_tm tm,
const char *  locale 
)

Definition at line 2452 of file localtime.c.

References ast_calloc, ast_free, ast_realloc, ast_setlocale(), format, ast_tm::tm_usec, and tmp().

Referenced by ast_strftime(), make_email_file(), prep_email_sub_vars(), and sendpage().

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 }
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:228
int tm_usec
Definition: localtime.h:48
const char * ast_setlocale(const char *locale)
Set the thread-local representation of the current locale.
Definition: localtime.c:2420
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int tmp()
Definition: bt_open.c:389
static char locale[20]
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
static snd_pcm_format_t format
Definition: chan_alsa.c:102

◆ ast_strptime()

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.

Parameters
sA string specifying some portion of a date and time.
formatThe format in which the string, s, is expected.
tmThe broken-out time structure into which the parsed data is expected.
Return values
Apointer to the first character within s not used to parse the date and time.

Definition at line 2550 of file localtime.c.

References ast_strptime_locale(), and NULL.

Referenced by acf_strptime(), conf_run(), find_conf_realtime(), mstime_to_time_t(), rt_extend_conf(), and testtime_write().

2551 {
2552  return ast_strptime_locale(s, format, tm, NULL);
2553 }
#define NULL
Definition: resample.c:96
char * ast_strptime_locale(const char *s, const char *format, struct ast_tm *tm, const char *locale)
Definition: localtime.c:2529
static snd_pcm_format_t format
Definition: chan_alsa.c:102

◆ ast_strptime_locale()

char* ast_strptime_locale ( const char *  s,
const char *  format,
struct ast_tm tm,
const char *  locale 
)

Definition at line 2529 of file localtime.c.

References ast_setlocale(), ast_tm::tm_isdst, and ast_tm::tm_usec.

Referenced by ast_strptime().

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 }
int tm_usec
Definition: localtime.h:48
const char * ast_setlocale(const char *locale)
Set the thread-local representation of the current locale.
Definition: localtime.c:2420
static char locale[20]
int tm_isdst
Definition: localtime.h:44
static snd_pcm_format_t format
Definition: chan_alsa.c:102

◆ ast_tzset()

static const struct state* ast_tzset ( const char *  zone)
static

Definition at line 1601 of file localtime.c.

References ast_copy_string(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero, FALSE, gmtload(), state::list, state::name, NULL, sstate_alloc(), TRUE, tzload(), and tzparse().

Referenced by ast_get_dst_info(), ast_localtime(), and ast_mktime().

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 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define FALSE
Definition: app_minivm.c:521
char name[TZ_STRLEN_MAX+1]
Definition: localtime.c:160
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define NULL
Definition: resample.c:96
static struct state * sstate_alloc(void)
Definition: localtime.c:778
#define ast_strlen_zero(foo)
Definition: strings.h:52
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_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
struct state::@423 list
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
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
static int tzparse(const char *name, struct state *sp, const int lastditch)
Definition: localtime.c:1385

◆ clean_time_zones()

void clean_time_zones ( void  )

Provided by localtime.c

Definition at line 1590 of file localtime.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, state::list, and sstate_free().

Referenced by really_quit().

1591 {
1592  struct state *sp;
1593 
1595  while ((sp = AST_LIST_REMOVE_HEAD(&zonelist, list))) {
1596  sstate_free(sp);
1597  }
1599 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static void sstate_free(struct state *p)
Definition: localtime.c:789
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
struct state::@423 list

◆ common_startup()

static void common_startup ( void  )
static

Start a notification for every entry already in the list.

Definition at line 328 of file localtime.c.

References add_notify(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, FILENAME_MAX, state::list, state::name, TZDEFAULT, and TZDIR.

Referenced by add_notify(), and inotify_daemon().

328  {
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 }
#define FILENAME_MAX
#define TZDEFAULT
Definition: tzfile.h:41
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char name[TZ_STRLEN_MAX+1]
Definition: localtime.c:160
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define TZDIR
Definition: tzfile.h:36
struct state::@423 list
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static const char name[]
Definition: cdr_mysql.c:74
static void add_notify(struct state *sp, const char *path)
Definition: localtime.c:411

◆ detzcode()

static long detzcode ( const char *const  codep)
static
Note
Section 4.12.3 of X3.159-1989 requires that Except for the strftime function, these functions [asctime, ctime, gmtime, localtime] return values in one of two static objects: a broken-down time structure and an array of char. Thanks to Paul Eggert for noting this.

Definition at line 822 of file localtime.c.

References result.

Referenced by tzload().

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 }
static PGresult * result
Definition: cel_pgsql.c:88

◆ detzcode64()

static time_t detzcode64 ( const char *const  codep)
static

Definition at line 833 of file localtime.c.

References int_fast64_t, and result.

Referenced by tzload().

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 }
static PGresult * result
Definition: cel_pgsql.c:88
you may need to compile with DHAVE_STDINT_H typedef long int_fast64_t

◆ differ_by_repeat()

static int differ_by_repeat ( const time_t  t1,
const time_t  t0 
)
static

Definition at line 844 of file localtime.c.

References SECSPERREPEAT, SECSPERREPEAT_BITS, t1, TYPE_BIT, TYPE_INTEGRAL, and TYPE_SIGNED.

Referenced by tzload().

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 }
#define TYPE_SIGNED(type)
#define SECSPERREPEAT
#define SECSPERREPEAT_BITS
#define TYPE_INTEGRAL(type)
#define TYPE_BIT(type)
static uint16_t t1
Definition: res_pktccops.c:157

◆ find_by_locale()

static struct locale_entry* find_by_locale ( locale_t  locale)
static

Definition at line 2366 of file localtime.c.

References AST_LIST_TRAVERSE, locale_entry::list, locale_entry::locale, and NULL.

Referenced by store_by_locale().

2367 {
2368  struct locale_entry *cur;
2370  if (locale == cur->locale) {
2371  return cur;
2372  }
2373  }
2374  return NULL;
2375 }
static char locale[20]
#define NULL
Definition: resample.c:96
Definition: localtime.c:242
locale_t locale
Definition: localtime.c:244
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct locale_entry::@424 list

◆ find_by_name()

static struct locale_entry* find_by_name ( const char *  name)
static

Definition at line 2377 of file localtime.c.

References AST_LIST_TRAVERSE, locale_entry::list, locale_entry::name, and NULL.

Referenced by ast_setlocale(), and store_by_locale().

2378 {
2379  struct locale_entry *cur;
2381  if (strcmp(name, cur->name) == 0) {
2382  return cur;
2383  }
2384  }
2385  return NULL;
2386 }
char name[0]
Definition: localtime.c:245
#define NULL
Definition: resample.c:96
Definition: localtime.c:242
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static const char name[]
Definition: cdr_mysql.c:74
struct locale_entry::@424 list

◆ getnum()

static const char* getnum ( const char *  strp,
int *  nump,
const int  min,
const int  max 
)
static

Given a pointer into a time zone string, extract a number from that string. Check that the number is within a specified range; if it is not, return NULL. Otherwise, return a pointer to the first character not part of the number.

Definition at line 1153 of file localtime.c.

References c, is_digit, and NULL.

Referenced by getrule(), and getsecs().

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 }
#define is_digit(c)
static struct test_val c
#define NULL
Definition: resample.c:96
#define min(a, b)
Definition: f2c.h:197
#define max(a, b)
Definition: f2c.h:198

◆ getoffset()

static const char* getoffset ( const char *  strp,
long *  offsetp 
)
static

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 at line 1220 of file localtime.c.

References getsecs(), and NULL.

Referenced by tzparse().

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 }
#define NULL
Definition: resample.c:96
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

◆ getqzname()

static const char* getqzname ( const char *  strp,
const int  delim 
)
static

Given a pointer into an extended time zone string, scan until the ending delimiter of the zone name is located. Return a pointer to the delimiter.

As with getzname above, the legal character set is actually quite restricted, with other characters producing undefined results. We don't do any checking here; checking is done later in common-case code.

Definition at line 1137 of file localtime.c.

References c.

Referenced by tzparse().

1138 {
1139  int c;
1140 
1141  while ((c = *strp) != '\0' && c != delim)
1142  ++strp;
1143  return strp;
1144 }
static struct test_val c

◆ getrule()

static const char* getrule ( const char *  strp,
struct rule rulep 
)
static

Given a pointer into a time zone string, extract a rule in the form date[/time]. See POSIX section 8 for the format of "date" and "time". If a valid rule is not found, return NULL. Otherwise, return a pointer to the first character not part of the rule.

Definition at line 1244 of file localtime.c.

References DAY_OF_YEAR, DAYSPERNYEAR, DAYSPERWEEK, getnum(), getsecs(), is_digit, JULIAN_DAY, MONSPERYEAR, MONTH_NTH_DAY_OF_WEEK, NULL, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, and SECSPERHOUR.

Referenced by tzparse().

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 }
#define DAYSPERLYEAR
Definition: tzfile.h:137
#define DAYSPERNYEAR
Definition: tzfile.h:136
#define is_digit(c)
int r_day
Definition: localtime.c:250
int r_week
Definition: localtime.c:251
#define NULL
Definition: resample.c:96
int r_mon
Definition: localtime.c:252
#define MONSPERYEAR
Definition: tzfile.h:140
long r_time
Definition: localtime.c:253
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
#define DAY_OF_YEAR
Definition: localtime.c:257
#define DAYSPERWEEK
Definition: tzfile.h:135
#define MONTH_NTH_DAY_OF_WEEK
Definition: localtime.c:258
#define JULIAN_DAY
Definition: localtime.c:256
int r_type
Definition: localtime.c:249
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
#define SECSPERHOUR
Definition: tzfile.h:138

◆ getsecs()

static const char* getsecs ( const char *  strp,
long *const  secsp 
)
static

Given a pointer into a time zone string, extract a number of seconds, 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 number of seconds.

Definition at line 1181 of file localtime.c.

References DAYSPERWEEK, getnum(), HOURSPERDAY, MINSPERHOUR, NULL, SECSPERHOUR, and SECSPERMIN.

Referenced by getoffset(), and getrule().

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 }
#define NULL
Definition: resample.c:96
#define HOURSPERDAY
Definition: tzfile.h:134
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
#define MINSPERHOUR
Definition: tzfile.h:133
#define DAYSPERWEEK
Definition: tzfile.h:135
#define SECSPERMIN
Definition: tzfile.h:132
#define SECSPERHOUR
Definition: tzfile.h:138

◆ getzname()

static const char* getzname ( const char *  strp)
static

Given a pointer into a time zone string, scan until a character that is not a valid character in a zone name is found. Return a pointer to that character.

Definition at line 1118 of file localtime.c.

References c, and is_digit.

Referenced by tzparse().

1119 {
1120  char c;
1121 
1122  while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
1123  c != '+')
1124  ++strp;
1125  return strp;
1126 }
#define is_digit(c)
static struct test_val c

◆ gmtload()

static int gmtload ( struct state sp)
static

Definition at line 1582 of file localtime.c.

References TRUE, tzload(), and tzparse().

Referenced by ast_tzset(), and gmtsub().

1583 {
1584  if (tzload(gmt, sp, TRUE) != 0)
1585  return tzparse(gmt, sp, TRUE);
1586  else
1587  return -1;
1588 }
static int tzload(const char *name, struct state *const sp, const int doextend)
Definition: localtime.c:853
#define TRUE
Definition: app_minivm.c:518
static int tzparse(const char *name, struct state *sp, const int lastditch)
Definition: localtime.c:1385
static const char gmt[]
Definition: localtime.c:110

◆ gmtsub()

static struct ast_tm* gmtsub ( const struct timeval *  timep,
const long  offset,
struct ast_tm tmp 
)
static

Definition at line 1866 of file localtime.c.

References AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, state::chars, gmtload(), state::list, state::name, NULL, result, sstate_alloc(), and timesub().

Referenced by localsub().

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 }
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 AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char name[TZ_STRLEN_MAX+1]
Definition: localtime.c:160
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define NULL
Definition: resample.c:96
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, sizeof gmt),(2 *(MY_TZNAME_MAX+1)))]
Definition: localtime.c:171
static struct state * sstate_alloc(void)
Definition: localtime.c:778
static int gmtload(struct state *sp)
Definition: localtime.c:1582
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
struct state::@423 list
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static PGresult * result
Definition: cel_pgsql.c:88

◆ increment_overflow()

static int increment_overflow ( int *  number,
int  delta 
)
static

Simplified normalize logic courtesy Paul Eggert.

Note
Adapted from code provided by Robert Elz, who writes: The "best" way to do mktime I think is based on an idea of Bob Kridle's (so its said...) from a long time ago. It does a binary search of the time_t space. Since time_t's are just 32 bits, its a max of 32 iterations (even at 64 bits it would still be very reasonable).

Definition at line 2051 of file localtime.c.

Referenced by normalize_overflow(), time2sub(), and timesub().

2052 {
2053  int number0;
2054 
2055  number0 = *number;
2056  *number += delta;
2057  return (*number < number0) != (delta < 0);
2058 }
Number structure.
Definition: app_followme.c:154

◆ inotify_daemon()

static void* inotify_daemon ( void *  data)
static

Definition at line 353 of file localtime.c.

References ast_alloca, ast_cond_broadcast, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, common_startup(), errno, FILENAME_MAX, state::list, LOG_ERROR, NULL, sstate_free(), and state::wd.

Referenced by add_notify().

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 
366 
367  if (inotify_fd < 0) {
368  ast_log(LOG_ERROR, "Cannot initialize file notification service: %s (%d)\n", strerror(errno), errno);
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 */
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  }
405  }
406  close(inotify_fd);
408  return NULL;
409 }
#define FILENAME_MAX
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static ast_cond_t initialization
Definition: localtime.c:322
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
static void sstate_free(struct state *p)
Definition: localtime.c:789
#define ast_log
Definition: astobj2.c:42
static int inotify_fd
Definition: localtime.c:351
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
#define ast_cond_broadcast(cond)
Definition: lock.h:202
static ast_mutex_t initialization_lock
Definition: localtime.c:323
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define LOG_ERROR
Definition: logger.h:285
static void common_startup(void)
Definition: localtime.c:328
int errno
struct state::@423 list
int wd[2]
Definition: localtime.c:174
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
static pthread_t inotify_thread
Definition: localtime.c:321
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ leaps_thru_end_of()

static int leaps_thru_end_of ( const int  y)
static

Return the number of leap years through the end of the given year where, to make the math easy, the answer for year zero is defined as zero.

Definition at line 1907 of file localtime.c.

Referenced by timesub().

1908 {
1909  return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1910  -(leaps_thru_end_of(-(y + 1)) + 1);
1911 }
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

◆ localsub()

static struct ast_tm* localsub ( const struct timeval *  timep,
const long  offset,
struct ast_tm tmp,
const struct state sp 
)
static
Note
The easy way to behave "as if no library function calls" localtime is to not call it–so we drop its guts into "localsub", which can be freely called. (And no, the PANS doesn't require the above behavior– but it is desirable.)

The unused offset argument is for the benefit of mktime variants.

Definition at line 1648 of file localtime.c.

References state::ats, AVGSECSPERYEAR, state::chars, gmtsub(), state::goahead, state::goback, int_fast64_t, NULL, result, state::timecnt, timesub(), ast_tm::tm_gmtoff, ast_tm::tm_isdst, ast_tm::tm_usec, ast_tm::tm_year, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.

Referenced by ast_localtime(), and ast_mktime().

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 }
static struct ast_tm * timesub(const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
Definition: localtime.c:1913
static struct ast_tm * localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
Definition: localtime.c:1648
int tm_usec
Definition: localtime.h:48
time type information
Definition: localtime.c:132
int typecnt
Definition: localtime.c:163
#define NULL
Definition: resample.c:96
long tt_gmtoff
Definition: localtime.c:133
int tm_year
Definition: localtime.h:41
int goahead
Definition: localtime.c:166
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, sizeof gmt),(2 *(MY_TZNAME_MAX+1)))]
Definition: localtime.c:171
int goback
Definition: localtime.c:165
#define YEARSPERREPEAT
long int tm_gmtoff
Definition: localtime.h:45
int tt_isdst
Definition: localtime.c:134
int tm_isdst
Definition: localtime.h:44
static PGresult * result
Definition: cel_pgsql.c:88
#define AVGSECSPERYEAR
time_t ats[TZ_MAX_TIMES]
Definition: localtime.c:167
static struct ast_tm * gmtsub(const struct timeval *timep, const long offset, struct ast_tm *tmp)
Definition: localtime.c:1866
you may need to compile with DHAVE_STDINT_H typedef long int_fast64_t
unsigned char types[TZ_MAX_TIMES]
Definition: localtime.c:168
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:169
int timecnt
Definition: localtime.c:162
int tt_abbrind
Definition: localtime.c:135

◆ long_increment_overflow()

static int long_increment_overflow ( long *  number,
int  delta 
)
static

Definition at line 2060 of file localtime.c.

Referenced by long_normalize_overflow(), and time2sub().

2061 {
2062  long number0;
2063 
2064  number0 = *number;
2065  *number += delta;
2066  return (*number < number0) != (delta < 0);
2067 }
Number structure.
Definition: app_followme.c:154

◆ long_normalize_overflow()

static int long_normalize_overflow ( long *  tensptr,
int *  unitsptr,
const int  base 
)
static

Definition at line 2080 of file localtime.c.

References long_increment_overflow().

Referenced by time2sub().

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 }
static int long_increment_overflow(long *number, int delta)
Definition: localtime.c:2060

◆ normalize_overflow()

static int normalize_overflow ( int *  tensptr,
int *  unitsptr,
const int  base 
)
static

Definition at line 2069 of file localtime.c.

References increment_overflow().

Referenced by time2sub().

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 }
static int increment_overflow(int *number, int delta)
Simplified normalize logic courtesy Paul Eggert.
Definition: localtime.c:2051

◆ P() [1/24]

static time_t detzcode64 P ( (const char *codep)  )
static

◆ P() [2/24]

static int differ_by_repeat P ( (time_t t1, time_t t0)  )
static

◆ P() [3/24]

static const char* getzname P ( (const char *strp)  )
static

◆ P() [4/24]

static const char* getqzname P ( (const char *strp, const int delim)  )
static

◆ P() [5/24]

static const char* getnum P ( (const char *strp, int *nump, int min, int max )
static

◆ P() [6/24]

static const char* getsecs P ( (const char *strp, long *secsp)  )
static

◆ P() [7/24]

static const char* getoffset P ( (const char *strp, long *offsetp)  )
static

◆ P() [8/24]

static const char* getrule P ( (const char *strp, struct rule *rulep)  )
static

◆ P() [9/24]

static int gmtload P ( (struct state *sp)  )
static

◆ P() [10/24]

static struct ast_tm* gmtsub P ( (const struct timeval *timep, long offset, struct ast_tm *tmp )
static

◆ P() [11/24]

static struct ast_tm* localsub P ( (const struct timeval *timep, long offset, struct ast_tm *tmp, const struct state *sp)  )
static

◆ P() [12/24]

static int increment_overflow P ( (int *number, int delta)  )
static

◆ P() [13/24]

static int leaps_thru_end_of P ( (int y)  )
static

◆ P() [14/24]

static int long_increment_overflow P ( (long *number, int delta)  )
static

◆ P() [15/24]

static int long_normalize_overflow P ( (long *tensptr, int *unitsptr, const int base)  )
static

◆ P() [16/24]

static int normalize_overflow P ( (int *tensptr, int *unitsptr, const int base)  )
static

◆ P() [17/24]

static struct timeval time1 P ( (struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, const struct state *sp)  )
static

◆ P() [18/24]

static struct timeval time2sub P ( (struct ast_tm *tmp, struct ast_tm *(*funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp)  )
static

◆ P() [19/24]

static struct timeval time2 P ( (struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp)  )
static

◆ P() [20/24]

static struct ast_tm* timesub P ( (const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp )
static

◆ P() [21/24]

static int tmcomp P ( (const struct ast_tm *atmp, const struct ast_tm *btmp)  )
static

◆ P() [22/24]

static time_t transtime P ( (time_t janfirst, int year, const struct rule *rulep, long offset)  )
static

◆ P() [23/24]

static int tzload P ( (const char *name, struct state *sp, int doextend)  )
static

◆ P() [24/24]

static int tzparse P ( (const char *name, struct state *sp, int lastditch)  )
static

◆ sstate_alloc()

static struct state * sstate_alloc ( void  )
static

Definition at line 778 of file localtime.c.

References ast_calloc, NULL, and SP_HEAP_INIT.

Referenced by add_notify(), ast_tzset(), and gmtsub().

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 }
#define SP_HEAP_INIT(sp)
Definition: localtime.c:195
#define NULL
Definition: resample.c:96
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204

◆ sstate_free()

static void sstate_free ( struct state p)
static

Definition at line 789 of file localtime.c.

References ast_free, and SP_HEAP_FREE.

Referenced by add_notify(), clean_time_zones(), and inotify_daemon().

790 {
791  SP_HEAP_FREE(p);
792  ast_free(p);
793 }
#define SP_HEAP_FREE(sp)
Definition: localtime.c:199
#define ast_free(a)
Definition: astmm.h:182

◆ store_by_locale()

static const char* store_by_locale ( locale_t  prevlocale)
static

Definition at line 2388 of file localtime.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, find_by_locale(), find_by_name(), locale_entry::list, locale_entry::locale, locale_entry::name, and NULL.

Referenced by ast_setlocale().

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 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char name[0]
Definition: localtime.c:245
#define NULL
Definition: resample.c:96
static struct locale_entry * find_by_name(const char *name)
Definition: localtime.c:2377
Definition: localtime.c:242
static struct locale_entry * find_by_locale(locale_t locale)
Definition: localtime.c:2366
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
locale_t locale
Definition: localtime.c:244
static const char name[]
Definition: cdr_mysql.c:74
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct locale_entry::@424 list

◆ time1()

static struct timeval time1 ( struct ast_tm tmp,
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *)  funcp,
const long  offset,
const struct state sp 
)
static

Definition at line 2292 of file localtime.c.

References FALSE, NULL, time2(), state::timecnt, TRUE, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, TZ_MAX_TYPES, and WRONG.

Referenced by ast_mktime().

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 }
#define FALSE
Definition: app_minivm.c:521
int typecnt
Definition: localtime.c:163
static const struct timeval WRONG
Definition: localtime.c:111
#define NULL
Definition: resample.c:96
long tt_gmtoff
Definition: localtime.c:133
int tt_isdst
Definition: localtime.c:134
int tm_sec
Definition: localtime.h:36
#define TRUE
Definition: app_minivm.c:518
int tm_isdst
Definition: localtime.h:44
#define TZ_MAX_TYPES
Definition: tzfile.h:112
unsigned char types[TZ_MAX_TIMES]
Definition: localtime.c:168
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
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:169
int timecnt
Definition: localtime.c:162

◆ time2()

static struct timeval time2 ( struct ast_tm tmp,
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *sp)  funcp,
const long  offset,
int *  okayp,
const struct state sp 
)
static
Note
First try without normalization of seconds (in case tm_sec contains a value associated with a leap second). If that fails, try with normalization of seconds.

Definition at line 2279 of file localtime.c.

References FALSE, time2sub(), and TRUE.

Referenced by time1().

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 }
#define FALSE
Definition: app_minivm.c:521
#define TRUE
Definition: app_minivm.c:518
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

◆ time2sub()

static struct timeval time2sub ( struct ast_tm tmp,
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *)  funcp,
const long  offset,
int *  okayp,
const int  do_norm_secs,
const struct state sp 
)
static

Definition at line 2105 of file localtime.c.

References EPOCH_YEAR, FALSE, HOURSPERDAY, increment_overflow(), isleap, long_increment_overflow(), long_normalize_overflow(), MINSPERHOUR, MONSPERYEAR, normalize_overflow(), NULL, SECSPERMIN, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_year, TM_YEAR_BASE, tmcomp(), tmp(), TRUE, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, TYPE_BIT, TYPE_INTEGRAL, TYPE_SIGNED, state::typecnt, and WRONG.

Referenced by time2().

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 }
#define TYPE_SIGNED(type)
#define FALSE
Definition: app_minivm.c:521
#define DAYSPERLYEAR
Definition: tzfile.h:137
#define isleap(y)
Definition: tzfile.h:168
static int tmp()
Definition: bt_open.c:389
int typecnt
Definition: localtime.c:163
static const int mon_lengths[2][MONSPERYEAR]
Definition: localtime.c:1103
static const struct timeval WRONG
Definition: localtime.c:111
#define NULL
Definition: resample.c:96
#define HOURSPERDAY
Definition: tzfile.h:134
long tt_gmtoff
Definition: localtime.c:133
#define TYPE_INTEGRAL(type)
static int normalize_overflow(int *tensptr, int *unitsptr, const int base)
Definition: localtime.c:2069
#define MONSPERYEAR
Definition: tzfile.h:140
static int long_normalize_overflow(long *tensptr, int *unitsptr, const int base)
Definition: localtime.c:2080
static int increment_overflow(int *number, int delta)
Simplified normalize logic courtesy Paul Eggert.
Definition: localtime.c:2051
#define MINSPERHOUR
Definition: tzfile.h:133
#define TM_YEAR_BASE
Definition: tzfile.h:163
int tt_isdst
Definition: localtime.c:134
static int tmcomp(const struct ast_tm *atmp, const struct ast_tm *btmp)
Definition: localtime.c:2091
#define SECSPERMIN
Definition: tzfile.h:132
#define TRUE
Definition: app_minivm.c:518
static const int year_lengths[2]
Definition: localtime.c:1108
static int long_increment_overflow(long *number, int delta)
Definition: localtime.c:2060
#define EPOCH_YEAR
Definition: tzfile.h:165
#define TYPE_BIT(type)
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:169

◆ timesub()

static struct ast_tm* timesub ( const struct timeval *  timep,
const long  offset,
const struct state sp,
struct ast_tm tmp 
)
static

Definition at line 1913 of file localtime.c.

References DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, EPOCH_WDAY, EPOCH_YEAR, increment_overflow(), isleap, state::leapcnt, leaps_thru_end_of(), lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, NULL, SECSPERDAY, SECSPERHOUR, SECSPERMIN, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, ast_tm::tm_wday, ast_tm::tm_yday, ast_tm::tm_year, TM_YEAR_BASE, tmp(), and while().

Referenced by gmtsub(), and localsub().

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 }
#define DAYSPERLYEAR
Definition: tzfile.h:137
int tm_usec
Definition: localtime.h:48
#define isleap(y)
Definition: tzfile.h:168
#define DAYSPERNYEAR
Definition: tzfile.h:136
#define EPOCH_WDAY
Definition: tzfile.h:166
static int tmp()
Definition: bt_open.c:389
static const int mon_lengths[2][MONSPERYEAR]
Definition: localtime.c:1103
time_t ls_trans
Definition: localtime.c:142
#define NULL
Definition: resample.c:96
int tm_year
Definition: localtime.h:41
struct lsinfo lsis[TZ_MAX_LEAPS]
Definition: localtime.c:172
#define SECSPERDAY
Definition: tzfile.h:139
while(1)
Definition: ast_expr2f.c:894
int tm_mon
Definition: localtime.h:40
int tm_mday
Definition: localtime.h:39
int leapcnt
Definition: localtime.c:161
long ls_corr
Definition: localtime.c:143
static int increment_overflow(int *number, int delta)
Simplified normalize logic courtesy Paul Eggert.
Definition: localtime.c:2051
int tm_wday
Definition: localtime.h:42
#define TM_YEAR_BASE
Definition: tzfile.h:163
#define DAYSPERWEEK
Definition: tzfile.h:135
int tm_hour
Definition: localtime.h:38
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
#define SECSPERMIN
Definition: tzfile.h:132
int tm_isdst
Definition: localtime.h:44
static const int year_lengths[2]
Definition: localtime.c:1108
#define EPOCH_YEAR
Definition: tzfile.h:165
int tm_yday
Definition: localtime.h:43
#define SECSPERHOUR
Definition: tzfile.h:138
int tm_min
Definition: localtime.h:37

◆ tmcomp()

static int tmcomp ( const struct ast_tm atmp,
const struct ast_tm btmp 
)
static

Definition at line 2091 of file localtime.c.

References result, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, and ast_tm::tm_year.

Referenced by time2sub().

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 }
int tm_usec
Definition: localtime.h:48
int tm_year
Definition: localtime.h:41
int tm_mon
Definition: localtime.h:40
int tm_mday
Definition: localtime.h:39
int tm_hour
Definition: localtime.h:38
int tm_sec
Definition: localtime.h:36
static PGresult * result
Definition: cel_pgsql.c:88
int tm_min
Definition: localtime.h:37

◆ transtime()

static time_t transtime ( const time_t  janfirst,
const int  year,
const struct rule rulep,
const long  offset 
)
static

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 at line 1295 of file localtime.c.

References d, DAY_OF_YEAR, DAYSPERWEEK, INITIALIZE, isleap, JULIAN_DAY, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, SECSPERDAY, and value.

Referenced by tzparse().

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 }
#define isleap(y)
Definition: tzfile.h:168
#define INITIALIZE(x)
static struct test_val d
static const int mon_lengths[2][MONSPERYEAR]
Definition: localtime.c:1103
int r_day
Definition: localtime.c:250
int r_week
Definition: localtime.c:251
int value
Definition: syslog.c:37
int r_mon
Definition: localtime.c:252
#define SECSPERDAY
Definition: tzfile.h:139
long r_time
Definition: localtime.c:253
#define DAY_OF_YEAR
Definition: localtime.c:257
#define DAYSPERWEEK
Definition: tzfile.h:135
#define MONTH_NTH_DAY_OF_WEEK
Definition: localtime.c:258
#define JULIAN_DAY
Definition: localtime.c:256
int r_type
Definition: localtime.c:249

◆ tzload()

static int tzload ( const char *  name,
struct state *const  sp,
const int  doextend 
)
static

Definition at line 853 of file localtime.c.

References add_notify(), ast_fully_booted, state::ats, buf, state::charcnt, state::chars, detzcode(), detzcode64(), differ_by_repeat(), FALSE, FILENAME_MAX, state::goahead, state::goback, if(), state::leapcnt, lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, name, NULL, OPEN_MODE, result, SP_STACK_INIT, state::timecnt, TRUE, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, state::ttis, TYPE_INTEGRAL, TYPE_SIGNED, state::typecnt, state::types, TZ_MAX_CHARS, TZ_MAX_LEAPS, TZ_MAX_TIMES, TZ_MAX_TYPES, TZDEFAULT, TZDIR, tzparse(), while(), and YEARSPERREPEAT.

Referenced by ast_tzset(), gmtload(), and tzparse().

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 }
#define FILENAME_MAX
static time_t detzcode64(const char *const codep)
Definition: localtime.c:833
#define TZDEFAULT
Definition: tzfile.h:41
#define TYPE_SIGNED(type)
#define FALSE
Definition: app_minivm.c:521
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
time type information
Definition: localtime.c:132
int typecnt
Definition: localtime.c:163
if(!yyg->yy_init)
Definition: ast_expr2f.c:868
#define TZ_MAX_TIMES
Definition: tzfile.h:107
time_t ls_trans
Definition: localtime.c:142
#define NULL
Definition: resample.c:96
#define SP_STACK_INIT(sp)
Definition: localtime.c:191
long tt_gmtoff
Definition: localtime.c:133
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
#define TZ_MAX_LEAPS
Definition: tzfile.h:129
#define OPEN_MODE
Definition: localtime.c:107
struct lsinfo lsis[TZ_MAX_LEAPS]
Definition: localtime.c:172
#define TZDIR
Definition: tzfile.h:36
#define ast_fully_booted
Definition: options.h:115
while(1)
Definition: ast_expr2f.c:894
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
int leapcnt
Definition: localtime.c:161
#define TZ_MAX_CHARS
Definition: tzfile.h:124
long ls_corr
Definition: localtime.c:143
#define YEARSPERREPEAT
Definition: tzfile.h:54
static const char name[]
Definition: cdr_mysql.c:74
int tt_isdst
Definition: localtime.c:134
static int differ_by_repeat(const time_t t1, const time_t t0)
Definition: localtime.c:844
leap second information
Definition: localtime.c:141
#define TRUE
Definition: app_minivm.c:518
static PGresult * result
Definition: cel_pgsql.c:88
#define TZ_MAX_TYPES
Definition: tzfile.h:112
time_t ats[TZ_MAX_TIMES]
Definition: localtime.c:167
static int tzparse(const char *name, struct state *sp, const int lastditch)
Definition: localtime.c:1385
unsigned char types[TZ_MAX_TIMES]
Definition: localtime.c:168
static void add_notify(struct state *sp, const char *path)
Definition: localtime.c:411
int tt_ttisgmt
Definition: localtime.c:137
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:169
int timecnt
Definition: localtime.c:162
int tt_abbrind
Definition: localtime.c:135

◆ tzparse()

static int tzparse ( const char *  name,
struct state sp,
const int  lastditch 
)
static
Note
Given a POSIX section 8-style TZ string, fill in the rule tables as appropriate.

Definition at line 1385 of file localtime.c.

References state::ats, state::charcnt, state::chars, EPOCH_YEAR, FALSE, getoffset(), getqzname(), getrule(), getzname(), INITIALIZE, isleap, state::leapcnt, name, NULL, SECSPERDAY, SECSPERHOUR, state::timecnt, transtime(), TRUE, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, ttinfo::tt_ttisgmt, state::ttis, state::typecnt, state::types, TZ_MAX_TIMES, TZDEFRULES, TZDEFRULESTRING, and tzload().

Referenced by ast_tzset(), gmtload(), and tzload().

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)
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 }
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 isleap(y)
Definition: tzfile.h:168
#define INITIALIZE(x)
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
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
#define TZ_MAX_TIMES
Definition: tzfile.h:107
#define NULL
Definition: resample.c:96
char * end
Definition: eagi_proxy.c:73
long tt_gmtoff
Definition: localtime.c:133
#define TZDEFRULESTRING
Definition: localtime.c:128
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, sizeof gmt),(2 *(MY_TZNAME_MAX+1)))]
Definition: localtime.c:171
static int tzload(const char *name, struct state *const sp, const int doextend)
Definition: localtime.c:853
#define SECSPERDAY
Definition: tzfile.h:139
int charcnt
Definition: localtime.c:164
int leapcnt
Definition: localtime.c:161
static const char name[]
Definition: cdr_mysql.c:74
int tt_isdst
Definition: localtime.c:134
#define TZDEFRULES
Definition: tzfile.h:45
#define TRUE
Definition: app_minivm.c:518
static const int year_lengths[2]
Definition: localtime.c:1108
time_t ats[TZ_MAX_TIMES]
Definition: localtime.c:167
#define EPOCH_YEAR
Definition: tzfile.h:165
unsigned char types[TZ_MAX_TIMES]
Definition: localtime.c:168
#define SECSPERHOUR
Definition: tzfile.h:138
int tt_ttisgmt
Definition: localtime.c:137
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:169
int timecnt
Definition: localtime.c:162
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

Variable Documentation

◆ elsieid

char elsieid[] = "@(#)localtime.c 8.5"
static

Definition at line 82 of file localtime.c.

◆ gmt

const char gmt[] = "GMT"
static

Definition at line 110 of file localtime.c.

◆ initialization

ast_cond_t initialization
static

Definition at line 322 of file localtime.c.

◆ initialization_lock

ast_mutex_t initialization_lock
static

Definition at line 323 of file localtime.c.

◆ inotify_fd

int inotify_fd = -1
static

Definition at line 351 of file localtime.c.

Referenced by scan_thread().

◆ inotify_thread

pthread_t inotify_thread = AST_PTHREADT_NULL
static

Definition at line 321 of file localtime.c.

◆ localelist

struct localelist localelist = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ mon_lengths

const int mon_lengths[2][MONSPERYEAR]
static
Initial value:
= {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
}

Definition at line 1103 of file localtime.c.

◆ test

struct ast_test* test = NULL
static

◆ WRONG

const struct timeval WRONG = { 0, 0 }
static

Definition at line 111 of file localtime.c.

Referenced by time1(), and time2sub().

◆ year_lengths

const int year_lengths[2]
static
Initial value:
= {
}
#define DAYSPERLYEAR
Definition: tzfile.h:137
#define DAYSPERNYEAR
Definition: tzfile.h:136

Definition at line 1108 of file localtime.c.

◆ zonelist

struct zonelist zonelist = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static