Wed Jan 8 2020 09:50:14

Asterisk developer's documentation


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"

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 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 struct stateast_tzset (const char *zone)
 
void clean_time_zones (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 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 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 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 int normalize_overflow P ((int *tensptr, int *unitsptr, const int base))
 
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 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 } , }
 
static const int mon_lengths [2][MONSPERYEAR]
 
static 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 } , }
 

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

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

Definition at line 148 of file localtime.c.

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

Definition at line 205 of file localtime.c.

Referenced by getrule(), and transtime().

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

Definition at line 204 of file localtime.c.

Referenced by getrule(), and transtime().

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

Definition at line 206 of file localtime.c.

Referenced by getrule(), and transtime().

#define MY_TZNAME_MAX   255

Definition at line 154 of file localtime.c.

#define OPEN_MODE   O_RDONLY

Definition at line 109 of file localtime.c.

Referenced by tzload().

#define TZ_ABBR_CHAR_SET   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"

Definition at line 93 of file localtime.c.

#define TZ_ABBR_ERR_CHAR   '_'

Definition at line 98 of file localtime.c.

#define TZ_ABBR_MAX_LEN   16

Definition at line 89 of file localtime.c.

#define TZ_STRLEN_MAX   255

Definition at line 157 of file localtime.c.

#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 130 of file localtime.c.

Referenced by tzparse().

Function Documentation

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

Definition at line 328 of file localtime.c.

References ast_cond_init, ast_cond_wait, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, FILENAME_MAX, inotify_daemon(), and state::wd.

Referenced by tzload().

329 {
335  /* Give the thread a chance to initialize */
337  } else {
338  fprintf(stderr, "Unable to start notification thread\n");
340  return;
341  }
343  }
344 
345  if (inotify_fd > -1) {
346  char fullpath[FILENAME_MAX + 1] = "";
347  if (readlink(path, fullpath, sizeof(fullpath) - 1) != -1) {
348  /* If file the symlink points to changes */
349  sp->wd[1] = inotify_add_watch(inotify_fd, fullpath, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE );
350  } else {
351  sp->wd[1] = -1;
352  }
353  /* or if the symlink itself changes (or the real file is here, if path is not a symlink) */
354  sp->wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE
355 #ifdef IN_DONT_FOLLOW /* Only defined in glibc 2.5 and above */
356  | IN_DONT_FOLLOW
357 #endif
358  );
359  }
360 }
static ast_cond_t initialization
Definition: localtime.c:267
#define ast_cond_wait(cond, mutex)
Definition: lock.h:171
#define ast_cond_init(cond, attr)
Definition: lock.h:167
#define ast_mutex_lock(a)
Definition: lock.h:155
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:426
static int inotify_fd
Definition: localtime.c:270
#define AST_PTHREADT_NULL
Definition: lock.h:65
#define FILENAME_MAX
Definition: private.h:207
static ast_mutex_t initialization_lock
Definition: localtime.c:268
static void * inotify_daemon(void *data)
Definition: localtime.c:272
int wd[2]
Definition: localtime.c:176
#define ast_mutex_init(pmutex)
Definition: lock.h:152
static pthread_t inotify_thread
Definition: localtime.c:266
#define ast_mutex_unlock(a)
Definition: lock.h:156
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 1585 of file localtime.c.

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

1586 {
1587  int i;
1588  int transition1 = -1;
1589  int transition2 = -1;
1590  time_t seconds;
1591  int bounds_exceeded = 0;
1592  time_t t = *timep;
1593  const struct state *sp;
1594 
1595  if (NULL == dst_enabled)
1596  return;
1597  *dst_enabled = 0;
1598 
1599  if (NULL == dst_start || NULL == dst_end || NULL == gmt_off)
1600  return;
1601 
1602  *gmt_off = 0;
1603 
1604  sp = ast_tzset(zone);
1605  if (NULL == sp)
1606  return;
1607 
1608  /* If the desired time exceeds the bounds of the defined time transitions
1609  * then give give up on determining DST info and simply look for gmt offset
1610  * This requires that I adjust the given time using increments of Gregorian
1611  * repeats to place the time within the defined time transitions in the
1612  * timezone structure.
1613  */
1614  if ((sp->goback && t < sp->ats[0]) ||
1615  (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1616  time_t tcycles;
1617  int_fast64_t icycles;
1618 
1619  if (t < sp->ats[0])
1620  seconds = sp->ats[0] - t;
1621  else seconds = t - sp->ats[sp->timecnt - 1];
1622  --seconds;
1623  tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1624  ++tcycles;
1625  icycles = tcycles;
1626  if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1627  return;
1628  seconds = icycles;
1629  seconds *= YEARSPERREPEAT;
1630  seconds *= AVGSECSPERYEAR;
1631  if (t < sp->ats[0])
1632  t += seconds;
1633  else
1634  t -= seconds;
1635 
1636  if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1])
1637  return; /* "cannot happen" */
1638 
1639  bounds_exceeded = 1;
1640  }
1641 
1642  if (sp->timecnt == 0 || t < sp->ats[0]) {
1643  /* I have no transition times or I'm before time */
1644  *dst_enabled = 0;
1645  /* Find where I can get gmtoff */
1646  i = 0;
1647  while (sp->ttis[i].tt_isdst)
1648  if (++i >= sp->typecnt) {
1649  i = 0;
1650  break;
1651  }
1652  *gmt_off = sp->ttis[i].tt_gmtoff;
1653  return;
1654  }
1655 
1656  for (i = 1; i < sp->timecnt; ++i) {
1657  if (t < sp->ats[i]) {
1658  transition1 = sp->types[i - 1];
1659  transition2 = sp->types[i];
1660  break;
1661  }
1662  }
1663  /* if I found transition times that do not bounded the given time and these correspond to
1664  or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */
1665  if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 ||
1666  (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) {
1667  *dst_enabled = 0;
1668  *gmt_off = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff;
1669  } else {
1670  /* I have valid daylight savings information. */
1671  if(sp->ttis[transition2].tt_isdst)
1672  *gmt_off = sp->ttis[transition1].tt_gmtoff;
1673  else
1674  *gmt_off = sp->ttis[transition2].tt_gmtoff;
1675 
1676  /* If I adjusted the time earlier, indicate that the dst is invalid */
1677  if (!bounds_exceeded) {
1678  *dst_enabled = 1;
1679  /* Determine which of the bounds is the start of daylight savings and which is the end */
1680  if(sp->ttis[transition2].tt_isdst) {
1681  *dst_start = sp->ats[i];
1682  *dst_end = sp->ats[i -1];
1683  } else {
1684  *dst_start = sp->ats[i -1];
1685  *dst_end = sp->ats[i];
1686  }
1687  }
1688  }
1689  return;
1690 }
#define AVGSECSPERYEAR
Definition: private.h:343
static struct state * ast_tzset(const char *zone)
Definition: localtime.c:1432
int typecnt
Definition: localtime.c:165
long tt_gmtoff
Definition: localtime.c:135
int goahead
Definition: localtime.c:168
int goback
Definition: localtime.c:167
int tt_isdst
Definition: localtime.c:136
#define YEARSPERREPEAT
Definition: private.h:335
time_t ats[TZ_MAX_TIMES]
Definition: localtime.c:169
you may need to compile with DHAVE_STDINT_H typedef long int_fast64_t
Definition: private.h:152
unsigned char types[TZ_MAX_TIMES]
Definition: localtime.c:170
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:171
int timecnt
Definition: localtime.c:164
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 1570 of file localtime.c.

References ast_tzset(), and localsub().

Referenced by __ast_verbose_ap(), acf_strftime(), action_corestatus(), append_date(), ast_cel_fabricate_channel_from_event(), ast_check_timing2(), ast_http_send(), ast_log(), ast_queue_log(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_es(), ast_say_date_fr(), ast_say_date_gr(), ast_say_date_he(), ast_say_date_hu(), 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_it(), 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_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_es(), ast_say_time_fr(), ast_say_time_gr(), ast_say_time_he(), ast_say_time_hu(), 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(), build_device(), build_radius_record(), callerid_genmsg(), cdr_get_tv(), cli_prompt(), conf_run(), enc_ie_date(), epoch_to_string(), exchangecal_get_events_between(), execute_cb(), find_conf_realtime(), format_date(), get_date(), get_ewscal_ids_for(), handle_cli_odbc_show(), handle_minivm_show_stats(), handle_show_settings(), iax2_datetime(), isodate(), leave_voicemail(), main(), make_email_file(), manager_log(), mstime(), odbc_log(), packdate(), pgsql_log(), phone_call(), play_message_datetime(), prep_email_sub_vars(), rt_extend_conf(), say_date_generic(), send_date_time(), send_date_time2(), send_date_time3(), sendmail(), 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().

1571 {
1572  const struct state *sp = ast_tzset(zone);
1573  memset(tmp, 0, sizeof(*tmp));
1574  return sp ? localsub(timep, 0L, tmp, sp) : NULL;
1575 }
static struct ast_tm * localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
Definition: localtime.c:1479
static struct state * ast_tzset(const char *zone)
Definition: localtime.c:1432
void ast_localtime_wakeup_monitor ( struct ast_test *  info)

Definition at line 607 of file localtime.c.

References ast_cond_wait, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, and lock.

608 {
611 #ifdef TEST_FRAMEWORK
612  test = info;
613 #endif
614  pthread_kill(inotify_thread, SIGURG);
616 #ifdef TEST_FRAMEWORK
617  test = NULL;
618 #endif
620  }
621 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static ast_cond_t initialization
Definition: localtime.c:267
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define ast_cond_wait(cond, mutex)
Definition: lock.h:171
#define AST_PTHREADT_NULL
Definition: lock.h:65
ast_mutex_t lock
Definition: app_meetme.c:964
static pthread_t inotify_thread
Definition: localtime.c:266
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 2185 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().

2186 {
2187  const struct state *sp;
2188  if (!(sp = ast_tzset(zone)))
2189  return WRONG;
2190  return time1(tmp, localsub, 0L, sp);
2191 }
static struct ast_tm * localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
Definition: localtime.c:1479
static struct state * ast_tzset(const char *zone)
Definition: localtime.c:1432
static struct timeval WRONG
Definition: localtime.c:113
static struct timeval time1(struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, const struct state *sp)
Definition: localtime.c:2120
const char* ast_setlocale ( const char *  locale)

Set the thread-local representation of the current locale.

Definition at line 2248 of file localtime.c.

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

Referenced by ast_strftime_locale(), and ast_strptime_locale().

2249 {
2250  struct locale_entry *cur;
2251  locale_t prevlocale = LC_GLOBAL_LOCALE;
2252 
2253  if (locale == NULL) {
2254  return store_by_locale(uselocale(LC_GLOBAL_LOCALE));
2255  }
2256 
2258  if ((cur = find_by_name(locale))) {
2259  prevlocale = uselocale(cur->locale);
2260  }
2261 
2262  if (!cur) {
2263  if ((cur = ast_calloc(1, sizeof(*cur) + strlen(locale) + 1))) {
2264  cur->locale = newlocale(LC_ALL_MASK, locale, NULL);
2265  strcpy(cur->name, locale); /* SAFE */
2267  prevlocale = uselocale(cur->locale);
2268  }
2269  }
2271  return store_by_locale(prevlocale);
2272 }
#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:193
void * locale_t
Definition: localtime.h:32
static char locale[20]
struct locale_entry::@307 list
static struct locale_entry * find_by_name(const char *name)
Definition: localtime.c:2205
Definition: localtime.c:190
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
locale_t locale
Definition: localtime.c:192
#define ast_calloc(a, b)
Definition: astmm.h:82
static const char * store_by_locale(locale_t prevlocale)
Definition: localtime.c:2216
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.
localeText string specifying the locale to be used for language strings.
Return values
Aninteger value specifying the number of bytes placed into buf or -1 on error.

Definition at line 2351 of file localtime.c.

References ast_strftime_locale().

Referenced by __ast_verbose_ap(), acf_strftime(), action_corestatus(), append_date(), ast_cel_fabricate_channel_from_event(), ast_http_send(), ast_log(), ast_queue_log(), build_radius_record(), cdr_get_tv(), cli_prompt(), conf_run(), dump_datetime(), epoch_to_string(), exchangecal_get_events_between(), execute_cb(), find_conf_realtime(), format_date(), get_date(), get_ewscal_ids_for(), handle_cli_odbc_show(), handle_minivm_show_stats(), handle_show_settings(), isodate(), leave_voicemail(), make_email_file(), manager_log(), mstime(), odbc_log(), pgsql_log(), rt_extend_conf(), sendmail(), sendpage(), sip_show_registry(), static_callback(), timeout_write(), and write_metadata().

2352 {
2353  return ast_strftime_locale(buf, len, tmp, tm, NULL);
2354 }
int ast_strftime_locale(char *buf, size_t len, const char *format, const struct ast_tm *tm, const char *locale)
Definition: localtime.c:2280
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 at line 2280 of file localtime.c.

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

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

2281 {
2282  size_t fmtlen = strlen(tmp) + 1;
2283  char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt;
2284  int decimals = -1, i, res;
2285  long fraction;
2286  const char *prevlocale;
2287 
2288  if (!format) {
2289  return -1;
2290  }
2291  for (; *tmp; tmp++) {
2292  if (*tmp == '%') {
2293  switch (tmp[1]) {
2294  case '1':
2295  case '2':
2296  case '3':
2297  case '4':
2298  case '5':
2299  case '6':
2300  if (tmp[2] != 'q') {
2301  goto defcase;
2302  }
2303  decimals = tmp[1] - '0';
2304  tmp++;
2305  /* Fall through */
2306  case 'q': /* Milliseconds */
2307  if (decimals == -1) {
2308  decimals = 3;
2309  }
2310 
2311  /* Juggle some memory to fit the item */
2312  newfmt = ast_realloc(format, fmtlen + decimals);
2313  if (!newfmt) {
2314  ast_free(format);
2315  return -1;
2316  }
2317  fptr = fptr - format + newfmt;
2318  format = newfmt;
2319  fmtlen += decimals;
2320 
2321  /* Reduce the fraction of time to the accuracy needed */
2322  for (i = 6, fraction = tm->tm_usec; i > decimals; i--) {
2323  fraction /= 10;
2324  }
2325  fptr += sprintf(fptr, "%0*ld", decimals, fraction);
2326 
2327  /* Reset, in case more than one 'q' specifier exists */
2328  decimals = -1;
2329  tmp++;
2330  break;
2331  default:
2332  goto defcase;
2333  }
2334  } else {
2335 defcase: *fptr++ = *tmp;
2336  }
2337  }
2338  *fptr = '\0';
2339 #undef strftime
2340  if (locale) {
2341  prevlocale = ast_setlocale(locale);
2342  }
2343  res = (int)strftime(buf, len, format, (struct tm *)tm);
2344  if (locale) {
2345  ast_setlocale(prevlocale);
2346  }
2347  ast_free(format);
2348  return res;
2349 }
int tm_usec
Definition: localtime.h:48
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:97
const char * ast_setlocale(const char *locale)
Set the thread-local representation of the current locale.
Definition: localtime.c:2248
#define ast_calloc(a, b)
Definition: astmm.h:82
#define ast_realloc(a, b)
Definition: astmm.h:103
static snd_pcm_format_t format
Definition: chan_alsa.c:93
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.
localeText string specifying the locale to be used for language strings.
Return values
Apointer to the first character within s not used to parse the date and time.

Definition at line 2377 of file localtime.c.

References ast_strptime_locale().

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

2378 {
2379  return ast_strptime_locale(s, format, tm, NULL);
2380 }
char * ast_strptime_locale(const char *s, const char *format, struct ast_tm *tm, const char *locale)
Definition: localtime.c:2356
static snd_pcm_format_t format
Definition: chan_alsa.c:93
char* ast_strptime_locale ( const char *  s,
const char *  format,
struct ast_tm tm,
const char *  locale 
)

Definition at line 2356 of file localtime.c.

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

Referenced by ast_strptime().

2357 {
2358  struct tm tm2 = { 0, };
2359  char *res;
2360  const char *prevlocale;
2361 
2362  prevlocale = ast_setlocale(locale);
2363  res = strptime(s, format, &tm2);
2364  ast_setlocale(prevlocale);
2365  /* ast_time and tm are not the same size - tm is a subset of
2366  * ast_time. Hence, the size of tm needs to be used for the
2367  * memcpy
2368  */
2369  memcpy(tm, &tm2, sizeof(tm2));
2370  tm->tm_usec = 0;
2371  /* strptime(3) doesn't set .tm_isdst correctly, so to force ast_mktime(3)
2372  * to deal with it correctly, we set it to -1. */
2373  tm->tm_isdst = -1;
2374  return res;
2375 }
int tm_usec
Definition: localtime.h:48
static char locale[20]
const char * ast_setlocale(const char *locale)
Set the thread-local representation of the current locale.
Definition: localtime.c:2248
int tm_isdst
Definition: localtime.h:44
static snd_pcm_format_t format
Definition: chan_alsa.c:93
static struct state* ast_tzset ( const char *  zone)
static

Definition at line 1432 of file localtime.c.

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

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

1433 {
1434  struct state *sp;
1435 
1436  if (ast_strlen_zero(zone)) {
1437 #ifdef SOLARIS
1438  zone = getenv("TZ");
1439  if (ast_strlen_zero(zone)) {
1440  zone = "GMT";
1441  }
1442 #else
1443  zone = "/etc/localtime";
1444 #endif
1445  }
1446 
1449  if (!strcmp(sp->name, zone)) {
1451  return sp;
1452  }
1453  }
1455 
1456  if (!(sp = ast_calloc(1, sizeof *sp)))
1457  return NULL;
1458 
1459  if (tzload(zone, sp, TRUE) != 0) {
1460  if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0)
1461  (void) gmtload(sp);
1462  }
1463  ast_copy_string(sp->name, zone, sizeof(sp->name));
1467  return sp;
1468 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define FALSE
Definition: app_minivm.c:506
char name[TZ_STRLEN_MAX+1]
Definition: localtime.c:162
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct state::@306 list
static int tzload(const char *name, struct state *const sp, const int doextend)
Definition: localtime.c:662
static int gmtload(struct state *sp)
Definition: localtime.c:1413
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define TRUE
Definition: app_minivm.c:503
static int tzparse(const char *name, struct state *sp, const int lastditch)
Definition: localtime.c:1182
void clean_time_zones ( void  )

Provided by localtime.c

Definition at line 1421 of file localtime.c.

References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, and AST_LIST_UNLOCK.

Referenced by really_quit().

1422 {
1423  struct state *sp;
1424 
1426  while ((sp = AST_LIST_REMOVE_HEAD(&zonelist, list))) {
1427  ast_free(sp);
1428  }
1430 }
#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
struct state::@306 list
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define ast_free(a)
Definition: astmm.h:97
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 631 of file localtime.c.

Referenced by tzload().

632 {
633  long result;
634  int i;
635 
636  result = (codep[0] & 0x80) ? ~0L : 0;
637  for (i = 0; i < 4; ++i)
638  result = (result << 8) | (codep[i] & 0xff);
639  return result;
640 }
static time_t detzcode64 ( const char *const  codep)
static

Definition at line 642 of file localtime.c.

References int_fast64_t.

Referenced by tzload().

643 {
644  time_t result;
645  int i;
646 
647  result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
648  for (i = 0; i < 8; ++i)
649  result = result * 256 + (codep[i] & 0xff);
650  return result;
651 }
you may need to compile with DHAVE_STDINT_H typedef long int_fast64_t
Definition: private.h:152
static int differ_by_repeat ( const time_t  t1,
const time_t  t0 
)
static

Definition at line 653 of file localtime.c.

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

Referenced by tzload().

654 {
655  const long long at1 = t1, at0 = t0;
656  if (TYPE_INTEGRAL(time_t) &&
657  TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
658  return 0;
659  return at1 - at0 == SECSPERREPEAT;
660 }
#define SECSPERREPEAT_BITS
Definition: private.h:351
#define TYPE_INTEGRAL(type)
Definition: private.h:270
#define TYPE_BIT(type)
Definition: private.h:257
#define SECSPERREPEAT
Definition: private.h:347
#define TYPE_SIGNED(type)
Definition: private.h:261
static uint16_t t1
Definition: res_pktccops.c:159
static struct locale_entry* find_by_locale ( locale_t  locale)
static

Definition at line 2194 of file localtime.c.

References AST_LIST_TRAVERSE, and locale_entry::locale.

Referenced by store_by_locale().

2195 {
2196  struct locale_entry *cur;
2198  if (locale == cur->locale) {
2199  return cur;
2200  }
2201  }
2202  return NULL;
2203 }
static char locale[20]
struct locale_entry::@307 list
Definition: localtime.c:190
locale_t locale
Definition: localtime.c:192
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static struct locale_entry* find_by_name ( const char *  name)
static

Definition at line 2205 of file localtime.c.

References AST_LIST_TRAVERSE, and locale_entry::name.

Referenced by ast_setlocale(), and store_by_locale().

2206 {
2207  struct locale_entry *cur;
2209  if (strcmp(name, cur->name) == 0) {
2210  return cur;
2211  }
2212  }
2213  return NULL;
2214 }
char name[0]
Definition: localtime.c:193
struct locale_entry::@307 list
Definition: localtime.c:190
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static const char name[]
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 950 of file localtime.c.

References is_digit.

Referenced by getrule(), and getsecs().

951 {
952  char c;
953  int num;
954 
955  if (strp == NULL || !is_digit(c = *strp))
956  return NULL;
957  num = 0;
958  do {
959  num = num * 10 + (c - '0');
960  if (num > max)
961  return NULL; /* illegal value */
962  c = *++strp;
963  } while (is_digit(c));
964  if (num < min)
965  return NULL; /* illegal value */
966  *nump = num;
967  return strp;
968 }
#define is_digit(c)
Definition: private.h:125
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 1017 of file localtime.c.

References getsecs().

Referenced by tzparse().

1018 {
1019  int neg = 0;
1020 
1021  if (*strp == '-') {
1022  neg = 1;
1023  ++strp;
1024  } else if (*strp == '+')
1025  ++strp;
1026  strp = getsecs(strp, offsetp);
1027  if (strp == NULL)
1028  return NULL; /* illegal time */
1029  if (neg)
1030  *offsetp = -*offsetp;
1031  return strp;
1032 }
static const char * getsecs(const char *strp, long *const secsp)
Given a pointer into a time zone string, extract a number of seconds, in hh[:mm[:ss]] form...
Definition: localtime.c:978
static 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 934 of file localtime.c.

Referenced by tzparse().

935 {
936  int c;
937 
938  while ((c = *strp) != '\0' && c != delim)
939  ++strp;
940  return strp;
941 }
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 1041 of file localtime.c.

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

Referenced by tzparse().

1042 {
1043  if (*strp == 'J') {
1044  /*
1045  ** Julian day.
1046  */
1047  rulep->r_type = JULIAN_DAY;
1048  ++strp;
1049  strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
1050  } else if (*strp == 'M') {
1051  /*
1052  ** Month, week, day.
1053  */
1054  rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
1055  ++strp;
1056  strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
1057  if (strp == NULL)
1058  return NULL;
1059  if (*strp++ != '.')
1060  return NULL;
1061  strp = getnum(strp, &rulep->r_week, 1, 5);
1062  if (strp == NULL)
1063  return NULL;
1064  if (*strp++ != '.')
1065  return NULL;
1066  strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
1067  } else if (is_digit(*strp)) {
1068  /*
1069  ** Day of year.
1070  */
1071  rulep->r_type = DAY_OF_YEAR;
1072  strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
1073  } else return NULL; /* invalid format */
1074  if (strp == NULL)
1075  return NULL;
1076  if (*strp == '/') {
1077  /*
1078  ** Time specified.
1079  */
1080  ++strp;
1081  strp = getsecs(strp, &rulep->r_time);
1082  } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
1083  return strp;
1084 }
#define DAYSPERLYEAR
Definition: tzfile.h:137
#define DAYSPERNYEAR
Definition: tzfile.h:136
int r_day
Definition: localtime.c:198
int r_week
Definition: localtime.c:199
#define is_digit(c)
Definition: private.h:125
int r_mon
Definition: localtime.c:200
#define MONSPERYEAR
Definition: tzfile.h:140
long r_time
Definition: localtime.c:201
static const char * getnum(const char *strp, int *nump, const int min, const int max)
Given a pointer into a time zone string, extract a number from that string. Check that the number is ...
Definition: localtime.c:950
#define DAY_OF_YEAR
Definition: localtime.c:205
#define DAYSPERWEEK
Definition: tzfile.h:135
#define MONTH_NTH_DAY_OF_WEEK
Definition: localtime.c:206
#define JULIAN_DAY
Definition: localtime.c:204
int r_type
Definition: localtime.c:197
static const char * getsecs(const char *strp, long *const secsp)
Given a pointer into a time zone string, extract a number of seconds, in hh[:mm[:ss]] form...
Definition: localtime.c:978
#define SECSPERHOUR
Definition: tzfile.h:138
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 978 of file localtime.c.

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

Referenced by getoffset(), and getrule().

979 {
980  int num;
981 
982  /*
983  ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
984  ** "M10.4.6/26", which does not conform to Posix,
985  ** but which specifies the equivalent of
986  ** ``02:00 on the first Sunday on or after 23 Oct''.
987  */
988  strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
989  if (strp == NULL)
990  return NULL;
991  *secsp = num * (long) SECSPERHOUR;
992  if (*strp == ':') {
993  ++strp;
994  strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
995  if (strp == NULL)
996  return NULL;
997  *secsp += num * SECSPERMIN;
998  if (*strp == ':') {
999  ++strp;
1000  /* `SECSPERMIN' allows for leap seconds. */
1001  strp = getnum(strp, &num, 0, SECSPERMIN);
1002  if (strp == NULL)
1003  return NULL;
1004  *secsp += num;
1005  }
1006  }
1007  return strp;
1008 }
#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:950
#define MINSPERHOUR
Definition: tzfile.h:133
#define DAYSPERWEEK
Definition: tzfile.h:135
#define SECSPERMIN
Definition: tzfile.h:132
#define SECSPERHOUR
Definition: tzfile.h:138
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 915 of file localtime.c.

References is_digit.

Referenced by tzparse().

916 {
917  char c;
918 
919  while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
920  c != '+')
921  ++strp;
922  return strp;
923 }
#define is_digit(c)
Definition: private.h:125
static int gmtload ( struct state sp)
static

Definition at line 1413 of file localtime.c.

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

Referenced by ast_tzset(), and gmtsub().

1414 {
1415  if (tzload(gmt, sp, TRUE) != 0)
1416  return tzparse(gmt, sp, TRUE);
1417  else
1418  return -1;
1419 }
static int tzload(const char *name, struct state *const sp, const int doextend)
Definition: localtime.c:662
#define TRUE
Definition: app_minivm.c:503
static int tzparse(const char *name, struct state *sp, const int lastditch)
Definition: localtime.c:1182
static const char gmt[]
Definition: localtime.c:112
static struct ast_tm* gmtsub ( const struct timeval *  timep,
const long  offset,
struct ast_tm tmp 
)
static

Definition at line 1696 of file localtime.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, state::chars, gmtload(), state::name, and timesub().

Referenced by localsub().

1697 {
1698  struct ast_tm * result;
1699  struct state *sp;
1700 
1703  if (!strcmp(sp->name, "UTC"))
1704  break;
1705  }
1706 
1707  if (!sp) {
1708  if (!(sp = (struct state *) ast_calloc(1, sizeof *sp)))
1709  return NULL;
1710  gmtload(sp);
1712  }
1714 
1715  result = timesub(timep, offset, sp, tmp);
1716 #ifdef TM_ZONE
1717  /*
1718  ** Could get fancy here and deliver something such as
1719  ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1720  ** but this is no time for a treasure hunt.
1721  */
1722  if (offset != 0)
1723  tmp->TM_ZONE = " ";
1724  else
1725  tmp->TM_ZONE = sp->chars;
1726 #endif /* defined TM_ZONE */
1727  return result;
1728 }
static struct ast_tm * timesub(const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
Definition: localtime.c:1741
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char name[TZ_STRLEN_MAX+1]
Definition: localtime.c:162
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, sizeof gmt),(2 *(MY_TZNAME_MAX+1)))]
Definition: localtime.c:173
struct state::@306 list
static int gmtload(struct state *sp)
Definition: localtime.c:1413
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_calloc(a, b)
Definition: astmm.h:82
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 1879 of file localtime.c.

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

1880 {
1881  int number0;
1882 
1883  number0 = *number;
1884  *number += delta;
1885  return (*number < number0) != (delta < 0);
1886 }
Number structure.
Definition: app_followme.c:109
static void* inotify_daemon ( void *  data)
static

Definition at line 272 of file localtime.c.

References ast_cond_broadcast, ast_free, 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, errno, FILENAME_MAX, LOG_ERROR, state::name, and state::wd.

Referenced by add_notify().

273 {
274  struct {
275  struct inotify_event iev;
276  char name[FILENAME_MAX + 1];
277  } buf;
278  ssize_t res;
279  struct state *cur;
280 
281  inotify_fd = inotify_init();
282 
286 
287  if (inotify_fd < 0) {
288  ast_log(LOG_ERROR, "Cannot initialize file notification service: %s (%d)\n", strerror(errno), errno);
290  return NULL;
291  }
292 
293  for (;/*ever*/;) {
294  /* This read should block, most of the time. */
295  if ((res = read(inotify_fd, &buf, sizeof(buf))) < sizeof(buf.iev) && res > 0) {
296  /* This should never happen */
297  ast_log(LOG_ERROR, "Inotify read less than a full event (%zd < %zu)?!!\n", res, sizeof(buf.iev));
298  break;
299  } else if (res < 0) {
300  if (errno == EINTR || errno == EAGAIN) {
301  /* If read fails, try again */
305  continue;
306  }
307  /* Sanity check -- this should never happen, either */
308  ast_log(LOG_ERROR, "Inotify failed: %s\n", strerror(errno));
309  break;
310  }
313  if (cur->wd[0] == buf.iev.wd || cur->wd[1] == buf.iev.wd) {
315  ast_free(cur);
316  break;
317  }
318  }
322  }
323  close(inotify_fd);
325  return NULL;
326 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static ast_cond_t initialization
Definition: localtime.c:267
char name[TZ_STRLEN_MAX+1]
Definition: localtime.c:162
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define ast_mutex_lock(a)
Definition: lock.h:155
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
struct state::@306 list
static int inotify_fd
Definition: localtime.c:270
#define AST_PTHREADT_NULL
Definition: lock.h:65
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
#define FILENAME_MAX
Definition: private.h:207
#define ast_cond_broadcast(cond)
Definition: lock.h:170
static ast_mutex_t initialization_lock
Definition: localtime.c:268
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
#define ast_free(a)
Definition: astmm.h:97
int wd[2]
Definition: localtime.c:176
#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:266
#define ast_mutex_unlock(a)
Definition: lock.h:156
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 1735 of file localtime.c.

Referenced by timesub().

1736 {
1737  return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1738  -(leaps_thru_end_of(-(y + 1)) + 1);
1739 }
static int leaps_thru_end_of(const int y)
Return the number of leap years through the end of the given year where, to make the math easy...
Definition: localtime.c:1735
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 1479 of file localtime.c.

References state::ats, AVGSECSPERYEAR, state::chars, gmtsub(), state::goahead, state::goback, int_fast64_t, 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().

1480 {
1481  const struct ttinfo * ttisp;
1482  int i;
1483  struct ast_tm * result;
1484  struct timeval t;
1485  memcpy(&t, timep, sizeof(t));
1486 
1487  if (sp == NULL)
1488  return gmtsub(timep, offset, tmp);
1489  if ((sp->goback && t.tv_sec < sp->ats[0]) ||
1490  (sp->goahead && t.tv_sec > sp->ats[sp->timecnt - 1])) {
1491  struct timeval newt = t;
1492  time_t seconds;
1493  time_t tcycles;
1494  int_fast64_t icycles;
1495 
1496  if (t.tv_sec < sp->ats[0])
1497  seconds = sp->ats[0] - t.tv_sec;
1498  else seconds = t.tv_sec - sp->ats[sp->timecnt - 1];
1499  --seconds;
1500  tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1501  ++tcycles;
1502  icycles = tcycles;
1503  if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1504  return NULL;
1505  seconds = icycles;
1506  seconds *= YEARSPERREPEAT;
1507  seconds *= AVGSECSPERYEAR;
1508  if (t.tv_sec < sp->ats[0])
1509  newt.tv_sec += seconds;
1510  else newt.tv_sec -= seconds;
1511  if (newt.tv_sec < sp->ats[0] ||
1512  newt.tv_sec > sp->ats[sp->timecnt - 1])
1513  return NULL; /* "cannot happen" */
1514  result = localsub(&newt, offset, tmp, sp);
1515  if (result == tmp) {
1516  time_t newy;
1517 
1518  newy = tmp->tm_year;
1519  if (t.tv_sec < sp->ats[0])
1520  newy -= icycles * YEARSPERREPEAT;
1521  else
1522  newy += icycles * YEARSPERREPEAT;
1523  tmp->tm_year = newy;
1524  if (tmp->tm_year != newy)
1525  return NULL;
1526  }
1527  return result;
1528  }
1529  if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) {
1530  i = 0;
1531  while (sp->ttis[i].tt_isdst) {
1532  if (++i >= sp->typecnt) {
1533  i = 0;
1534  break;
1535  }
1536  }
1537  } else {
1538  int lo = 1;
1539  int hi = sp->timecnt;
1540 
1541  while (lo < hi) {
1542  int mid = (lo + hi) >> 1;
1543 
1544  if (t.tv_sec < sp->ats[mid])
1545  hi = mid;
1546  else
1547  lo = mid + 1;
1548  }
1549  i = (int) sp->types[lo - 1];
1550  }
1551  ttisp = &sp->ttis[i];
1552  /*
1553  ** To get (wrong) behavior that's compatible with System V Release 2.0
1554  ** you'd replace the statement below with
1555  ** t += ttisp->tt_gmtoff;
1556  ** timesub(&t, 0L, sp, tmp);
1557  */
1558  result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1559  tmp->tm_isdst = ttisp->tt_isdst;
1560 #ifndef SOLARIS /* Solaris doesn't have this element */
1561  tmp->tm_gmtoff = ttisp->tt_gmtoff;
1562 #endif
1563 #ifdef TM_ZONE
1564  tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
1565 #endif /* defined TM_ZONE */
1566  tmp->tm_usec = timep->tv_usec;
1567  return result;
1568 }
#define AVGSECSPERYEAR
Definition: private.h:343
static struct ast_tm * timesub(const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
Definition: localtime.c:1741
static struct ast_tm * localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
Definition: localtime.c:1479
int tm_usec
Definition: localtime.h:48
time type information
Definition: localtime.c:134
int typecnt
Definition: localtime.c:165
long tt_gmtoff
Definition: localtime.c:135
int tm_year
Definition: localtime.h:41
int goahead
Definition: localtime.c:168
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, sizeof gmt),(2 *(MY_TZNAME_MAX+1)))]
Definition: localtime.c:173
int goback
Definition: localtime.c:167
long int tm_gmtoff
Definition: localtime.h:45
int tt_isdst
Definition: localtime.c:136
#define YEARSPERREPEAT
Definition: private.h:335
int tm_isdst
Definition: localtime.h:44
time_t ats[TZ_MAX_TIMES]
Definition: localtime.c:169
you may need to compile with DHAVE_STDINT_H typedef long int_fast64_t
Definition: private.h:152
static struct ast_tm * gmtsub(const struct timeval *timep, const long offset, struct ast_tm *tmp)
Definition: localtime.c:1696
unsigned char types[TZ_MAX_TIMES]
Definition: localtime.c:170
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:171
int timecnt
Definition: localtime.c:164
int tt_abbrind
Definition: localtime.c:137
static int long_increment_overflow ( long *  number,
int  delta 
)
static

Definition at line 1888 of file localtime.c.

Referenced by long_normalize_overflow(), and time2sub().

1889 {
1890  long number0;
1891 
1892  number0 = *number;
1893  *number += delta;
1894  return (*number < number0) != (delta < 0);
1895 }
Number structure.
Definition: app_followme.c:109
static int long_normalize_overflow ( long *  tensptr,
int *  unitsptr,
const int  base 
)
static

Definition at line 1908 of file localtime.c.

References long_increment_overflow().

Referenced by time2sub().

1909 {
1910  int tensdelta;
1911 
1912  tensdelta = (*unitsptr >= 0) ?
1913  (*unitsptr / base) :
1914  (-1 - (-1 - *unitsptr) / base);
1915  *unitsptr -= tensdelta * base;
1916  return long_increment_overflow(tensptr, tensdelta);
1917 }
static int long_increment_overflow(long *number, int delta)
Definition: localtime.c:1888
static int normalize_overflow ( int *  tensptr,
int *  unitsptr,
const int  base 
)
static

Definition at line 1897 of file localtime.c.

References increment_overflow().

Referenced by time2sub().

1898 {
1899  int tensdelta;
1900 
1901  tensdelta = (*unitsptr >= 0) ?
1902  (*unitsptr / base) :
1903  (-1 - (-1 - *unitsptr) / base);
1904  *unitsptr -= tensdelta * base;
1905  return increment_overflow(tensptr, tensdelta);
1906 }
static int increment_overflow(int *number, int delta)
Simplified normalize logic courtesy Paul Eggert.
Definition: localtime.c:1879
static time_t detzcode64 P ( (const char *codep)  )
static
static int differ_by_repeat P ( (time_t t1, time_t t0)  )
static
static const char* getzname P ( (const char *strp)  )
static
static const char* getqzname P ( (const char *strp, const int delim)  )
static
static const char* getnum P ( (const char *strp, int *nump, int min, int max)  )
static
static const char* getsecs P ( (const char *strp, long *secsp)  )
static
static const char* getoffset P ( (const char *strp, long *offsetp)  )
static
static const char* getrule P ( (const char *strp, struct rule *rulep)  )
static
static int gmtload P ( (struct state *sp)  )
static
static struct ast_tm* gmtsub P ( (const struct timeval *timep, long offset, struct ast_tm *tmp)  )
static
static struct ast_tm* localsub P ( (const struct timeval *timep, long offset, struct ast_tm *tmp, const struct state *sp)  )
static
static int increment_overflow P ( (int *number, int delta)  )
static
static int leaps_thru_end_of P ( (int y)  )
static
static int long_increment_overflow P ( (long *number, int delta)  )
static
static int long_normalize_overflow P ( (long *tensptr, int *unitsptr, const int base)  )
static
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
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
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
static int normalize_overflow P ( (int *tensptr, int *unitsptr, const int base)  )
static
static struct ast_tm* timesub P ( (const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp)  )
static
static int tmcomp P ( (const struct ast_tm *atmp, const struct ast_tm *btmp)  )
static
static time_t transtime P ( (time_t janfirst, int year, const struct rule *rulep, long offset)  )
static
static int tzload P ( (const char *name, struct state *sp, int doextend)  )
static
static int tzparse P ( (const char *name, struct state *sp, int lastditch)  )
static
static const char* store_by_locale ( locale_t  prevlocale)
static

Definition at line 2216 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::locale, and locale_entry::name.

Referenced by ast_setlocale().

2217 {
2218  struct locale_entry *cur;
2219  if (prevlocale == LC_GLOBAL_LOCALE) {
2220  return NULL;
2221  } else {
2222  /* Get a handle for this entry, if any */
2223  if ((cur = find_by_locale(prevlocale))) {
2224  return cur->name;
2225  } else {
2226  /* Create an entry, so it can be restored later */
2227  int x;
2228  cur = NULL;
2230  for (x = 0; x < 10000; x++) {
2231  char name[5];
2232  snprintf(name, sizeof(name), "%04d", x);
2233  if (!find_by_name(name)) {
2234  if ((cur = ast_calloc(1, sizeof(*cur) + strlen(name) + 1))) {
2235  cur->locale = prevlocale;
2236  strcpy(cur->name, name); /* SAFE */
2238  }
2239  break;
2240  }
2241  }
2243  return cur ? cur->name : NULL;
2244  }
2245  }
2246 }
#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:193
struct locale_entry::@307 list
static struct locale_entry * find_by_name(const char *name)
Definition: localtime.c:2205
Definition: localtime.c:190
static struct locale_entry * find_by_locale(locale_t locale)
Definition: localtime.c:2194
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
locale_t locale
Definition: localtime.c:192
static const char name[]
#define ast_calloc(a, b)
Definition: astmm.h:82
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 2120 of file localtime.c.

References FALSE, 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().

2121 {
2122  struct timeval t;
2123  int samei, otheri;
2124  int sameind, otherind;
2125  int i;
2126  int nseen;
2127  int seen[TZ_MAX_TYPES];
2128  int types[TZ_MAX_TYPES];
2129  int okay;
2130 
2131  if (tmp->tm_isdst > 1)
2132  tmp->tm_isdst = 1;
2133  t = time2(tmp, funcp, offset, &okay, sp);
2134 #ifdef PCTS
2135  /*
2136  ** PCTS code courtesy Grant Sullivan.
2137  */
2138  if (okay)
2139  return t;
2140  if (tmp->tm_isdst < 0)
2141  tmp->tm_isdst = 0; /* reset to std and try again */
2142 #endif /* defined PCTS */
2143 #ifndef PCTS
2144  if (okay || tmp->tm_isdst < 0)
2145  return t;
2146 #endif /* !defined PCTS */
2147  /*
2148  ** We're supposed to assume that somebody took a time of one type
2149  ** and did some math on it that yielded a "struct ast_tm" that's bad.
2150  ** We try to divine the type they started from and adjust to the
2151  ** type they need.
2152  */
2153  if (sp == NULL)
2154  return WRONG;
2155  for (i = 0; i < sp->typecnt; ++i)
2156  seen[i] = FALSE;
2157  nseen = 0;
2158  for (i = sp->timecnt - 1; i >= 0; --i)
2159  if (!seen[sp->types[i]]) {
2160  seen[sp->types[i]] = TRUE;
2161  types[nseen++] = sp->types[i];
2162  }
2163  for (sameind = 0; sameind < nseen; ++sameind) {
2164  samei = types[sameind];
2165  if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2166  continue;
2167  for (otherind = 0; otherind < nseen; ++otherind) {
2168  otheri = types[otherind];
2169  if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2170  continue;
2171  tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
2172  sp->ttis[samei].tt_gmtoff;
2173  tmp->tm_isdst = !tmp->tm_isdst;
2174  t = time2(tmp, funcp, offset, &okay, sp);
2175  if (okay)
2176  return t;
2177  tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
2178  sp->ttis[samei].tt_gmtoff;
2179  tmp->tm_isdst = !tmp->tm_isdst;
2180  }
2181  }
2182  return WRONG;
2183 }
#define FALSE
Definition: app_minivm.c:506
int typecnt
Definition: localtime.c:165
long tt_gmtoff
Definition: localtime.c:135
int tt_isdst
Definition: localtime.c:136
int tm_sec
Definition: localtime.h:36
#define TRUE
Definition: app_minivm.c:503
int tm_isdst
Definition: localtime.h:44
#define TZ_MAX_TYPES
Definition: tzfile.h:112
static struct timeval WRONG
Definition: localtime.c:113
unsigned char types[TZ_MAX_TIMES]
Definition: localtime.c:170
static struct timeval time2(struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), const long offset, int *okayp, const struct state *sp)
Definition: localtime.c:2107
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:171
int timecnt
Definition: localtime.c:164
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 2107 of file localtime.c.

References FALSE, time2sub(), and TRUE.

Referenced by time1().

2108 {
2109  struct timeval t;
2110 
2111  /*! \note
2112  ** First try without normalization of seconds
2113  ** (in case tm_sec contains a value associated with a leap second).
2114  ** If that fails, try with normalization of seconds.
2115  */
2116  t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
2117  return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
2118 }
#define FALSE
Definition: app_minivm.c:506
#define TRUE
Definition: app_minivm.c:503
static struct timeval time2sub(struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, int *okayp, const int do_norm_secs, const struct state *sp)
Definition: localtime.c:1933
static struct timeval 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 1933 of file localtime.c.

References DAYSPERLYEAR, EPOCH_YEAR, FALSE, HOURSPERDAY, increment_overflow(), isleap, long_increment_overflow(), long_normalize_overflow(), MINSPERHOUR, MONSPERYEAR, normalize_overflow(), 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(), TRUE, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, TYPE_BIT, TYPE_INTEGRAL, TYPE_SIGNED, state::typecnt, and WRONG.

Referenced by time2().

1934 {
1935  int dir;
1936  int i, j;
1937  int saved_seconds;
1938  long li;
1939  time_t lo;
1940  time_t hi;
1941  long y;
1942  struct timeval newt = { 0, 0 };
1943  struct timeval t = { 0, 0 };
1944  struct ast_tm yourtm, mytm;
1945 
1946  *okayp = FALSE;
1947  yourtm = *tmp;
1948  if (do_norm_secs) {
1949  if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
1950  SECSPERMIN))
1951  return WRONG;
1952  }
1953  if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
1954  return WRONG;
1955  if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
1956  return WRONG;
1957  y = yourtm.tm_year;
1958  if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
1959  return WRONG;
1960  /*
1961  ** Turn y into an actual year number for now.
1962  ** It is converted back to an offset from TM_YEAR_BASE later.
1963  */
1965  return WRONG;
1966  while (yourtm.tm_mday <= 0) {
1967  if (long_increment_overflow(&y, -1))
1968  return WRONG;
1969  li = y + (1 < yourtm.tm_mon);
1970  yourtm.tm_mday += year_lengths[isleap(li)];
1971  }
1972  while (yourtm.tm_mday > DAYSPERLYEAR) {
1973  li = y + (1 < yourtm.tm_mon);
1974  yourtm.tm_mday -= year_lengths[isleap(li)];
1975  if (long_increment_overflow(&y, 1))
1976  return WRONG;
1977  }
1978  for ( ; ; ) {
1979  i = mon_lengths[isleap(y)][yourtm.tm_mon];
1980  if (yourtm.tm_mday <= i)
1981  break;
1982  yourtm.tm_mday -= i;
1983  if (++yourtm.tm_mon >= MONSPERYEAR) {
1984  yourtm.tm_mon = 0;
1985  if (long_increment_overflow(&y, 1))
1986  return WRONG;
1987  }
1988  }
1990  return WRONG;
1991  yourtm.tm_year = y;
1992  if (yourtm.tm_year != y)
1993  return WRONG;
1994  if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
1995  saved_seconds = 0;
1996  else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
1997  /*
1998  ** We can't set tm_sec to 0, because that might push the
1999  ** time below the minimum representable time.
2000  ** Set tm_sec to 59 instead.
2001  ** This assumes that the minimum representable time is
2002  ** not in the same minute that a leap second was deleted from,
2003  ** which is a safer assumption than using 58 would be.
2004  */
2005  if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
2006  return WRONG;
2007  saved_seconds = yourtm.tm_sec;
2008  yourtm.tm_sec = SECSPERMIN - 1;
2009  } else {
2010  saved_seconds = yourtm.tm_sec;
2011  yourtm.tm_sec = 0;
2012  }
2013  /*
2014  ** Do a binary search (this works whatever time_t's type is).
2015  */
2016  if (!TYPE_SIGNED(time_t)) {
2017  lo = 0;
2018  hi = lo - 1;
2019  } else if (!TYPE_INTEGRAL(time_t)) {
2020  if (sizeof(time_t) > sizeof(float))
2021  hi = (time_t) DBL_MAX;
2022  else hi = (time_t) FLT_MAX;
2023  lo = -hi;
2024  } else {
2025  lo = 1;
2026  for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
2027  lo *= 2;
2028  hi = -(lo + 1);
2029  }
2030  for ( ; ; ) {
2031  t.tv_sec = lo / 2 + hi / 2;
2032  if (t.tv_sec < lo)
2033  t.tv_sec = lo;
2034  else if (t.tv_sec > hi)
2035  t.tv_sec = hi;
2036  if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
2037  /*
2038  ** Assume that t is too extreme to be represented in
2039  ** a struct ast_tm; arrange things so that it is less
2040  ** extreme on the next pass.
2041  */
2042  dir = (t.tv_sec > 0) ? 1 : -1;
2043  } else dir = tmcomp(&mytm, &yourtm);
2044  if (dir != 0) {
2045  if (t.tv_sec == lo) {
2046  ++t.tv_sec;
2047  if (t.tv_sec <= lo)
2048  return WRONG;
2049  ++lo;
2050  } else if (t.tv_sec == hi) {
2051  --t.tv_sec;
2052  if (t.tv_sec >= hi)
2053  return WRONG;
2054  --hi;
2055  }
2056  if (lo > hi)
2057  return WRONG;
2058  if (dir > 0)
2059  hi = t.tv_sec;
2060  else lo = t.tv_sec;
2061  continue;
2062  }
2063  if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
2064  break;
2065  /*
2066  ** Right time, wrong type.
2067  ** Hunt for right time, right type.
2068  ** It's okay to guess wrong since the guess
2069  ** gets checked.
2070  */
2071  /*
2072  ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
2073  */
2074  for (i = sp->typecnt - 1; i >= 0; --i) {
2075  if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
2076  continue;
2077  for (j = sp->typecnt - 1; j >= 0; --j) {
2078  if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
2079  continue;
2080  newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff -
2081  sp->ttis[i].tt_gmtoff;
2082  if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
2083  continue;
2084  if (tmcomp(&mytm, &yourtm) != 0)
2085  continue;
2086  if (mytm.tm_isdst != yourtm.tm_isdst)
2087  continue;
2088  /*
2089  ** We have a match.
2090  */
2091  t = newt;
2092  goto label;
2093  }
2094  }
2095  return WRONG;
2096  }
2097 label:
2098  newt.tv_sec = t.tv_sec + saved_seconds;
2099  if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0))
2100  return WRONG;
2101  t.tv_sec = newt.tv_sec;
2102  if ((*funcp)(&t, offset, tmp, sp))
2103  *okayp = TRUE;
2104  return t;
2105 }
#define FALSE
Definition: app_minivm.c:506
#define DAYSPERLYEAR
Definition: tzfile.h:137
#define isleap(y)
Definition: tzfile.h:168
int typecnt
Definition: localtime.c:165
static const int mon_lengths[2][MONSPERYEAR]
Definition: localtime.c:900
#define HOURSPERDAY
Definition: tzfile.h:134
long tt_gmtoff
Definition: localtime.c:135
static int normalize_overflow(int *tensptr, int *unitsptr, const int base)
Definition: localtime.c:1897
#define MONSPERYEAR
Definition: tzfile.h:140
static int long_normalize_overflow(long *tensptr, int *unitsptr, const int base)
Definition: localtime.c:1908
static int increment_overflow(int *number, int delta)
Simplified normalize logic courtesy Paul Eggert.
Definition: localtime.c:1879
#define MINSPERHOUR
Definition: tzfile.h:133
#define TM_YEAR_BASE
Definition: tzfile.h:163
int tt_isdst
Definition: localtime.c:136
#define TYPE_INTEGRAL(type)
Definition: private.h:270
static int tmcomp(const struct ast_tm *atmp, const struct ast_tm *btmp)
Definition: localtime.c:1919
#define SECSPERMIN
Definition: tzfile.h:132
#define TRUE
Definition: app_minivm.c:503
static const int year_lengths[2]
Definition: localtime.c:905
static struct timeval WRONG
Definition: localtime.c:113
#define TYPE_BIT(type)
Definition: private.h:257
static int long_increment_overflow(long *number, int delta)
Definition: localtime.c:1888
#define EPOCH_YEAR
Definition: tzfile.h:165
#define TYPE_SIGNED(type)
Definition: private.h:261
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:171
static struct ast_tm* timesub ( const struct timeval *  timep,
const long  offset,
const struct state sp,
struct ast_tm tmp 
)
static

Definition at line 1741 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, 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, and while().

Referenced by gmtsub(), and localsub().

1742 {
1743  const struct lsinfo * lp;
1744  time_t tdays;
1745  int idays; /* unsigned would be so 2003 */
1746  long rem;
1747  int y;
1748  const int * ip;
1749  long corr;
1750  int hit;
1751  int i;
1752  long seconds;
1753 
1754 
1755  corr = 0;
1756  hit = 0;
1757  i = (sp == NULL) ? 0 : sp->leapcnt;
1758  while (--i >= 0) {
1759  lp = &sp->lsis[i];
1760  if (timep->tv_sec >= lp->ls_trans) {
1761  if (timep->tv_sec == lp->ls_trans) {
1762  hit = ((i == 0 && lp->ls_corr > 0) ||
1763  lp->ls_corr > sp->lsis[i - 1].ls_corr);
1764  if (hit)
1765  while (i > 0 &&
1766  sp->lsis[i].ls_trans ==
1767  sp->lsis[i - 1].ls_trans + 1 &&
1768  sp->lsis[i].ls_corr ==
1769  sp->lsis[i - 1].ls_corr + 1) {
1770  ++hit;
1771  --i;
1772  }
1773  }
1774  corr = lp->ls_corr;
1775  break;
1776  }
1777  }
1778  y = EPOCH_YEAR;
1779  tdays = timep->tv_sec / SECSPERDAY;
1780  rem = timep->tv_sec - tdays * SECSPERDAY;
1781  while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
1782  int newy;
1783  time_t tdelta;
1784  int idelta;
1785  int leapdays;
1786 
1787  tdelta = tdays / DAYSPERLYEAR;
1788  idelta = tdelta;
1789  if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
1790  return NULL;
1791  if (idelta == 0)
1792  idelta = (tdays < 0) ? -1 : 1;
1793  newy = y;
1794  if (increment_overflow(&newy, idelta))
1795  return NULL;
1796  leapdays = leaps_thru_end_of(newy - 1) -
1797  leaps_thru_end_of(y - 1);
1798  tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
1799  tdays -= leapdays;
1800  y = newy;
1801  }
1802 
1803  seconds = tdays * SECSPERDAY + 0.5;
1804  tdays = seconds / SECSPERDAY;
1805  rem += seconds - tdays * SECSPERDAY;
1806 
1807  /*
1808  ** Given the range, we can now fearlessly cast...
1809  */
1810  idays = tdays;
1811  rem += offset - corr;
1812  while (rem < 0) {
1813  rem += SECSPERDAY;
1814  --idays;
1815  }
1816  while (rem >= SECSPERDAY) {
1817  rem -= SECSPERDAY;
1818  ++idays;
1819  }
1820  while (idays < 0) {
1821  if (increment_overflow(&y, -1))
1822  return NULL;
1823  idays += year_lengths[isleap(y)];
1824  }
1825  while (idays >= year_lengths[isleap(y)]) {
1826  idays -= year_lengths[isleap(y)];
1827  if (increment_overflow(&y, 1))
1828  return NULL;
1829  }
1830  tmp->tm_year = y;
1832  return NULL;
1833  tmp->tm_yday = idays;
1834  /*
1835  ** The "extra" mods below avoid overflow problems.
1836  */
1837  tmp->tm_wday = EPOCH_WDAY +
1838  ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1840  leaps_thru_end_of(y - 1) -
1842  idays;
1843  tmp->tm_wday %= DAYSPERWEEK;
1844  if (tmp->tm_wday < 0)
1845  tmp->tm_wday += DAYSPERWEEK;
1846  tmp->tm_hour = (int) (rem / SECSPERHOUR);
1847  rem %= SECSPERHOUR;
1848  tmp->tm_min = (int) (rem / SECSPERMIN);
1849  /*
1850  ** A positive leap second requires a special
1851  ** representation. This uses "... ??:59:60" et seq.
1852  */
1853  tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1854  ip = mon_lengths[isleap(y)];
1855  for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1856  idays -= ip[tmp->tm_mon];
1857  tmp->tm_mday = (int) (idays + 1);
1858  tmp->tm_isdst = 0;
1859 #ifdef TM_GMTOFF
1860  tmp->TM_GMTOFF = offset;
1861 #endif /* defined TM_GMTOFF */
1862  tmp->tm_usec = timep->tv_usec;
1863  return tmp;
1864 }
#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 const int mon_lengths[2][MONSPERYEAR]
Definition: localtime.c:900
time_t ls_trans
Definition: localtime.c:144
int tm_year
Definition: localtime.h:41
struct lsinfo lsis[TZ_MAX_LEAPS]
Definition: localtime.c:174
#define SECSPERDAY
Definition: tzfile.h:139
int tm_mon
Definition: localtime.h:40
int tm_mday
Definition: localtime.h:39
int leapcnt
Definition: localtime.c:163
long ls_corr
Definition: localtime.c:145
static int increment_overflow(int *number, int delta)
Simplified normalize logic courtesy Paul Eggert.
Definition: localtime.c:1879
while(yyssp!=yyss)
Definition: ast_expr2.c:2538
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:143
static int leaps_thru_end_of(const int y)
Return the number of leap years through the end of the given year where, to make the math easy...
Definition: localtime.c:1735
int tm_sec
Definition: localtime.h:36
#define SECSPERMIN
Definition: tzfile.h:132
int tm_isdst
Definition: localtime.h:44
static const int year_lengths[2]
Definition: localtime.c:905
#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
static int tmcomp ( const struct ast_tm atmp,
const struct ast_tm btmp 
)
static

Definition at line 1919 of file localtime.c.

References 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().

1920 {
1921  int result;
1922 
1923  if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
1924  (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1925  (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1926  (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1927  (result = (atmp->tm_min - btmp->tm_min)) == 0 &&
1928  (result = (atmp->tm_sec - btmp->tm_sec)) == 0)
1929  result = atmp->tm_usec - btmp->tm_usec;
1930  return result;
1931 }
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
int tm_min
Definition: localtime.h:37
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 1092 of file localtime.c.

References 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().

1093 {
1094  int leapyear;
1095  time_t value;
1096  int i;
1097  int d, m1, yy0, yy1, yy2, dow;
1098 
1099  INITIALIZE(value);
1100  leapyear = isleap(year);
1101  switch (rulep->r_type) {
1102 
1103  case JULIAN_DAY:
1104  /*
1105  ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
1106  ** years.
1107  ** In non-leap years, or if the day number is 59 or less, just
1108  ** add SECSPERDAY times the day number-1 to the time of
1109  ** January 1, midnight, to get the day.
1110  */
1111  value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
1112  if (leapyear && rulep->r_day >= 60)
1113  value += SECSPERDAY;
1114  break;
1115 
1116  case DAY_OF_YEAR:
1117  /*
1118  ** n - day of year.
1119  ** Just add SECSPERDAY times the day number to the time of
1120  ** January 1, midnight, to get the day.
1121  */
1122  value = janfirst + rulep->r_day * SECSPERDAY;
1123  break;
1124 
1125  case MONTH_NTH_DAY_OF_WEEK:
1126  /*
1127  ** Mm.n.d - nth "dth day" of month m.
1128  */
1129  value = janfirst;
1130  for (i = 0; i < rulep->r_mon - 1; ++i)
1131  value += mon_lengths[leapyear][i] * SECSPERDAY;
1132 
1133  /*
1134  ** Use Zeller's Congruence to get day-of-week of first day of
1135  ** month.
1136  */
1137  m1 = (rulep->r_mon + 9) % 12 + 1;
1138  yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
1139  yy1 = yy0 / 100;
1140  yy2 = yy0 % 100;
1141  dow = ((26 * m1 - 2) / 10 +
1142  1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1143  if (dow < 0)
1144  dow += DAYSPERWEEK;
1145 
1146  /*
1147  ** "dow" is the day-of-week of the first day of the month. Get
1148  ** the day-of-month (zero-origin) of the first "dow" day of the
1149  ** month.
1150  */
1151  d = rulep->r_day - dow;
1152  if (d < 0)
1153  d += DAYSPERWEEK;
1154  for (i = 1; i < rulep->r_week; ++i) {
1155  if (d + DAYSPERWEEK >=
1156  mon_lengths[leapyear][rulep->r_mon - 1])
1157  break;
1158  d += DAYSPERWEEK;
1159  }
1160 
1161  /*
1162  ** "d" is the day-of-month (zero-origin) of the day we want.
1163  */
1164  value += d * SECSPERDAY;
1165  break;
1166  }
1167 
1168  /*
1169  ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
1170  ** question. To get the Epoch-relative time of the specified local
1171  ** time on that day, add the transition time and the current offset
1172  ** from UTC.
1173  */
1174  return value + rulep->r_time + offset;
1175 }
#define isleap(y)
Definition: tzfile.h:168
#define INITIALIZE(x)
Definition: private.h:302
static const int mon_lengths[2][MONSPERYEAR]
Definition: localtime.c:900
int r_day
Definition: localtime.c:198
int r_week
Definition: localtime.c:199
int value
Definition: syslog.c:39
int r_mon
Definition: localtime.c:200
#define SECSPERDAY
Definition: tzfile.h:139
long r_time
Definition: localtime.c:201
#define DAY_OF_YEAR
Definition: localtime.c:205
#define DAYSPERWEEK
Definition: tzfile.h:135
#define MONTH_NTH_DAY_OF_WEEK
Definition: localtime.c:206
#define JULIAN_DAY
Definition: localtime.c:204
int r_type
Definition: localtime.c:197
static int tzload ( const char *  name,
struct state *const  sp,
const int  doextend 
)
static

Definition at line 662 of file localtime.c.

References add_notify(), ast_fully_booted, state::ats, state::charcnt, state::chars, detzcode(), detzcode64(), differ_by_repeat(), FALSE, FILENAME_MAX, for(), state::goahead, state::goback, if(), state::leapcnt, lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, state::name, OPEN_MODE, 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().

663 {
664  const char * p;
665  int i;
666  int fid;
667  int stored;
668  int nread;
669  union {
670  struct tzhead tzhead;
671  char buf[2 * sizeof(struct tzhead) +
672  2 * sizeof *sp +
673  4 * TZ_MAX_TIMES];
674  } u;
675 
676  if (name == NULL && (name = TZDEFAULT) == NULL)
677  return -1;
678  {
679  int doaccess;
680  /*
681  ** Section 4.9.1 of the C standard says that
682  ** "FILENAME_MAX expands to an integral constant expression
683  ** that is the size needed for an array of char large enough
684  ** to hold the longest file name string that the implementation
685  ** guarantees can be opened."
686  */
687  char fullname[FILENAME_MAX + 1];
688 
689  if (name[0] == ':')
690  ++name;
691  doaccess = name[0] == '/';
692  if (!doaccess) {
693  if ((p = TZDIR) == NULL)
694  return -1;
695  if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
696  return -1;
697  (void) strcpy(fullname, p);
698  (void) strcat(fullname, "/");
699  (void) strcat(fullname, name);
700  /*
701  ** Set doaccess if '.' (as in "../") shows up in name.
702  */
703  if (strchr(name, '.') != NULL)
704  doaccess = TRUE;
705  name = fullname;
706  }
707  if (doaccess && access(name, R_OK) != 0)
708  return -1;
709  if ((fid = open(name, OPEN_MODE)) == -1)
710  return -1;
711  if (ast_fully_booted) {
712  /* If we don't wait until Asterisk is fully booted, it's possible
713  * that the watcher thread gets started in the parent process,
714  * before daemon(3) is called, and the thread won't propagate to
715  * the child. Given that bootup only takes a few seconds, it's
716  * reasonable to only start the watcher later. */
717  add_notify(sp, name);
718  }
719  }
720  nread = read(fid, u.buf, sizeof u.buf);
721  if (close(fid) < 0 || nread <= 0)
722  return -1;
723  for (stored = 4; stored <= 8; stored *= 2) {
724  int ttisstdcnt;
725  int ttisgmtcnt;
726 
727  ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
728  ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
729  sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
730  sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
731  sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
732  sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
733  p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
734  if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
735  sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
736  sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
737  sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
738  (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
739  (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
740  return -1;
741  if (nread - (p - u.buf) <
742  sp->timecnt * stored + /* ats */
743  sp->timecnt + /* types */
744  sp->typecnt * 6 + /* ttinfos */
745  sp->charcnt + /* chars */
746  sp->leapcnt * (stored + 4) + /* lsinfos */
747  ttisstdcnt + /* ttisstds */
748  ttisgmtcnt) /* ttisgmts */
749  return -1;
750  for (i = 0; i < sp->timecnt; ++i) {
751  sp->ats[i] = (stored == 4) ?
752  detzcode(p) : detzcode64(p);
753  p += stored;
754  }
755  for (i = 0; i < sp->timecnt; ++i) {
756  sp->types[i] = (unsigned char) *p++;
757  if (sp->types[i] >= sp->typecnt)
758  return -1;
759  }
760  for (i = 0; i < sp->typecnt; ++i) {
761  struct ttinfo * ttisp;
762 
763  ttisp = &sp->ttis[i];
764  ttisp->tt_gmtoff = detzcode(p);
765  p += 4;
766  ttisp->tt_isdst = (unsigned char) *p++;
767  if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
768  return -1;
769  ttisp->tt_abbrind = (unsigned char) *p++;
770  if (ttisp->tt_abbrind < 0 ||
771  ttisp->tt_abbrind > sp->charcnt)
772  return -1;
773  }
774  for (i = 0; i < sp->charcnt; ++i)
775  sp->chars[i] = *p++;
776  sp->chars[i] = '\0'; /* ensure '\0' at end */
777  for (i = 0; i < sp->leapcnt; ++i) {
778  struct lsinfo * lsisp;
779 
780  lsisp = &sp->lsis[i];
781  lsisp->ls_trans = (stored == 4) ?
782  detzcode(p) : detzcode64(p);
783  p += stored;
784  lsisp->ls_corr = detzcode(p);
785  p += 4;
786  }
787  for (i = 0; i < sp->typecnt; ++i) {
788  struct ttinfo * ttisp;
789 
790  ttisp = &sp->ttis[i];
791  if (ttisstdcnt == 0)
792  ttisp->tt_ttisstd = FALSE;
793  else {
794  ttisp->tt_ttisstd = *p++;
795  if (ttisp->tt_ttisstd != TRUE &&
796  ttisp->tt_ttisstd != FALSE)
797  return -1;
798  }
799  }
800  for (i = 0; i < sp->typecnt; ++i) {
801  struct ttinfo * ttisp;
802 
803  ttisp = &sp->ttis[i];
804  if (ttisgmtcnt == 0)
805  ttisp->tt_ttisgmt = FALSE;
806  else {
807  ttisp->tt_ttisgmt = *p++;
808  if (ttisp->tt_ttisgmt != TRUE &&
809  ttisp->tt_ttisgmt != FALSE)
810  return -1;
811  }
812  }
813  /*
814  ** Out-of-sort ats should mean we're running on a
815  ** signed time_t system but using a data file with
816  ** unsigned values (or vice versa).
817  */
818  for (i = 0; i < sp->timecnt - 2; ++i)
819  if (sp->ats[i] > sp->ats[i + 1]) {
820  ++i;
821  if (TYPE_SIGNED(time_t)) {
822  /*
823  ** Ignore the end (easy).
824  */
825  sp->timecnt = i;
826  } else {
827  /*
828  ** Ignore the beginning (harder).
829  */
830  int j;
831 
832  for (j = 0; j + i < sp->timecnt; ++j) {
833  sp->ats[j] = sp->ats[j + i];
834  sp->types[j] = sp->types[j + i];
835  }
836  sp->timecnt = j;
837  }
838  break;
839  }
840  /*
841  ** If this is an old file, we're done.
842  */
843  if (u.tzhead.tzh_version[0] == '\0')
844  break;
845  nread -= p - u.buf;
846  for (i = 0; i < nread; ++i)
847  u.buf[i] = p[i];
848  /*
849  ** If this is a narrow integer time_t system, we're done.
850  */
851  if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
852  break;
853  }
854  if (doextend && nread > 2 &&
855  u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
856  sp->typecnt + 2 <= TZ_MAX_TYPES) {
857  struct state ts;
858  int result;
859 
860  u.buf[nread - 1] = '\0';
861  result = tzparse(&u.buf[1], &ts, FALSE);
862  if (result == 0 && ts.typecnt == 2 &&
863  sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
864  for (i = 0; i < 2; ++i)
865  ts.ttis[i].tt_abbrind +=
866  sp->charcnt;
867  for (i = 0; i < ts.charcnt; ++i)
868  sp->chars[sp->charcnt++] =
869  ts.chars[i];
870  i = 0;
871  while (i < ts.timecnt &&
872  ts.ats[i] <=
873  sp->ats[sp->timecnt - 1])
874  ++i;
875  while (i < ts.timecnt &&
876  sp->timecnt < TZ_MAX_TIMES) {
877  sp->ats[sp->timecnt] =
878  ts.ats[i];
879  sp->types[sp->timecnt] =
880  sp->typecnt +
881  ts.types[i];
882  ++sp->timecnt;
883  ++i;
884  }
885  sp->ttis[sp->typecnt++] = ts.ttis[0];
886  sp->ttis[sp->typecnt++] = ts.ttis[1];
887  }
888  }
889  i = 2 * YEARSPERREPEAT;
890  sp->goback = sp->goahead = sp->timecnt > i;
891  sp->goback = sp->goback && sp->types[i] == sp->types[0] &&
892  differ_by_repeat(sp->ats[i], sp->ats[0]);
893  sp->goahead = sp->goahead &&
894  sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
895  differ_by_repeat(sp->ats[sp->timecnt - 1],
896  sp->ats[sp->timecnt - 1 - i]);
897  return 0;
898 }
static time_t detzcode64(const char *const codep)
Definition: localtime.c:642
#define TZDEFAULT
Definition: tzfile.h:41
#define FALSE
Definition: app_minivm.c:506
time type information
Definition: localtime.c:134
int typecnt
Definition: localtime.c:165
#define TZ_MAX_TIMES
Definition: tzfile.h:107
for(;;)
Definition: ast_expr2.c:2460
time_t ls_trans
Definition: localtime.c:144
long tt_gmtoff
Definition: localtime.c:135
int goahead
Definition: localtime.c:168
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, sizeof gmt),(2 *(MY_TZNAME_MAX+1)))]
Definition: localtime.c:173
#define TZ_MAX_LEAPS
Definition: tzfile.h:129
#define OPEN_MODE
Definition: localtime.c:109
struct lsinfo lsis[TZ_MAX_LEAPS]
Definition: localtime.c:174
#define TZDIR
Definition: tzfile.h:36
#define ast_fully_booted
Definition: options.h:113
#define FILENAME_MAX
Definition: private.h:207
int charcnt
Definition: localtime.c:166
int tt_ttisstd
Definition: localtime.c:138
static long detzcode(const char *const codep)
Definition: localtime.c:631
int goback
Definition: localtime.c:167
int leapcnt
Definition: localtime.c:163
#define TZ_MAX_CHARS
Definition: tzfile.h:124
long ls_corr
Definition: localtime.c:145
while(yyssp!=yyss)
Definition: ast_expr2.c:2538
static const char name[]
Definition: tzfile.h:54
int tt_isdst
Definition: localtime.c:136
#define TYPE_INTEGRAL(type)
Definition: private.h:270
static int differ_by_repeat(const time_t t1, const time_t t0)
Definition: localtime.c:653
if(yyss+yystacksize-1<=yyssp)
Definition: ast_expr2.c:1874
leap second information
Definition: localtime.c:143
#define YEARSPERREPEAT
Definition: private.h:335
#define TRUE
Definition: app_minivm.c:503
#define TZ_MAX_TYPES
Definition: tzfile.h:112
time_t ats[TZ_MAX_TIMES]
Definition: localtime.c:169
static int tzparse(const char *name, struct state *sp, const int lastditch)
Definition: localtime.c:1182
unsigned char types[TZ_MAX_TIMES]
Definition: localtime.c:170
#define TYPE_SIGNED(type)
Definition: private.h:261
static void add_notify(struct state *sp, const char *path)
Definition: localtime.c:328
int tt_ttisgmt
Definition: localtime.c:139
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:171
int timecnt
Definition: localtime.c:164
int tt_abbrind
Definition: localtime.c:137
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 1182 of file localtime.c.

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

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

1183 {
1184  const char * stdname;
1185  const char * dstname;
1186  size_t stdlen;
1187  size_t dstlen;
1188  long stdoffset;
1189  long dstoffset;
1190  time_t * atp;
1191  unsigned char * typep;
1192  char * cp;
1193  int load_result;
1194 
1195  INITIALIZE(dstname);
1196  stdname = name;
1197  if (lastditch) {
1198  stdlen = strlen(name); /* length of standard zone name */
1199  name += stdlen;
1200  if (stdlen >= sizeof sp->chars)
1201  stdlen = (sizeof sp->chars) - 1;
1202  stdoffset = 0;
1203  } else {
1204  if (*name == '<') {
1205  name++;
1206  stdname = name;
1207  name = getqzname(name, '>');
1208  if (*name != '>')
1209  return -1;
1210  stdlen = name - stdname;
1211  name++;
1212  } else {
1213  name = getzname(name);
1214  stdlen = name - stdname;
1215  }
1216  if (*name == '\0')
1217  return -1;
1218  name = getoffset(name, &stdoffset);
1219  if (name == NULL)
1220  return -1;
1221  }
1222  load_result = tzload(TZDEFRULES, sp, FALSE);
1223  if (load_result != 0)
1224  sp->leapcnt = 0; /* so, we're off a little */
1225  if (*name != '\0') {
1226  if (*name == '<') {
1227  dstname = ++name;
1228  name = getqzname(name, '>');
1229  if (*name != '>')
1230  return -1;
1231  dstlen = name - dstname;
1232  name++;
1233  } else {
1234  dstname = name;
1235  name = getzname(name);
1236  dstlen = name - dstname; /* length of DST zone name */
1237  }
1238  if (*name != '\0' && *name != ',' && *name != ';') {
1239  name = getoffset(name, &dstoffset);
1240  if (name == NULL)
1241  return -1;
1242  } else dstoffset = stdoffset - SECSPERHOUR;
1243  if (*name == '\0' && load_result != 0)
1245  if (*name == ',' || *name == ';') {
1246  struct rule start;
1247  struct rule end;
1248  int year;
1249  time_t janfirst;
1250  time_t starttime;
1251  time_t endtime;
1252 
1253  ++name;
1254  if ((name = getrule(name, &start)) == NULL)
1255  return -1;
1256  if (*name++ != ',')
1257  return -1;
1258  if ((name = getrule(name, &end)) == NULL)
1259  return -1;
1260  if (*name != '\0')
1261  return -1;
1262  sp->typecnt = 2; /* standard time and DST */
1263  /*
1264  ** Two transitions per year, from EPOCH_YEAR forward.
1265  */
1266  sp->ttis[0].tt_gmtoff = -dstoffset;
1267  sp->ttis[0].tt_isdst = 1;
1268  sp->ttis[0].tt_abbrind = stdlen + 1;
1269  sp->ttis[1].tt_gmtoff = -stdoffset;
1270  sp->ttis[1].tt_isdst = 0;
1271  sp->ttis[1].tt_abbrind = 0;
1272  atp = sp->ats;
1273  typep = sp->types;
1274  janfirst = 0;
1275  sp->timecnt = 0;
1276  for (year = EPOCH_YEAR;
1277  sp->timecnt + 2 <= TZ_MAX_TIMES;
1278  ++year) {
1279  time_t newfirst;
1280 
1281  starttime = transtime(janfirst, year, &start,
1282  stdoffset);
1283  endtime = transtime(janfirst, year, &end,
1284  dstoffset);
1285  if (starttime > endtime) {
1286  *atp++ = endtime;
1287  *typep++ = 1; /* DST ends */
1288  *atp++ = starttime;
1289  *typep++ = 0; /* DST begins */
1290  } else {
1291  *atp++ = starttime;
1292  *typep++ = 0; /* DST begins */
1293  *atp++ = endtime;
1294  *typep++ = 1; /* DST ends */
1295  }
1296  sp->timecnt += 2;
1297  newfirst = janfirst;
1298  newfirst += year_lengths[isleap(year)] *
1299  SECSPERDAY;
1300  if (newfirst <= janfirst)
1301  break;
1302  janfirst = newfirst;
1303  }
1304  } else {
1305  long theirstdoffset;
1306  long theirdstoffset;
1307  long theiroffset;
1308  int isdst;
1309  int i;
1310  int j;
1311 
1312  if (*name != '\0')
1313  return -1;
1314  /*
1315  ** Initial values of theirstdoffset and theirdstoffset.
1316  */
1317  theirstdoffset = 0;
1318  for (i = 0; i < sp->timecnt; ++i) {
1319  j = sp->types[i];
1320  if (!sp->ttis[j].tt_isdst) {
1321  theirstdoffset =
1322  -sp->ttis[j].tt_gmtoff;
1323  break;
1324  }
1325  }
1326  theirdstoffset = 0;
1327  for (i = 0; i < sp->timecnt; ++i) {
1328  j = sp->types[i];
1329  if (sp->ttis[j].tt_isdst) {
1330  theirdstoffset =
1331  -sp->ttis[j].tt_gmtoff;
1332  break;
1333  }
1334  }
1335  /*
1336  ** Initially we're assumed to be in standard time.
1337  */
1338  isdst = FALSE;
1339  theiroffset = theirstdoffset;
1340  /*
1341  ** Now juggle transition times and types
1342  ** tracking offsets as you do.
1343  */
1344  for (i = 0; i < sp->timecnt; ++i) {
1345  j = sp->types[i];
1346  sp->types[i] = sp->ttis[j].tt_isdst;
1347  if (sp->ttis[j].tt_ttisgmt) {
1348  /* No adjustment to transition time */
1349  } else {
1350  /*
1351  ** If summer time is in effect, and the
1352  ** transition time was not specified as
1353  ** standard time, add the summer time
1354  ** offset to the transition time;
1355  ** otherwise, add the standard time
1356  ** offset to the transition time.
1357  */
1358  /*
1359  ** Transitions from DST to DDST
1360  ** will effectively disappear since
1361  ** POSIX provides for only one DST
1362  ** offset.
1363  */
1364  if (isdst && !sp->ttis[j].tt_ttisstd) {
1365  sp->ats[i] += dstoffset -
1366  theirdstoffset;
1367  } else {
1368  sp->ats[i] += stdoffset -
1369  theirstdoffset;
1370  }
1371  }
1372  theiroffset = -sp->ttis[j].tt_gmtoff;
1373  if (sp->ttis[j].tt_isdst)
1374  theirdstoffset = theiroffset;
1375  else theirstdoffset = theiroffset;
1376  }
1377  /*
1378  ** Finally, fill in ttis.
1379  ** ttisstd and ttisgmt need not be handled.
1380  */
1381  sp->ttis[0].tt_gmtoff = -stdoffset;
1382  sp->ttis[0].tt_isdst = FALSE;
1383  sp->ttis[0].tt_abbrind = 0;
1384  sp->ttis[1].tt_gmtoff = -dstoffset;
1385  sp->ttis[1].tt_isdst = TRUE;
1386  sp->ttis[1].tt_abbrind = stdlen + 1;
1387  sp->typecnt = 2;
1388  }
1389  } else {
1390  dstlen = 0;
1391  sp->typecnt = 1; /* only standard time */
1392  sp->timecnt = 0;
1393  sp->ttis[0].tt_gmtoff = -stdoffset;
1394  sp->ttis[0].tt_isdst = 0;
1395  sp->ttis[0].tt_abbrind = 0;
1396  }
1397  sp->charcnt = stdlen + 1;
1398  if (dstlen != 0)
1399  sp->charcnt += dstlen + 1;
1400  if ((size_t) sp->charcnt > sizeof sp->chars)
1401  return -1;
1402  cp = sp->chars;
1403  (void) strncpy(cp, stdname, stdlen);
1404  cp += stdlen;
1405  *cp++ = '\0';
1406  if (dstlen != 0) {
1407  (void) strncpy(cp, dstname, dstlen);
1408  *(cp + dstlen) = '\0';
1409  }
1410  return 0;
1411 }
static const char * getoffset(const char *strp, long *offsetp)
Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the time.
Definition: localtime.c:1017
#define FALSE
Definition: app_minivm.c:506
#define isleap(y)
Definition: tzfile.h:168
#define INITIALIZE(x)
Definition: private.h:302
static const char * getqzname(const char *strp, const int delim)
Given a pointer into an extended time zone string, scan until the ending delimiter of the zone name i...
Definition: localtime.c:934
int typecnt
Definition: localtime.c:165
static const char * getrule(const char *strp, struct rule *rulep)
Given a pointer into a time zone string, extract a rule in the form date[/time]. See POSIX section 8 ...
Definition: localtime.c:1041
#define TZ_MAX_TIMES
Definition: tzfile.h:107
long tt_gmtoff
Definition: localtime.c:135
#define TZDEFRULESTRING
Definition: localtime.c:130
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, sizeof gmt),(2 *(MY_TZNAME_MAX+1)))]
Definition: localtime.c:173
static int tzload(const char *name, struct state *const sp, const int doextend)
Definition: localtime.c:662
#define SECSPERDAY
Definition: tzfile.h:139
int charcnt
Definition: localtime.c:166
int tt_ttisstd
Definition: localtime.c:138
int leapcnt
Definition: localtime.c:163
static const char name[]
int tt_isdst
Definition: localtime.c:136
#define TZDEFRULES
Definition: tzfile.h:45
#define TRUE
Definition: app_minivm.c:503
static const int year_lengths[2]
Definition: localtime.c:905
time_t ats[TZ_MAX_TIMES]
Definition: localtime.c:169
#define EPOCH_YEAR
Definition: tzfile.h:165
unsigned char types[TZ_MAX_TIMES]
Definition: localtime.c:170
#define SECSPERHOUR
Definition: tzfile.h:138
int tt_ttisgmt
Definition: localtime.c:139
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:171
int timecnt
Definition: localtime.c:164
int tt_abbrind
Definition: localtime.c:137
static const char * getzname(const char *strp)
Given a pointer into a time zone string, scan until a character that is not a valid character in a zo...
Definition: localtime.c:915
static time_t transtime(const time_t janfirst, const int year, const struct rule *rulep, const long offset)
Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect.
Definition: localtime.c:1092

Variable Documentation

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

Definition at line 84 of file localtime.c.

const char gmt[] = "GMT"
static

Definition at line 112 of file localtime.c.

ast_cond_t initialization
static

Definition at line 267 of file localtime.c.

ast_mutex_t initialization_lock
static

Definition at line 268 of file localtime.c.

int inotify_fd = -1
static

Definition at line 270 of file localtime.c.

Referenced by scan_thread().

pthread_t inotify_thread = AST_PTHREADT_NULL
static

Definition at line 266 of file localtime.c.

struct localelist localelist = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
static
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 900 of file localtime.c.

struct timeval WRONG = { 0, 0 }
static

Definition at line 113 of file localtime.c.

Referenced by time1(), and time2sub().

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

Definition at line 905 of file localtime.c.

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