Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Macros | Functions | Variables
localtime.c File Reference
#include "asterisk.h"
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <float.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include "private.h"
#include "tzfile.h"
#include "asterisk/_private.h"
#include "asterisk/lock.h"
#include "asterisk/localtime.h"
#include "asterisk/strings.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/test.h"

Go to the source code of this file.

Data Structures

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

Macros

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

Functions

static void add_notify (struct state *sp, const char *path)
 
void ast_get_dst_info (const time_t *const timep, int *dst_enabled, time_t *dst_start, time_t *dst_end, int *gmt_off, const char *const zone)
 
struct ast_tmast_localtime (const struct timeval *timep, struct ast_tm *tmp, const char *zone)
 Timezone-independent version of localtime_r(3). More...
 
void ast_localtime_wakeup_monitor (struct ast_test *info)
 
struct timeval ast_mktime (struct ast_tm *tmp, const char *zone)
 Timezone-independent version of mktime(3). More...
 
const char * ast_setlocale (const char *locale)
 Set the thread-local representation of the current locale.
 
int ast_strftime (char *buf, size_t len, const char *tmp, const struct ast_tm *tm)
 Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strftime(3), with the addition of q, which specifies microseconds. More...
 
int ast_strftime_locale (char *buf, size_t len, const char *tmp, const struct ast_tm *tm, const char *locale)
 
char * ast_strptime (const char *s, const char *format, struct ast_tm *tm)
 Special version of strptime(3) which places the answer in the common structure ast_tm. Also, unlike strptime(3), ast_strptime() initializes its memory prior to use. More...
 
char * ast_strptime_locale (const char *s, const char *format, struct ast_tm *tm, const char *locale)
 
static const struct stateast_tzset (const char *zone)
 
void clean_time_zones (void)
 
static void common_startup (void)
 
static long detzcode (const char *const codep)
 
static time_t detzcode64 (const char *const codep)
 
static int differ_by_repeat (const time_t t1, const time_t t0)
 
static struct locale_entryfind_by_locale (locale_t locale)
 
static struct locale_entryfind_by_name (const char *name)
 
static const char * getnum (const char *strp, int *nump, const int min, const int max)
 Given a pointer into a time zone string, extract a number from that string. Check that the number is within a specified range; if it is not, return NULL. Otherwise, return a pointer to the first character not part of the number.
 
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.
 
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.
 
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.
 
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.
 
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.
 
static struct ast_tmlocalsub (const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
 
static int long_increment_overflow (long *number, int delta)
 
static int long_normalize_overflow (long *tensptr, int *unitsptr, const int base)
 
static int normalize_overflow (int *tensptr, int *unitsptr, const int base)
 
static long detzcode P ((const char *codep))
 
static int differ_by_repeat P ((time_t t1, time_t t0))
 
static const char *getzname P ((const char *strp))
 
static const char *getqzname P ((const char *strp, const int delim))
 
static const char *getnum P ((const char *strp, int *nump, int min, int max))
 
static const char *getsecs P ((const char *strp, long *secsp))
 
static const char *getoffset P ((const char *strp, long *offsetp))
 
static const char *getrule P ((const char *strp, struct rule *rulep))
 
static int gmtload P ((struct state *sp))
 
static struct ast_tm *gmtsub P ((const struct timeval *timep, long offset, struct ast_tm *tmp))
 
static struct ast_tm *localsub P ((const struct timeval *timep, long offset, struct ast_tm *tmp, const struct state *sp))
 
static int increment_overflow P ((int *number, int delta))
 
static int leaps_thru_end_of P ((int y))
 
static int long_increment_overflow P ((long *number, int delta))
 
static int long_normalize_overflow P ((long *tensptr, int *unitsptr, const int base))
 
static int normalize_overflow P ((int *tensptr, int *unitsptr, const int base))
 
static struct timeval time1 P ((struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, const struct state *sp))
 
static struct timeval time2sub P ((struct ast_tm *tmp, struct ast_tm *(*funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp))
 
static struct timeval time2 P ((struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp))
 
static struct ast_tm *timesub P ((const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp))
 
static int tmcomp P ((const struct ast_tm *atmp, const struct ast_tm *btmp))
 
static time_t transtime P ((time_t janfirst, int year, const struct rule *rulep, long offset))
 
static int tzload P ((const char *name, struct state *sp, int doextend))
 
static int tzparse P ((const char *name, struct state *sp, int lastditch))
 
static struct statesstate_alloc (void)
 
static void sstate_free (struct state *p)
 
static const char * store_by_locale (locale_t prevlocale)
 
static struct timeval time1 (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, const struct state *sp)
 
static struct timeval time2 (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), const long offset, int *okayp, const struct state *sp)
 
static struct timeval time2sub (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, int *okayp, const int do_norm_secs, const struct state *sp)
 
static struct ast_tmtimesub (const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
 
static int tmcomp (const struct ast_tm *atmp, const struct ast_tm *btmp)
 
static time_t transtime (const time_t janfirst, const int year, const struct rule *rulep, const long offset)
 Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect.
 
static int tzload (const char *name, struct state *const sp, const int doextend)
 
static int tzparse (const char *name, struct state *sp, const int lastditch)
 

Variables

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

Detailed Description

Multi-timezone Localtime code

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

Definition in file localtime.c.

Macro Definition Documentation

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

Definition at line 195 of file localtime.c.

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

Definition at line 191 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 128 of file localtime.c.

Referenced by tzparse().

Function Documentation

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

Timezone-independent version of localtime_r(3).

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

Definition at line 1739 of file localtime.c.

References localsub().

Referenced by action_corestatus(), ast_cel_fabricate_channel_from_event(), ast_check_timing2(), ast_http_send(), ast_json_timeval(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_fr(), ast_say_date_gr(), ast_say_date_he(), ast_say_date_hu(), ast_say_date_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_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(), get_date(), handle_minivm_show_stats(), handle_show_settings(), isodate(), make_email_file(), packdate(), set_timezone_variables(), sms_handleincoming_proto2(), vmu_tm(), and write_metadata().

1740 {
1741  const struct state *sp = ast_tzset(zone);
1742  memset(tmp, 0, sizeof(*tmp));
1743  return sp ? localsub(timep, 0L, tmp, sp) : NULL;
1744 }
static struct ast_tm * localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
Definition: localtime.c:1648
struct timeval ast_mktime ( struct ast_tm *const  tmp,
const char *  zone 
)

Timezone-independent version of mktime(3).

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

Definition at line 2357 of file localtime.c.

References localsub().

Referenced by sms_handleincoming_proto2(), sms_readfile(), and unpackdate().

2358 {
2359  const struct state *sp;
2360  if (!(sp = ast_tzset(zone)))
2361  return WRONG;
2362  return time1(tmp, localsub, 0L, sp);
2363 }
static struct ast_tm * localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
Definition: localtime.c:1648
int ast_strftime ( char *  buf,
size_t  len,
const char *  format,
const struct ast_tm tm 
)

Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strftime(3), with the addition of q, which specifies microseconds.

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

Definition at line 2524 of file localtime.c.

Referenced by action_corestatus(), ast_cel_fabricate_channel_from_event(), ast_http_send(), ast_json_timeval(), get_date(), handle_minivm_show_stats(), handle_show_settings(), isodate(), make_email_file(), and write_metadata().

2525 {
2526  return ast_strftime_locale(buf, len, tmp, tm, NULL);
2527 }
char* ast_strptime ( const char *  s,
const char *  format,
struct ast_tm tm 
)

Special version of strptime(3) which places the answer in the common structure ast_tm. Also, unlike strptime(3), ast_strptime() initializes its memory prior to use.

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

Definition at line 2550 of file localtime.c.

2551 {
2552  return ast_strptime_locale(s, format, tm, NULL);
2553 }
void clean_time_zones ( void  )

Provided by localtime.c

Definition at line 1590 of file localtime.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, and AST_LIST_UNLOCK.

Referenced by really_quit().

1591 {
1592  struct state *sp;
1593 
1595  while ((sp = AST_LIST_REMOVE_HEAD(&zonelist, list))) {
1596  sstate_free(sp);
1597  }
1599 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
static void common_startup ( void  )
static

Start a notification for every entry already in the list.

Definition at line 328 of file localtime.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and state::name.

328  {
329  struct state *sp;
331  AST_LIST_TRAVERSE(&zonelist, sp, list) {
332  /* ensure sp->name is not relative -- it
333  * often is -- otherwise add_notify() fails
334  */
335  char name[FILENAME_MAX + 1];
336 
337  if (sp->name[0] == '/') {
338  snprintf(name, sizeof(name), "%s", sp->name);
339  } else if (!strcmp(sp->name, TZDEFAULT)) {
340  snprintf(name, sizeof(name), "/etc/%s", sp->name);
341  } else {
342  snprintf(name, sizeof(name), "%s/%s", TZDIR, sp->name);
343  }
344 
345  add_notify(sp, name);
346  }
348 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
char name[TZ_STRLEN_MAX+1]
Definition: localtime.c:160
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
static long detzcode ( const char *const  codep)
static
Note
Section 4.12.3 of X3.159-1989 requires that Except for the strftime function, these functions [asctime, ctime, gmtime, localtime] return values in one of two static objects: a broken-down time structure and an array of char. Thanks to Paul Eggert for noting this.

Definition at line 822 of file localtime.c.

823 {
824  long result;
825  int i;
826 
827  result = (codep[0] & 0x80) ? ~0L : 0;
828  for (i = 0; i < 4; ++i)
829  result = (result << 8) | (codep[i] & 0xff);
830  return result;
831 }
static const char* getqzname ( const char *  strp,
const int  delim 
)
static

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

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

Definition at line 1137 of file localtime.c.

Referenced by tzparse().

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

Simplified normalize logic courtesy Paul Eggert.

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

Definition at line 2051 of file localtime.c.

2052 {
2053  int number0;
2054 
2055  number0 = *number;
2056  *number += delta;
2057  return (*number < number0) != (delta < 0);
2058 }
Number structure.
Definition: app_followme.c:154
static struct ast_tm* localsub ( const struct timeval *  timep,
const long  offset,
struct ast_tm tmp,
const struct state sp 
)
static
Note
The easy way to behave "as if no library function calls" localtime is to not call it–so we drop its guts into "localsub", which can be freely called. (And no, the PANS doesn't require the above behavior– but it is desirable.)

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

Definition at line 1648 of file localtime.c.

References ast_tm::tm_gmtoff, ast_tm::tm_isdst, ast_tm::tm_usec, and ast_tm::tm_year.

Referenced by ast_localtime(), and ast_mktime().

1649 {
1650  const struct ttinfo * ttisp;
1651  int i;
1652  struct ast_tm * result;
1653  struct timeval t;
1654  memcpy(&t, timep, sizeof(t));
1655 
1656  if (sp == NULL)
1657  return gmtsub(timep, offset, tmp);
1658  if ((sp->goback && t.tv_sec < sp->ats[0]) ||
1659  (sp->goahead && t.tv_sec > sp->ats[sp->timecnt - 1])) {
1660  struct timeval newt = t;
1661  time_t seconds;
1662  time_t tcycles;
1663  int_fast64_t icycles;
1664 
1665  if (t.tv_sec < sp->ats[0])
1666  seconds = sp->ats[0] - t.tv_sec;
1667  else seconds = t.tv_sec - sp->ats[sp->timecnt - 1];
1668  --seconds;
1669  tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1670  ++tcycles;
1671  icycles = tcycles;
1672  if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1673  return NULL;
1674  seconds = icycles;
1675  seconds *= YEARSPERREPEAT;
1676  seconds *= AVGSECSPERYEAR;
1677  if (t.tv_sec < sp->ats[0])
1678  newt.tv_sec += seconds;
1679  else newt.tv_sec -= seconds;
1680  if (newt.tv_sec < sp->ats[0] ||
1681  newt.tv_sec > sp->ats[sp->timecnt - 1])
1682  return NULL; /* "cannot happen" */
1683  result = localsub(&newt, offset, tmp, sp);
1684  if (result == tmp) {
1685  time_t newy;
1686 
1687  newy = tmp->tm_year;
1688  if (t.tv_sec < sp->ats[0])
1689  newy -= icycles * YEARSPERREPEAT;
1690  else
1691  newy += icycles * YEARSPERREPEAT;
1692  tmp->tm_year = newy;
1693  if (tmp->tm_year != newy)
1694  return NULL;
1695  }
1696  return result;
1697  }
1698  if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) {
1699  i = 0;
1700  while (sp->ttis[i].tt_isdst) {
1701  if (++i >= sp->typecnt) {
1702  i = 0;
1703  break;
1704  }
1705  }
1706  } else {
1707  int lo = 1;
1708  int hi = sp->timecnt;
1709 
1710  while (lo < hi) {
1711  int mid = (lo + hi) >> 1;
1712 
1713  if (t.tv_sec < sp->ats[mid])
1714  hi = mid;
1715  else
1716  lo = mid + 1;
1717  }
1718  i = (int) sp->types[lo - 1];
1719  }
1720  ttisp = &sp->ttis[i];
1721  /*
1722  ** To get (wrong) behavior that's compatible with System V Release 2.0
1723  ** you'd replace the statement below with
1724  ** t += ttisp->tt_gmtoff;
1725  ** timesub(&t, 0L, sp, tmp);
1726  */
1727  result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1728  tmp->tm_isdst = ttisp->tt_isdst;
1729 #ifndef SOLARIS /* Solaris doesn't have this element */
1730  tmp->tm_gmtoff = ttisp->tt_gmtoff;
1731 #endif
1732 #ifdef TM_ZONE
1733  tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
1734 #endif /* defined TM_ZONE */
1735  tmp->tm_usec = timep->tv_usec;
1736  return result;
1737 }
static struct ast_tm * localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
Definition: localtime.c:1648
int tm_usec
Definition: localtime.h:48
time type information
Definition: localtime.c:132
int tm_year
Definition: localtime.h:41
long int tm_gmtoff
Definition: localtime.h:45
int tm_isdst
Definition: localtime.h:44
static struct timeval time2 ( struct ast_tm tmp,
struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *sp)  funcp,
const long  offset,
int *  okayp,
const struct state sp 
)
static
Note
First try without normalization of seconds (in case tm_sec contains a value associated with a leap second). If that fails, try with normalization of seconds.

Definition at line 2279 of file localtime.c.

2280 {
2281  struct timeval t;
2282 
2283  /*! \note
2284  ** First try without normalization of seconds
2285  ** (in case tm_sec contains a value associated with a leap second).
2286  ** If that fails, try with normalization of seconds.
2287  */
2288  t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
2289  return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
2290 }
static int tzparse ( const char *  name,
struct state sp,
const int  lastditch 
)
static
Note
Given a POSIX section 8-style TZ string, fill in the rule tables as appropriate.

Definition at line 1385 of file localtime.c.

References getoffset(), getqzname(), getrule(), getzname(), state::name, transtime(), and TZDEFRULESTRING.

1386 {
1387  const char * stdname;
1388  const char * dstname;
1389  size_t stdlen;
1390  size_t dstlen;
1391  long stdoffset;
1392  long dstoffset;
1393  time_t * atp;
1394  unsigned char * typep;
1395  char * cp;
1396  int load_result;
1397 
1398  INITIALIZE(dstname);
1399  stdname = name;
1400  if (lastditch) {
1401  stdlen = strlen(name); /* length of standard zone name */
1402  name += stdlen;
1403  if (stdlen >= sizeof sp->chars)
1404  stdlen = (sizeof sp->chars) - 1;
1405  stdoffset = 0;
1406  } else {
1407  if (*name == '<') {
1408  name++;
1409  stdname = name;
1410  name = getqzname(name, '>');
1411  if (*name != '>')
1412  return -1;
1413  stdlen = name - stdname;
1414  name++;
1415  } else {
1416  name = getzname(name);
1417  stdlen = name - stdname;
1418  }
1419  if (*name == '\0')
1420  return -1;
1421  name = getoffset(name, &stdoffset);
1422  if (name == NULL)
1423  return -1;
1424  }
1425  load_result = tzload(TZDEFRULES, sp, FALSE);
1426  if (load_result != 0)
1427  sp->leapcnt = 0; /* so, we're off a little */
1428  if (*name != '\0') {
1429  if (*name == '<') {
1430  dstname = ++name;
1431  name = getqzname(name, '>');
1432  if (*name != '>')
1433  return -1;
1434  dstlen = name - dstname;
1435  name++;
1436  } else {
1437  dstname = name;
1438  name = getzname(name);
1439  dstlen = name - dstname; /* length of DST zone name */
1440  }
1441  if (*name != '\0' && *name != ',' && *name != ';') {
1442  name = getoffset(name, &dstoffset);
1443  if (name == NULL)
1444  return -1;
1445  } else dstoffset = stdoffset - SECSPERHOUR;
1446  if (*name == '\0' && load_result != 0)
1447  name = TZDEFRULESTRING;
1448  if (*name == ',' || *name == ';') {
1449  struct rule start;
1450  struct rule end;
1451  int year;
1452  time_t janfirst;
1453  time_t starttime;
1454  time_t endtime;
1455 
1456  ++name;
1457  if ((name = getrule(name, &start)) == NULL)
1458  return -1;
1459  if (*name++ != ',')
1460  return -1;
1461  if ((name = getrule(name, &end)) == NULL)
1462  return -1;
1463  if (*name != '\0')
1464  return -1;
1465  sp->typecnt = 2; /* standard time and DST */
1466  /*
1467  ** Two transitions per year, from EPOCH_YEAR forward.
1468  */
1469  sp->ttis[0].tt_gmtoff = -dstoffset;
1470  sp->ttis[0].tt_isdst = 1;
1471  sp->ttis[0].tt_abbrind = stdlen + 1;
1472  sp->ttis[1].tt_gmtoff = -stdoffset;
1473  sp->ttis[1].tt_isdst = 0;
1474  sp->ttis[1].tt_abbrind = 0;
1475  atp = sp->ats;
1476  typep = sp->types;
1477  janfirst = 0;
1478  sp->timecnt = 0;
1479  for (year = EPOCH_YEAR;
1480  sp->timecnt + 2 <= TZ_MAX_TIMES;
1481  ++year) {
1482  time_t newfirst;
1483 
1484  starttime = transtime(janfirst, year, &start,
1485  stdoffset);
1486  endtime = transtime(janfirst, year, &end,
1487  dstoffset);
1488  if (starttime > endtime) {
1489  *atp++ = endtime;
1490  *typep++ = 1; /* DST ends */
1491  *atp++ = starttime;
1492  *typep++ = 0; /* DST begins */
1493  } else {
1494  *atp++ = starttime;
1495  *typep++ = 0; /* DST begins */
1496  *atp++ = endtime;
1497  *typep++ = 1; /* DST ends */
1498  }
1499  sp->timecnt += 2;
1500  newfirst = janfirst;
1501  newfirst += year_lengths[isleap(year)] *
1502  SECSPERDAY;
1503  if (newfirst <= janfirst)
1504  break;
1505  janfirst = newfirst;
1506  }
1507  } else {
1508  long theirstdoffset;
1509  long theiroffset;
1510  int i;
1511  int j;
1512 
1513  if (*name != '\0')
1514  return -1;
1515  /*
1516  ** Initial values of theirstdoffset.
1517  */
1518  theirstdoffset = 0;
1519  for (i = 0; i < sp->timecnt; ++i) {
1520  j = sp->types[i];
1521  if (!sp->ttis[j].tt_isdst) {
1522  theirstdoffset =
1523  -sp->ttis[j].tt_gmtoff;
1524  break;
1525  }
1526  }
1527  theiroffset = theirstdoffset;
1528  /*
1529  ** Now juggle transition times and types
1530  ** tracking offsets as you do.
1531  */
1532  for (i = 0; i < sp->timecnt; ++i) {
1533  j = sp->types[i];
1534  sp->types[i] = sp->ttis[j].tt_isdst;
1535  if (sp->ttis[j].tt_ttisgmt) {
1536  /* No adjustment to transition time */
1537  } else {
1538  /* Add the standard time offset to the transition time. */
1539  sp->ats[i] += stdoffset - theirstdoffset;
1540  }
1541  theiroffset = -sp->ttis[j].tt_gmtoff;
1542  if (!sp->ttis[j].tt_isdst) {
1543  theirstdoffset = theiroffset;
1544  }
1545  }
1546  /*
1547  ** Finally, fill in ttis.
1548  ** ttisstd and ttisgmt need not be handled.
1549  */
1550  sp->ttis[0].tt_gmtoff = -stdoffset;
1551  sp->ttis[0].tt_isdst = FALSE;
1552  sp->ttis[0].tt_abbrind = 0;
1553  sp->ttis[1].tt_gmtoff = -dstoffset;
1554  sp->ttis[1].tt_isdst = TRUE;
1555  sp->ttis[1].tt_abbrind = stdlen + 1;
1556  sp->typecnt = 2;
1557  }
1558  } else {
1559  dstlen = 0;
1560  sp->typecnt = 1; /* only standard time */
1561  sp->timecnt = 0;
1562  sp->ttis[0].tt_gmtoff = -stdoffset;
1563  sp->ttis[0].tt_isdst = 0;
1564  sp->ttis[0].tt_abbrind = 0;
1565  }
1566  sp->charcnt = stdlen + 1;
1567  if (dstlen != 0)
1568  sp->charcnt += dstlen + 1;
1569  if ((size_t) sp->charcnt > sizeof sp->chars)
1570  return -1;
1571  cp = sp->chars;
1572  (void) strncpy(cp, stdname, stdlen);
1573  cp += stdlen;
1574  *cp++ = '\0';
1575  if (dstlen != 0) {
1576  (void) strncpy(cp, dstname, dstlen);
1577  *(cp + dstlen) = '\0';
1578  }
1579  return 0;
1580 }
static const char * getoffset(const char *strp, long *offsetp)
Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the time.
Definition: localtime.c:1220
static const char * getqzname(const char *strp, const int delim)
Given a pointer into an extended time zone string, scan until the ending delimiter of the zone name i...
Definition: localtime.c:1137
static const char * getrule(const char *strp, struct rule *rulep)
Given a pointer into a time zone string, extract a rule in the form date[/time]. See POSIX section 8 ...
Definition: localtime.c:1244
#define TZDEFRULESTRING
Definition: localtime.c:128
static const char * getzname(const char *strp)
Given a pointer into a time zone string, scan until a character that is not a valid character in a zo...
Definition: localtime.c:1118
static time_t transtime(const time_t janfirst, const int year, const struct rule *rulep, const long offset)
Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect.
Definition: localtime.c:1295

Variable Documentation

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

Definition at line 1103 of file localtime.c.

const int year_lengths[2]
static
Initial value:
= {
DAYSPERNYEAR, DAYSPERLYEAR
}

Definition at line 1108 of file localtime.c.