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

Go to the source code of this file.

Data Structures

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

Macros

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

Functions

static void add_notify (struct state *sp, const char *path)
 
void ast_get_dst_info (const time_t *const timep, int *dst_enabled, time_t *dst_start, time_t *dst_end, int *gmt_off, const char *const zone)
 
struct ast_tmast_localtime (const struct timeval *timep, struct ast_tm *tmp, const char *zone)
 Timezone-independent version of localtime_r(3). More...
 
void ast_localtime_wakeup_monitor (struct ast_test *info)
 
struct timeval ast_mktime (struct ast_tm *tmp, const char *zone)
 Timezone-independent version of mktime(3). More...
 
const char * ast_setlocale (const char *locale)
 Set the thread-local representation of the current locale. More...
 
int ast_strftime (char *buf, size_t len, const char *tmp, const struct ast_tm *tm)
 Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strftime(3), with the addition of q, which specifies microseconds. More...
 
int ast_strftime_locale (char *buf, size_t len, const char *tmp, const struct ast_tm *tm, const char *locale)
 
char * ast_strptime (const char *s, const char *format, struct ast_tm *tm)
 Special version of strptime(3) which places the answer in the common structure ast_tm. Also, unlike strptime(3), ast_strptime() initializes its memory prior to use. More...
 
char * ast_strptime_locale (const char *s, const char *format, struct ast_tm *tm, const char *locale)
 
static const struct stateast_tzset (const char *zone)
 
void clean_time_zones (void)
 
static void common_startup (void)
 
static long detzcode (const char *const codep)
 
static time_t detzcode64 (const char *const codep)
 
static int differ_by_repeat (const time_t t1, const time_t t0)
 
static struct locale_entryfind_by_locale (locale_t locale)
 
static struct locale_entryfind_by_name (const char *name)
 
static const char * getnum (const char *strp, int *nump, const int min, const int max)
 Given a pointer into a time zone string, extract a number from that string. Check that the number is within a specified range; if it is not, return NULL. Otherwise, return a pointer to the first character not part of the number. More...
 
static const char * getoffset (const char *strp, long *offsetp)
 Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the time. More...
 
static const char * getqzname (const char *strp, const int delim)
 Given a pointer into an extended time zone string, scan until the ending delimiter of the zone name is located. Return a pointer to the delimiter. More...
 
static const char * getrule (const char *strp, struct rule *rulep)
 Given a pointer into a time zone string, extract a rule in the form date[/time]. See POSIX section 8 for the format of "date" and "time". If a valid rule is not found, return NULL. Otherwise, return a pointer to the first character not part of the rule. More...
 
static const char * getsecs (const char *strp, long *const secsp)
 Given a pointer into a time zone string, extract a number of seconds, in hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the number of seconds. More...
 
static const char * getzname (const char *strp)
 Given a pointer into a time zone string, scan until a character that is not a valid character in a zone name is found. Return a pointer to that character. More...
 
static int gmtload (struct state *sp)
 
static struct ast_tmgmtsub (const struct timeval *timep, const long offset, struct ast_tm *tmp)
 
static int increment_overflow (int *number, int delta)
 Simplified normalize logic courtesy Paul Eggert. More...
 
static void * inotify_daemon (void *data)
 
static int leaps_thru_end_of (const int y)
 Return the number of leap years through the end of the given year where, to make the math easy, the answer for year zero is defined as zero. More...
 
static struct ast_tmlocalsub (const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
 
static int long_increment_overflow (long *number, int delta)
 
static int long_normalize_overflow (long *tensptr, int *unitsptr, const int base)
 
static int normalize_overflow (int *tensptr, int *unitsptr, const int base)
 
static long detzcode P ((const char *codep))
 
static int 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 *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 *getoffset P ((const char *strp, long *offsetp))
 
static const char *getsecs P ((const char *strp, long *secsp))
 
static const char *getrule P ((const char *strp, struct rule *rulep))
 
static int tmcomp P ((const struct ast_tm *atmp, const struct ast_tm *btmp))
 
static struct ast_tm *timesub P ((const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp))
 
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 normalize_overflow P ((int *tensptr, int *unitsptr, const int base))
 
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 gmtload P ((struct state *sp))
 
static time_t transtime P ((time_t janfirst, int year, const struct rule *rulep, long offset))
 
static int differ_by_repeat P ((time_t t1, time_t t0))
 
static struct statesstate_alloc (void)
 
static void sstate_free (struct state *p)
 
static const char * store_by_locale (locale_t prevlocale)
 
static struct timeval time1 (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, const struct state *sp)
 
static struct timeval time2 (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), const long offset, int *okayp, const struct state *sp)
 
static struct timeval time2sub (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, int *okayp, const int do_norm_secs, const struct state *sp)
 
static struct ast_tmtimesub (const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
 
static int tmcomp (const struct ast_tm *atmp, const struct ast_tm *btmp)
 
static time_t transtime (const time_t janfirst, const int year, const struct rule *rulep, const long offset)
 Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect. More...
 
static int tzload (const char *name, struct state *const sp, const int doextend)
 
static int tzparse (const char *name, struct state *sp, const int lastditch)
 

Variables

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

Detailed Description

Multi-timezone Localtime code

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

Definition in file localtime.c.

Macro Definition Documentation

◆ BIGGEST

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

Definition at line 146 of file localtime.c.

◆ DAY_OF_YEAR

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

Definition at line 257 of file localtime.c.

◆ JULIAN_DAY

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

Definition at line 256 of file localtime.c.

◆ MONTH_NTH_DAY_OF_WEEK

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

Definition at line 258 of file localtime.c.

◆ MY_TZNAME_MAX

#define MY_TZNAME_MAX   255

Definition at line 152 of file localtime.c.

◆ OPEN_MODE

#define OPEN_MODE   O_RDONLY

Definition at line 107 of file localtime.c.

◆ SP_HEAP_FREE

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

Definition at line 199 of file localtime.c.

◆ SP_HEAP_INIT

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

Definition at line 195 of file localtime.c.

◆ SP_STACK_CHECK

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

Definition at line 194 of file localtime.c.

◆ SP_STACK_FLAG

#define SP_STACK_FLAG   INT_MIN

Definition at line 189 of file localtime.c.

◆ SP_STACK_INIT

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

Definition at line 191 of file localtime.c.

◆ TZ_ABBR_CHAR_SET

#define TZ_ABBR_CHAR_SET    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"

Definition at line 91 of file localtime.c.

◆ TZ_ABBR_ERR_CHAR

#define TZ_ABBR_ERR_CHAR   '_'

Definition at line 96 of file localtime.c.

◆ TZ_ABBR_MAX_LEN

#define TZ_ABBR_MAX_LEN   16

Definition at line 87 of file localtime.c.

◆ TZ_STRLEN_MAX

#define TZ_STRLEN_MAX   255

Definition at line 155 of file localtime.c.

◆ TZDEFRULESTRING

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

Definition at line 128 of file localtime.c.

Function Documentation

◆ add_notify()

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

Definition at line 411 of file localtime.c.

412{
413 /* watch for flag indicating stack automatic sp,
414 * should not be added to watch
415 */
416 if (SP_STACK_CHECK(sp)) {
417 return;
418 }
419
425 /* Give the thread a chance to initialize */
427 } else {
428 fprintf(stderr, "Unable to start notification thread\n");
430 return;
431 }
433 }
434
435 if (inotify_fd > -1) {
436 char fullpath[FILENAME_MAX + 1] = "";
437 if (readlink(path, fullpath, sizeof(fullpath) - 1) != -1) {
438 /* If file the symlink points to changes */
439 sp->wd[1] = inotify_add_watch(inotify_fd, fullpath, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE );
440 } else {
441 sp->wd[1] = -1;
442 }
443 /* or if the symlink itself changes (or the real file is here, if path is not a symlink) */
444 sp->wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE
445#ifdef IN_DONT_FOLLOW /* Only defined in glibc 2.5 and above */
446 | IN_DONT_FOLLOW
447#endif
448 );
449 }
450}
static ast_cond_t initialization
Definition: localtime.c:322
static void * inotify_daemon(void *data)
Definition: localtime.c:353
#define SP_STACK_CHECK(sp)
Definition: localtime.c:194
static ast_mutex_t initialization_lock
Definition: localtime.c:323
static pthread_t inotify_thread
Definition: localtime.c:321
static int inotify_fd
Definition: localtime.c:351
#define ast_cond_wait(cond, mutex)
Definition: lock.h:205
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_cond_init(cond, attr)
Definition: lock.h:201
#define ast_mutex_init(pmutex)
Definition: lock.h:186
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
#define FILENAME_MAX
#define NULL
Definition: resample.c:96
int wd[2]
Definition: localtime.c:174
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592

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, initialization, initialization_lock, inotify_daemon(), inotify_fd, inotify_thread, NULL, SP_STACK_CHECK, and state::wd.

Referenced by common_startup(), and tzload().

◆ ast_get_dst_info()

void ast_get_dst_info ( const time_t *const  timep,
int *  dst_enabled,
time_t *  dst_start,
time_t *  dst_end,
int *  gmt_off,
const char *const  zone 
)

Definition at line 1754 of file localtime.c.

1755{
1756 int i;
1757 int transition1 = -1;
1758 int transition2 = -1;
1759 time_t seconds;
1760 int bounds_exceeded = 0;
1761 time_t t = *timep;
1762 const struct state *sp;
1763
1764 if (NULL == dst_enabled)
1765 return;
1766 *dst_enabled = 0;
1767
1768 if (NULL == dst_start || NULL == dst_end || NULL == gmt_off)
1769 return;
1770
1771 *gmt_off = 0;
1772
1773 sp = ast_tzset(zone);
1774 if (NULL == sp)
1775 return;
1776
1777 /* If the desired time exceeds the bounds of the defined time transitions
1778 * then give up on determining DST info and simply look for gmt offset
1779 * This requires that I adjust the given time using increments of Gregorian
1780 * repeats to place the time within the defined time transitions in the
1781 * timezone structure.
1782 */
1783 if ((sp->goback && t < sp->ats[0]) ||
1784 (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1785 time_t tcycles;
1786 int_fast64_t icycles;
1787
1788 if (t < sp->ats[0])
1789 seconds = sp->ats[0] - t;
1790 else seconds = t - sp->ats[sp->timecnt - 1];
1791 --seconds;
1792 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1793 ++tcycles;
1794 icycles = tcycles;
1795 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1796 return;
1797 seconds = icycles;
1798 seconds *= YEARSPERREPEAT;
1799 seconds *= AVGSECSPERYEAR;
1800 if (t < sp->ats[0])
1801 t += seconds;
1802 else
1803 t -= seconds;
1804
1805 if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1])
1806 return; /* "cannot happen" */
1807
1808 bounds_exceeded = 1;
1809 }
1810
1811 if (sp->timecnt == 0 || t < sp->ats[0]) {
1812 /* I have no transition times or I'm before time */
1813 *dst_enabled = 0;
1814 /* Find where I can get gmtoff */
1815 i = 0;
1816 while (sp->ttis[i].tt_isdst) {
1817 if (++i >= sp->typecnt) {
1818 i = 0;
1819 break;
1820 }
1821 }
1822 *gmt_off = sp->ttis[i].tt_gmtoff;
1823 return;
1824 }
1825
1826 for (i = 1; i < sp->timecnt; ++i) {
1827 if (t < sp->ats[i]) {
1828 transition1 = sp->types[i - 1];
1829 transition2 = sp->types[i];
1830 break;
1831 }
1832 }
1833 /* if I found transition times that do not bounded the given time and these correspond to
1834 or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */
1835 if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 ||
1836 (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) {
1837 *dst_enabled = 0;
1838 *gmt_off = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff;
1839 } else {
1840 /* I have valid daylight savings information. */
1841 if(sp->ttis[transition2].tt_isdst)
1842 *gmt_off = sp->ttis[transition1].tt_gmtoff;
1843 else
1844 *gmt_off = sp->ttis[transition2].tt_gmtoff;
1845
1846 /* If I adjusted the time earlier, indicate that the dst is invalid */
1847 if (!bounds_exceeded) {
1848 *dst_enabled = 1;
1849 /* Determine which of the bounds is the start of daylight savings and which is the end */
1850 if(sp->ttis[transition2].tt_isdst) {
1851 *dst_start = sp->ats[i];
1852 *dst_end = sp->ats[i -1];
1853 } else {
1854 *dst_start = sp->ats[i -1];
1855 *dst_end = sp->ats[i];
1856 }
1857 }
1858 }
1859 return;
1860}
static const struct state * ast_tzset(const char *zone)
Definition: localtime.c:1601
#define AVGSECSPERYEAR
you may need to compile with DHAVE_STDINT_H typedef long int_fast64_t
#define YEARSPERREPEAT
int typecnt
Definition: localtime.c:163
int goback
Definition: localtime.c:165
time_t ats[TZ_MAX_TIMES]
Definition: localtime.c:167
int timecnt
Definition: localtime.c:162
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: localtime.c:169
unsigned char types[TZ_MAX_TIMES]
Definition: localtime.c:168
int goahead
Definition: localtime.c:166
int tt_isdst
Definition: localtime.c:134
long tt_gmtoff
Definition: localtime.c:133

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

Referenced by set_timezone_variables().

◆ ast_localtime()

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

Timezone-independent version of localtime_r(3).

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

Definition at line 1739 of file localtime.c.

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 int tmp()
Definition: bt_open.c:389
static struct ast_tm * localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
Definition: localtime.c:1648

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

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

◆ ast_localtime_wakeup_monitor()

void ast_localtime_wakeup_monitor ( struct ast_test *  info)

Definition at line 795 of file localtime.c.

796{
797 struct timeval wait_now = ast_tvnow();
798 struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 2, .tv_nsec = wait_now.tv_usec * 1000 };
799
802#ifdef TEST_FRAMEWORK
803 test = info;
804#endif
805 pthread_kill(inotify_thread, SIGURG);
807#ifdef TEST_FRAMEWORK
808 test = NULL;
809#endif
811 }
812}
ast_mutex_t lock
Definition: app_sla.c:331
#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_cond_timedwait(cond, mutex, time)
Definition: lock.h:206
def info(msg)
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

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

Referenced by AST_TEST_DEFINE().

◆ ast_mktime()

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

Timezone-independent version of mktime(3).

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

Definition at line 2357 of file localtime.c.

2358{
2359 const struct state *sp;
2360 if (!(sp = ast_tzset(zone)))
2361 return WRONG;
2362 return time1(tmp, localsub, 0L, sp);
2363}
static const struct timeval WRONG
Definition: localtime.c:111
static struct timeval time1(struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, const struct state *sp)
Definition: localtime.c:2292

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

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

◆ ast_setlocale()

const char * ast_setlocale ( const char *  locale)

Set the thread-local representation of the current locale.

Definition at line 2420 of file localtime.c.

2421{
2422 struct locale_entry *cur;
2423 locale_t prevlocale = LC_GLOBAL_LOCALE;
2424
2425 if (locale == NULL) {
2426 return store_by_locale(uselocale(LC_GLOBAL_LOCALE));
2427 }
2428
2430 if ((cur = find_by_name(locale))) {
2431 prevlocale = uselocale(cur->locale);
2432 }
2433
2434 if (!cur) {
2435 if ((cur = ast_calloc(1, sizeof(*cur) + strlen(locale) + 1))) {
2436 cur->locale = newlocale(LC_ALL_MASK, locale, NULL);
2437 strcpy(cur->name, locale); /* SAFE */
2439 prevlocale = uselocale(cur->locale);
2440 }
2441 }
2443 return store_by_locale(prevlocale);
2444}
static char locale[20]
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
static struct locale_entry * find_by_name(const char *name)
Definition: localtime.c:2377
static const char * store_by_locale(locale_t prevlocale)
Definition: localtime.c:2388
void * locale_t
Definition: localtime.h:32
Definition: localtime.c:242
locale_t locale
Definition: localtime.c:244
struct locale_entry::@401 list
char name[0]
Definition: localtime.c:245

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

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

◆ ast_strftime()

int ast_strftime ( char *  buf,
size_t  len,
const char *  format,
const struct ast_tm tm 
)

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

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

Definition at line 2524 of file localtime.c.

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

References ast_strftime_locale(), buf, len(), NULL, and tmp().

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

◆ ast_strftime_locale()

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

Definition at line 2452 of file localtime.c.

2453{
2454 size_t fmtlen = strlen(tmp) + 1;
2455 char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt;
2456 int decimals = -1, i, res;
2457 long fraction;
2458 const char *prevlocale;
2459
2460 buf[0] = '\0';/* Ensure the buffer is initialized. */
2461 if (!format) {
2462 return -1;
2463 }
2464 for (; *tmp; tmp++) {
2465 if (*tmp == '%') {
2466 switch (tmp[1]) {
2467 case '1':
2468 case '2':
2469 case '3':
2470 case '4':
2471 case '5':
2472 case '6':
2473 if (tmp[2] != 'q') {
2474 goto defcase;
2475 }
2476 decimals = tmp[1] - '0';
2477 tmp++;
2478 /* Fall through */
2479 case 'q': /* Milliseconds */
2480 if (decimals == -1) {
2481 decimals = 3;
2482 }
2483
2484 /* Juggle some memory to fit the item */
2485 newfmt = ast_realloc(format, fmtlen + decimals);
2486 if (!newfmt) {
2487 ast_free(format);
2488 return -1;
2489 }
2490 fptr = fptr - format + newfmt;
2491 format = newfmt;
2492 fmtlen += decimals;
2493
2494 /* Reduce the fraction of time to the accuracy needed */
2495 for (i = 6, fraction = tm->tm_usec; i > decimals; i--) {
2496 fraction /= 10;
2497 }
2498 fptr += sprintf(fptr, "%0*ld", decimals, fraction);
2499
2500 /* Reset, in case more than one 'q' specifier exists */
2501 decimals = -1;
2502 tmp++;
2503 break;
2504 default:
2505 goto defcase;
2506 }
2507 } else {
2508defcase: *fptr++ = *tmp;
2509 }
2510 }
2511 *fptr = '\0';
2512#undef strftime
2513 if (locale) {
2514 prevlocale = ast_setlocale(locale);
2515 }
2516 res = (int)strftime(buf, len, format, (struct tm *)tm);
2517 if (locale) {
2518 ast_setlocale(prevlocale);
2519 }
2520 ast_free(format);
2521 return res;
2522}
#define ast_free(a)
Definition: astmm.h:180
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:226
const char * ast_setlocale(const char *locale)
Set the thread-local representation of the current locale.
Definition: localtime.c:2420
int tm_usec
Definition: localtime.h:48

References ast_calloc, ast_free, ast_realloc, ast_setlocale(), buf, len(), locale, ast_tm::tm_usec, and tmp().

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

◆ ast_strptime()

char * ast_strptime ( const char *  s,
const char *  format,
struct ast_tm tm 
)

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

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

Definition at line 2550 of file localtime.c.

2551{
2552 return ast_strptime_locale(s, format, tm, NULL);
2553}
char * ast_strptime_locale(const char *s, const char *format, struct ast_tm *tm, const char *locale)
Definition: localtime.c:2529

References ast_strptime_locale(), and NULL.

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

◆ ast_strptime_locale()

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

Definition at line 2529 of file localtime.c.

2530{
2531 struct tm tm2 = { 0, };
2532 char *res;
2533 const char *prevlocale;
2534
2535 prevlocale = ast_setlocale(locale);
2536 res = strptime(s, format, &tm2);
2537 ast_setlocale(prevlocale);
2538 /* ast_time and tm are not the same size - tm is a subset of
2539 * ast_time. Hence, the size of tm needs to be used for the
2540 * memcpy
2541 */
2542 memcpy(tm, &tm2, sizeof(tm2));
2543 tm->tm_usec = 0;
2544 /* strptime(3) doesn't set .tm_isdst correctly, so to force ast_mktime(3)
2545 * to deal with it correctly, we set it to -1. */
2546 tm->tm_isdst = -1;
2547 return res;
2548}
int tm_isdst
Definition: localtime.h:44

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

Referenced by ast_strptime().

◆ ast_tzset()

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

Definition at line 1601 of file localtime.c.

1602{
1603 struct state *sp;
1604
1605 if (ast_strlen_zero(zone)) {
1606#ifdef SOLARIS
1607 zone = getenv("TZ");
1608 if (ast_strlen_zero(zone)) {
1609 zone = "GMT";
1610 }
1611#else
1612 zone = "/etc/localtime";
1613#endif
1614 }
1615
1618 if (!strcmp(sp->name, zone)) {
1620 return sp;
1621 }
1622 }
1623
1624 if (!(sp = sstate_alloc())) {
1626 return NULL;
1627 }
1628
1629 if (tzload(zone, sp, TRUE) != 0) {
1630 if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0)
1631 (void) gmtload(sp);
1632 }
1633 ast_copy_string(sp->name, zone, sizeof(sp->name));
1636 return sp;
1637}
#define TRUE
Definition: app_minivm.c:524
#define FALSE
Definition: app_minivm.c:527
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
static int tzload(const char *name, struct state *const sp, const int doextend)
Definition: localtime.c:853
static struct state * sstate_alloc(void)
Definition: localtime.c:778
static int tzparse(const char *name, struct state *sp, const int lastditch)
Definition: localtime.c:1385
static int gmtload(struct state *sp)
Definition: localtime.c:1582
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char name[TZ_STRLEN_MAX+1]
Definition: localtime.c:160
struct state::@400 list

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

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

◆ clean_time_zones()

void clean_time_zones ( void  )

Provided by localtime.c

Definition at line 1590 of file localtime.c.

1591{
1592 struct state *sp;
1593
1595 while ((sp = AST_LIST_REMOVE_HEAD(&zonelist, list))) {
1596 sstate_free(sp);
1597 }
1599}
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
static void sstate_free(struct state *p)
Definition: localtime.c:789

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

Referenced by really_quit().

◆ common_startup()

static void common_startup ( void  )
static

Start a notification for every entry already in the list.

Definition at line 328 of file localtime.c.

328 {
329 struct state *sp;
332 /* ensure sp->name is not relative -- it
333 * often is -- otherwise add_notify() fails
334 */
335 char name[FILENAME_MAX + 1];
336
337 if (sp->name[0] == '/') {
338 snprintf(name, sizeof(name), "%s", sp->name);
339 } else if (!strcmp(sp->name, TZDEFAULT)) {
340 snprintf(name, sizeof(name), "/etc/%s", sp->name);
341 } else {
342 snprintf(name, sizeof(name), "%s/%s", TZDIR, sp->name);
343 }
344
345 add_notify(sp, name);
346 }
348}
static const char name[]
Definition: format_mp3.c:68
static void add_notify(struct state *sp, const char *path)
Definition: localtime.c:411
#define TZDIR
Definition: tzfile.h:36
#define TZDEFAULT
Definition: tzfile.h:41

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

Referenced by inotify_daemon().

◆ detzcode()

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

Definition at line 822 of file localtime.c.

823{
824 long result;
825 int i;
826
827 result = (codep[0] & 0x80) ? ~0L : 0;
828 for (i = 0; i < 4; ++i)
829 result = (result << 8) | (codep[i] & 0xff);
830 return result;
831}
static PGresult * result
Definition: cel_pgsql.c:84

References result.

Referenced by tzload().

◆ detzcode64()

static time_t detzcode64 ( const char *const  codep)
static

Definition at line 833 of file localtime.c.

834{
835 time_t result;
836 int i;
837
838 result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
839 for (i = 0; i < 8; ++i)
840 result = result * 256 + (codep[i] & 0xff);
841 return result;
842}

References int_fast64_t, and result.

Referenced by tzload().

◆ differ_by_repeat()

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

Definition at line 844 of file localtime.c.

845{
846 const long long at1 = t1, at0 = t0;
847 if (TYPE_INTEGRAL(time_t) &&
848 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
849 return 0;
850 return at1 - at0 == SECSPERREPEAT;
851}
#define SECSPERREPEAT
#define TYPE_INTEGRAL(type)
#define SECSPERREPEAT_BITS
#define TYPE_BIT(type)
#define TYPE_SIGNED(type)

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

Referenced by tzload().

◆ find_by_locale()

static struct locale_entry * find_by_locale ( locale_t  locale)
static

Definition at line 2366 of file localtime.c.

2367{
2368 struct locale_entry *cur;
2370 if (locale == cur->locale) {
2371 return cur;
2372 }
2373 }
2374 return NULL;
2375}

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

Referenced by store_by_locale().

◆ find_by_name()

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

Definition at line 2377 of file localtime.c.

2378{
2379 struct locale_entry *cur;
2381 if (strcmp(name, cur->name) == 0) {
2382 return cur;
2383 }
2384 }
2385 return NULL;
2386}

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

Referenced by ast_setlocale(), and store_by_locale().

◆ getnum()

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

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

Definition at line 1153 of file localtime.c.

1154{
1155 char c;
1156 int num;
1157
1158 if (strp == NULL || !is_digit(c = *strp))
1159 return NULL;
1160 num = 0;
1161 do {
1162 num = num * 10 + (c - '0');
1163 if (num > max)
1164 return NULL; /* illegal value */
1165 c = *++strp;
1166 } while (is_digit(c));
1167 if (num < min)
1168 return NULL; /* illegal value */
1169 *nump = num;
1170 return strp;
1171}
#define min(a, b)
Definition: f2c.h:197
#define max(a, b)
Definition: f2c.h:198
#define is_digit(c)
static struct test_val c

References c, is_digit, max, min, and NULL.

Referenced by getrule(), and getsecs().

◆ getoffset()

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

Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the time.

Definition at line 1220 of file localtime.c.

1221{
1222 int neg = 0;
1223
1224 if (*strp == '-') {
1225 neg = 1;
1226 ++strp;
1227 } else if (*strp == '+')
1228 ++strp;
1229 strp = getsecs(strp, offsetp);
1230 if (strp == NULL)
1231 return NULL; /* illegal time */
1232 if (neg)
1233 *offsetp = -*offsetp;
1234 return strp;
1235}
static const char * getsecs(const char *strp, long *const secsp)
Given a pointer into a time zone string, extract a number of seconds, in hh[:mm[:ss]] form,...
Definition: localtime.c:1181

References getsecs(), and NULL.

Referenced by tzparse().

◆ getqzname()

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

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

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

Definition at line 1137 of file localtime.c.

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

References c.

Referenced by tzparse().

◆ getrule()

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

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

Definition at line 1244 of file localtime.c.

1245{
1246 if (*strp == 'J') {
1247 /*
1248 ** Julian day.
1249 */
1250 rulep->r_type = JULIAN_DAY;
1251 ++strp;
1252 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
1253 } else if (*strp == 'M') {
1254 /*
1255 ** Month, week, day.
1256 */
1258 ++strp;
1259 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
1260 if (strp == NULL)
1261 return NULL;
1262 if (*strp++ != '.')
1263 return NULL;
1264 strp = getnum(strp, &rulep->r_week, 1, 5);
1265 if (strp == NULL)
1266 return NULL;
1267 if (*strp++ != '.')
1268 return NULL;
1269 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
1270 } else if (is_digit(*strp)) {
1271 /*
1272 ** Day of year.
1273 */
1274 rulep->r_type = DAY_OF_YEAR;
1275 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
1276 } else return NULL; /* invalid format */
1277 if (strp == NULL)
1278 return NULL;
1279 if (*strp == '/') {
1280 /*
1281 ** Time specified.
1282 */
1283 ++strp;
1284 strp = getsecs(strp, &rulep->r_time);
1285 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
1286 return strp;
1287}
static const char * getnum(const char *strp, int *nump, const int min, const int max)
Given a pointer into a time zone string, extract a number from that string. Check that the number is ...
Definition: localtime.c:1153
#define DAY_OF_YEAR
Definition: localtime.c:257
#define JULIAN_DAY
Definition: localtime.c:256
#define MONTH_NTH_DAY_OF_WEEK
Definition: localtime.c:258
int r_mon
Definition: localtime.c:252
long r_time
Definition: localtime.c:253
int r_day
Definition: localtime.c:250
int r_week
Definition: localtime.c:251
int r_type
Definition: localtime.c:249
#define SECSPERHOUR
Definition: tzfile.h:138
#define DAYSPERNYEAR
Definition: tzfile.h:136
#define MONSPERYEAR
Definition: tzfile.h:140
#define DAYSPERWEEK
Definition: tzfile.h:135
#define DAYSPERLYEAR
Definition: tzfile.h:137

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

Referenced by tzparse().

◆ getsecs()

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

Given a pointer into a time zone string, extract a number of seconds, in hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the number of seconds.

Definition at line 1181 of file localtime.c.

1182{
1183 int num;
1184
1185 /*
1186 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
1187 ** "M10.4.6/26", which does not conform to Posix,
1188 ** but which specifies the equivalent of
1189 ** ``02:00 on the first Sunday on or after 23 Oct''.
1190 */
1191 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
1192 if (strp == NULL)
1193 return NULL;
1194 *secsp = num * (long) SECSPERHOUR;
1195 if (*strp == ':') {
1196 ++strp;
1197 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
1198 if (strp == NULL)
1199 return NULL;
1200 *secsp += num * SECSPERMIN;
1201 if (*strp == ':') {
1202 ++strp;
1203 /* `SECSPERMIN' allows for leap seconds. */
1204 strp = getnum(strp, &num, 0, SECSPERMIN);
1205 if (strp == NULL)
1206 return NULL;
1207 *secsp += num;
1208 }
1209 }
1210 return strp;
1211}
#define SECSPERMIN
Definition: tzfile.h:132
#define HOURSPERDAY
Definition: tzfile.h:134
#define MINSPERHOUR
Definition: tzfile.h:133

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

Referenced by getoffset(), and getrule().

◆ getzname()

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

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

Definition at line 1118 of file localtime.c.

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

References c, and is_digit.

Referenced by tzparse().

◆ gmtload()

static int gmtload ( struct state sp)
static

Definition at line 1582 of file localtime.c.

1583{
1584 if (tzload(gmt, sp, TRUE) != 0)
1585 return tzparse(gmt, sp, TRUE);
1586 else
1587 return -1;
1588}
static const char gmt[]
Definition: localtime.c:110

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

Referenced by ast_tzset(), and gmtsub().

◆ gmtsub()

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

Definition at line 1866 of file localtime.c.

1867{
1868 struct ast_tm * result;
1869 struct state *sp;
1870
1873 if (!strcmp(sp->name, "UTC"))
1874 break;
1875 }
1876
1877 if (!sp) {
1878 if (!(sp = sstate_alloc())) {
1880 return NULL;
1881 }
1882 gmtload(sp);
1884 }
1886
1887 result = timesub(timep, offset, sp, tmp);
1888#ifdef TM_ZONE
1889 /*
1890 ** Could get fancy here and deliver something such as
1891 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1892 ** but this is no time for a treasure hunt.
1893 */
1894 if (offset != 0)
1895 tmp->TM_ZONE = " ";
1896 else
1897 tmp->TM_ZONE = sp->chars;
1898#endif /* defined TM_ZONE */
1899 return result;
1900}
static struct ast_tm * timesub(const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
Definition: localtime.c:1913
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, sizeof gmt),(2 *(MY_TZNAME_MAX+1)))]
Definition: localtime.c:171

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

Referenced by localsub().

◆ increment_overflow()

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

Simplified normalize logic courtesy Paul Eggert.

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

Definition at line 2051 of file localtime.c.

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

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

◆ inotify_daemon()

static void * inotify_daemon ( void *  data)
static

Definition at line 353 of file localtime.c.

354{
355 /* inotify_event is dynamically sized */
356 struct inotify_event *iev;
357 size_t real_sizeof_iev = sizeof(*iev) + FILENAME_MAX + 1;
358 ssize_t res;
359 struct state *cur;
360
361 inotify_fd = inotify_init();
362
366
367 if (inotify_fd < 0) {
368 ast_log(LOG_ERROR, "Cannot initialize file notification service: %s (%d)\n", strerror(errno), errno);
370 return NULL;
371 }
372 iev = ast_alloca(real_sizeof_iev);
373
375
376 for (;/*ever*/;) {
377 /* This read should block, most of the time. */
378 if ((res = read(inotify_fd, iev, real_sizeof_iev)) < sizeof(*iev) && res > 0) {
379 /* This should never happen */
380 ast_log(LOG_ERROR, "Inotify read less than a full event (%zd < %zu)?!!\n", res, sizeof(*iev));
381 break;
382 } else if (res < 0) {
383 if (errno == EINTR || errno == EAGAIN) {
384 /* If read fails, try again */
388 continue;
389 }
390 /* Sanity check -- this should never happen, either */
391 ast_log(LOG_ERROR, "Inotify failed: %s\n", strerror(errno));
392 break;
393 }
396 if (cur->wd[0] == iev->wd || cur->wd[1] == iev->wd) {
398 sstate_free(cur);
399 break;
400 }
401 }
405 }
406 close(inotify_fd);
408 return NULL;
409}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
static void common_startup(void)
Definition: localtime.c:328
#define ast_cond_broadcast(cond)
Definition: lock.h:204
int errno

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

Referenced by add_notify().

◆ leaps_thru_end_of()

static int leaps_thru_end_of ( const int  y)
static

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

Definition at line 1907 of file localtime.c.

1908{
1909 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1910 -(leaps_thru_end_of(-(y + 1)) + 1);
1911}
static int leaps_thru_end_of(const int y)
Return the number of leap years through the end of the given year where, to make the math easy,...
Definition: localtime.c:1907

References leaps_thru_end_of().

Referenced by leaps_thru_end_of(), and timesub().

◆ localsub()

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

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

Definition at line 1648 of file localtime.c.

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 * gmtsub(const struct timeval *timep, const long offset, struct ast_tm *tmp)
Definition: localtime.c:1866
time type information
Definition: localtime.c:132
int tt_abbrind
Definition: localtime.c:135

References state::ats, AVGSECSPERYEAR, state::chars, gmtsub(), state::goahead, state::goback, int_fast64_t, localsub(), NULL, result, state::timecnt, timesub(), tmp(), ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.

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

◆ long_increment_overflow()

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

Definition at line 2060 of file localtime.c.

2061{
2062 long number0;
2063
2064 number0 = *number;
2065 *number += delta;
2066 return (*number < number0) != (delta < 0);
2067}

Referenced by long_normalize_overflow(), and time2sub().

◆ long_normalize_overflow()

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

Definition at line 2080 of file localtime.c.

2081{
2082 int tensdelta;
2083
2084 tensdelta = (*unitsptr >= 0) ?
2085 (*unitsptr / base) :
2086 (-1 - (-1 - *unitsptr) / base);
2087 *unitsptr -= tensdelta * base;
2088 return long_increment_overflow(tensptr, tensdelta);
2089}
static int long_increment_overflow(long *number, int delta)
Definition: localtime.c:2060

References long_increment_overflow().

Referenced by time2sub().

◆ normalize_overflow()

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

Definition at line 2069 of file localtime.c.

2070{
2071 int tensdelta;
2072
2073 tensdelta = (*unitsptr >= 0) ?
2074 (*unitsptr / base) :
2075 (-1 - (-1 - *unitsptr) / base);
2076 *unitsptr -= tensdelta * base;
2077 return increment_overflow(tensptr, tensdelta);
2078}
static int increment_overflow(int *number, int delta)
Simplified normalize logic courtesy Paul Eggert.
Definition: localtime.c:2051

References increment_overflow().

Referenced by time2sub().

◆ P() [1/24]

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

◆ P() [2/24]

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

◆ P() [3/24]

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

◆ P() [4/24]

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

◆ P() [5/24]

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

◆ P() [6/24]

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

◆ P() [7/24]

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

◆ P() [8/24]

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

◆ P() [9/24]

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

◆ P() [10/24]

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

◆ P() [11/24]

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

◆ P() [12/24]

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

◆ P() [13/24]

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

◆ P() [14/24]

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

◆ P() [15/24]

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

◆ P() [16/24]

static int leaps_thru_end_of P ( (int y)  )
static

◆ P() [17/24]

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

◆ P() [18/24]

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

◆ P() [19/24]

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

◆ P() [20/24]

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

◆ P() [21/24]

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

◆ P() [22/24]

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

◆ P() [23/24]

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

◆ P() [24/24]

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

◆ sstate_alloc()

static struct state * sstate_alloc ( void  )
static

Definition at line 778 of file localtime.c.

779{
780 struct state *p = ast_calloc(1, sizeof(*p));
781
782 if (p != NULL) {
783 SP_HEAP_INIT(p);
784 }
785
786 return p;
787}
#define SP_HEAP_INIT(sp)
Definition: localtime.c:195

References ast_calloc, NULL, and SP_HEAP_INIT.

Referenced by ast_tzset(), and gmtsub().

◆ sstate_free()

static void sstate_free ( struct state p)
static

Definition at line 789 of file localtime.c.

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

References ast_free, and SP_HEAP_FREE.

Referenced by clean_time_zones(), and inotify_daemon().

◆ store_by_locale()

static const char * store_by_locale ( locale_t  prevlocale)
static

Definition at line 2388 of file localtime.c.

2389{
2390 struct locale_entry *cur;
2391 if (prevlocale == LC_GLOBAL_LOCALE) {
2392 return NULL;
2393 } else {
2394 /* Get a handle for this entry, if any */
2395 if ((cur = find_by_locale(prevlocale))) {
2396 return cur->name;
2397 } else {
2398 /* Create an entry, so it can be restored later */
2399 int x;
2400 cur = NULL;
2402 for (x = 0; x < 10000; x++) {
2403 char name[6];
2404 snprintf(name, sizeof(name), "%04d", x);
2405 if (!find_by_name(name)) {
2406 if ((cur = ast_calloc(1, sizeof(*cur) + strlen(name) + 1))) {
2407 cur->locale = prevlocale;
2408 strcpy(cur->name, name); /* SAFE */
2410 }
2411 break;
2412 }
2413 }
2415 return cur ? cur->name : NULL;
2416 }
2417 }
2418}
static struct locale_entry * find_by_locale(locale_t locale)
Definition: localtime.c:2366

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

Referenced by ast_setlocale().

◆ time1()

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

Definition at line 2292 of file localtime.c.

2293{
2294 struct timeval t;
2295 int samei, otheri;
2296 int sameind, otherind;
2297 int i;
2298 int nseen;
2299 int seen[TZ_MAX_TYPES];
2300 int types[TZ_MAX_TYPES];
2301 int okay;
2302
2303 if (tmp->tm_isdst > 1)
2304 tmp->tm_isdst = 1;
2305 t = time2(tmp, funcp, offset, &okay, sp);
2306#ifdef PCTS
2307 /*
2308 ** PCTS code courtesy Grant Sullivan.
2309 */
2310 if (okay)
2311 return t;
2312 if (tmp->tm_isdst < 0)
2313 tmp->tm_isdst = 0; /* reset to std and try again */
2314#endif /* defined PCTS */
2315#ifndef PCTS
2316 if (okay || tmp->tm_isdst < 0)
2317 return t;
2318#endif /* !defined PCTS */
2319 /*
2320 ** We're supposed to assume that somebody took a time of one type
2321 ** and did some math on it that yielded a "struct ast_tm" that's bad.
2322 ** We try to divine the type they started from and adjust to the
2323 ** type they need.
2324 */
2325 if (sp == NULL)
2326 return WRONG;
2327 for (i = 0; i < sp->typecnt; ++i)
2328 seen[i] = FALSE;
2329 nseen = 0;
2330 for (i = sp->timecnt - 1; i >= 0; --i)
2331 if (!seen[sp->types[i]]) {
2332 seen[sp->types[i]] = TRUE;
2333 types[nseen++] = sp->types[i];
2334 }
2335 for (sameind = 0; sameind < nseen; ++sameind) {
2336 samei = types[sameind];
2337 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2338 continue;
2339 for (otherind = 0; otherind < nseen; ++otherind) {
2340 otheri = types[otherind];
2341 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2342 continue;
2343 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
2344 sp->ttis[samei].tt_gmtoff;
2345 tmp->tm_isdst = !tmp->tm_isdst;
2346 t = time2(tmp, funcp, offset, &okay, sp);
2347 if (okay)
2348 return t;
2349 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
2350 sp->ttis[samei].tt_gmtoff;
2351 tmp->tm_isdst = !tmp->tm_isdst;
2352 }
2353 }
2354 return WRONG;
2355}
static struct timeval time2(struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), const long offset, int *okayp, const struct state *sp)
Definition: localtime.c:2279
#define TZ_MAX_TYPES
Definition: tzfile.h:112

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

Referenced by ast_mktime().

◆ time2()

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

Definition at line 2279 of file localtime.c.

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 struct timeval time2sub(struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, int *okayp, const int do_norm_secs, const struct state *sp)
Definition: localtime.c:2105

References FALSE, time2sub(), tmp(), and TRUE.

Referenced by time1().

◆ time2sub()

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

Definition at line 2105 of file localtime.c.

2106{
2107 int dir;
2108 int i, j;
2109 int saved_seconds;
2110 long li;
2111 time_t lo;
2112 time_t hi;
2113 long y;
2114 struct timeval newt = { 0, 0 };
2115 struct timeval t = { 0, 0 };
2116 struct ast_tm yourtm, mytm;
2117
2118 *okayp = FALSE;
2119 yourtm = *tmp;
2120 if (do_norm_secs) {
2121 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
2122 SECSPERMIN))
2123 return WRONG;
2124 }
2125 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
2126 return WRONG;
2127 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
2128 return WRONG;
2129 y = yourtm.tm_year;
2130 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
2131 return WRONG;
2132 /*
2133 ** Turn y into an actual year number for now.
2134 ** It is converted back to an offset from TM_YEAR_BASE later.
2135 */
2137 return WRONG;
2138 while (yourtm.tm_mday <= 0) {
2139 if (long_increment_overflow(&y, -1))
2140 return WRONG;
2141 li = y + (1 < yourtm.tm_mon);
2142 yourtm.tm_mday += year_lengths[isleap(li)];
2143 }
2144 while (yourtm.tm_mday > DAYSPERLYEAR) {
2145 li = y + (1 < yourtm.tm_mon);
2146 yourtm.tm_mday -= year_lengths[isleap(li)];
2147 if (long_increment_overflow(&y, 1))
2148 return WRONG;
2149 }
2150 for ( ; ; ) {
2151 i = mon_lengths[isleap(y)][yourtm.tm_mon];
2152 if (yourtm.tm_mday <= i)
2153 break;
2154 yourtm.tm_mday -= i;
2155 if (++yourtm.tm_mon >= MONSPERYEAR) {
2156 yourtm.tm_mon = 0;
2157 if (long_increment_overflow(&y, 1))
2158 return WRONG;
2159 }
2160 }
2162 return WRONG;
2163 yourtm.tm_year = y;
2164 if (yourtm.tm_year != y)
2165 return WRONG;
2166 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
2167 saved_seconds = 0;
2168 else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
2169 /*
2170 ** We can't set tm_sec to 0, because that might push the
2171 ** time below the minimum representable time.
2172 ** Set tm_sec to 59 instead.
2173 ** This assumes that the minimum representable time is
2174 ** not in the same minute that a leap second was deleted from,
2175 ** which is a safer assumption than using 58 would be.
2176 */
2177 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
2178 return WRONG;
2179 saved_seconds = yourtm.tm_sec;
2180 yourtm.tm_sec = SECSPERMIN - 1;
2181 } else {
2182 saved_seconds = yourtm.tm_sec;
2183 yourtm.tm_sec = 0;
2184 }
2185 /*
2186 ** Do a binary search (this works whatever time_t's type is).
2187 */
2188 if (!TYPE_SIGNED(time_t)) {
2189 lo = 0;
2190 hi = lo - 1;
2191 } else if (!TYPE_INTEGRAL(time_t)) {
2192 if (sizeof(time_t) > sizeof(float))
2193 hi = (time_t) DBL_MAX;
2194 else hi = (time_t) FLT_MAX;
2195 lo = -hi;
2196 } else {
2197 lo = 1;
2198 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
2199 lo *= 2;
2200 hi = -(lo + 1);
2201 }
2202 for ( ; ; ) {
2203 t.tv_sec = lo / 2 + hi / 2;
2204 if (t.tv_sec < lo)
2205 t.tv_sec = lo;
2206 else if (t.tv_sec > hi)
2207 t.tv_sec = hi;
2208 if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
2209 /*
2210 ** Assume that t is too extreme to be represented in
2211 ** a struct ast_tm; arrange things so that it is less
2212 ** extreme on the next pass.
2213 */
2214 dir = (t.tv_sec > 0) ? 1 : -1;
2215 } else dir = tmcomp(&mytm, &yourtm);
2216 if (dir != 0) {
2217 if (t.tv_sec == lo) {
2218 ++t.tv_sec;
2219 if (t.tv_sec <= lo)
2220 return WRONG;
2221 ++lo;
2222 } else if (t.tv_sec == hi) {
2223 --t.tv_sec;
2224 if (t.tv_sec >= hi)
2225 return WRONG;
2226 --hi;
2227 }
2228 if (lo > hi)
2229 return WRONG;
2230 if (dir > 0)
2231 hi = t.tv_sec;
2232 else lo = t.tv_sec;
2233 continue;
2234 }
2235 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
2236 break;
2237 /*
2238 ** Right time, wrong type.
2239 ** Hunt for right time, right type.
2240 ** It's okay to guess wrong since the guess
2241 ** gets checked.
2242 */
2243 /*
2244 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
2245 */
2246 for (i = sp->typecnt - 1; i >= 0; --i) {
2247 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
2248 continue;
2249 for (j = sp->typecnt - 1; j >= 0; --j) {
2250 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
2251 continue;
2252 newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff -
2253 sp->ttis[i].tt_gmtoff;
2254 if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
2255 continue;
2256 if (tmcomp(&mytm, &yourtm) != 0)
2257 continue;
2258 if (mytm.tm_isdst != yourtm.tm_isdst)
2259 continue;
2260 /*
2261 ** We have a match.
2262 */
2263 t = newt;
2264 goto label;
2265 }
2266 }
2267 return WRONG;
2268 }
2269label:
2270 newt.tv_sec = t.tv_sec + saved_seconds;
2271 if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0))
2272 return WRONG;
2273 t.tv_sec = newt.tv_sec;
2274 if ((*funcp)(&t, offset, tmp, sp))
2275 *okayp = TRUE;
2276 return t;
2277}
static int long_normalize_overflow(long *tensptr, int *unitsptr, const int base)
Definition: localtime.c:2080
static int normalize_overflow(int *tensptr, int *unitsptr, const int base)
Definition: localtime.c:2069
static int tmcomp(const struct ast_tm *atmp, const struct ast_tm *btmp)
Definition: localtime.c:2091
static const int year_lengths[2]
Definition: localtime.c:1108
static const int mon_lengths[2][MONSPERYEAR]
Definition: localtime.c:1103
#define TM_YEAR_BASE
Definition: tzfile.h:163
#define isleap(y)
Definition: tzfile.h:168
#define EPOCH_YEAR
Definition: tzfile.h:165

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

Referenced by time2().

◆ timesub()

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

Definition at line 1913 of file localtime.c.

1914{
1915 const struct lsinfo * lp;
1916 time_t tdays;
1917 int idays; /* unsigned would be so 2003 */
1918 long rem;
1919 int y;
1920 const int * ip;
1921 long corr;
1922 int hit;
1923 int i;
1924 long seconds;
1925
1926
1927 corr = 0;
1928 hit = 0;
1929 i = (sp == NULL) ? 0 : sp->leapcnt;
1930 while (--i >= 0) {
1931 lp = &sp->lsis[i];
1932 if (timep->tv_sec >= lp->ls_trans) {
1933 if (timep->tv_sec == lp->ls_trans) {
1934 hit = ((i == 0 && lp->ls_corr > 0) ||
1935 lp->ls_corr > sp->lsis[i - 1].ls_corr);
1936 if (hit)
1937 while (i > 0 &&
1938 sp->lsis[i].ls_trans ==
1939 sp->lsis[i - 1].ls_trans + 1 &&
1940 sp->lsis[i].ls_corr ==
1941 sp->lsis[i - 1].ls_corr + 1) {
1942 ++hit;
1943 --i;
1944 }
1945 }
1946 corr = lp->ls_corr;
1947 break;
1948 }
1949 }
1950 y = EPOCH_YEAR;
1951 tdays = timep->tv_sec / SECSPERDAY;
1952 rem = timep->tv_sec - tdays * SECSPERDAY;
1953 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
1954 int newy;
1955 time_t tdelta;
1956 int idelta;
1957 int leapdays;
1958
1959 tdelta = tdays / DAYSPERLYEAR;
1960 idelta = tdelta;
1961 if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
1962 return NULL;
1963 if (idelta == 0)
1964 idelta = (tdays < 0) ? -1 : 1;
1965 newy = y;
1966 if (increment_overflow(&newy, idelta))
1967 return NULL;
1968 leapdays = leaps_thru_end_of(newy - 1) -
1969 leaps_thru_end_of(y - 1);
1970 tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
1971 tdays -= leapdays;
1972 y = newy;
1973 }
1974
1975 seconds = tdays * SECSPERDAY + 0.5;
1976 tdays = seconds / SECSPERDAY;
1977 rem += seconds - tdays * SECSPERDAY;
1978
1979 /*
1980 ** Given the range, we can now fearlessly cast...
1981 */
1982 idays = tdays;
1983 rem += offset - corr;
1984 while (rem < 0) {
1985 rem += SECSPERDAY;
1986 --idays;
1987 }
1988 while (rem >= SECSPERDAY) {
1989 rem -= SECSPERDAY;
1990 ++idays;
1991 }
1992 while (idays < 0) {
1993 if (increment_overflow(&y, -1))
1994 return NULL;
1995 idays += year_lengths[isleap(y)];
1996 }
1997 while (idays >= year_lengths[isleap(y)]) {
1998 idays -= year_lengths[isleap(y)];
1999 if (increment_overflow(&y, 1))
2000 return NULL;
2001 }
2002 tmp->tm_year = y;
2003 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
2004 return NULL;
2005 tmp->tm_yday = idays;
2006 /*
2007 ** The "extra" mods below avoid overflow problems.
2008 */
2009 tmp->tm_wday = EPOCH_WDAY +
2010 ((y - EPOCH_YEAR) % DAYSPERWEEK) *
2012 leaps_thru_end_of(y - 1) -
2014 idays;
2015 tmp->tm_wday %= DAYSPERWEEK;
2016 if (tmp->tm_wday < 0)
2017 tmp->tm_wday += DAYSPERWEEK;
2018 tmp->tm_hour = (int) (rem / SECSPERHOUR);
2019 rem %= SECSPERHOUR;
2020 tmp->tm_min = (int) (rem / SECSPERMIN);
2021 /*
2022 ** A positive leap second requires a special
2023 ** representation. This uses "... ??:59:60" et seq.
2024 */
2025 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
2026 ip = mon_lengths[isleap(y)];
2027 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
2028 idays -= ip[tmp->tm_mon];
2029 tmp->tm_mday = (int) (idays + 1);
2030 tmp->tm_isdst = 0;
2031#ifdef TM_GMTOFF
2032 tmp->TM_GMTOFF = offset;
2033#endif /* defined TM_GMTOFF */
2034 tmp->tm_usec = timep->tv_usec;
2035 return tmp;
2036}
while(1)
Definition: ast_expr2f.c:880
leap second information
Definition: localtime.c:141
long ls_corr
Definition: localtime.c:143
time_t ls_trans
Definition: localtime.c:142
struct lsinfo lsis[TZ_MAX_LEAPS]
Definition: localtime.c:172
int leapcnt
Definition: localtime.c:161
#define SECSPERDAY
Definition: tzfile.h:139
#define EPOCH_WDAY
Definition: tzfile.h:166

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, mon_lengths, NULL, SECSPERDAY, SECSPERHOUR, SECSPERMIN, TM_YEAR_BASE, tmp(), while(), and year_lengths.

Referenced by gmtsub(), and localsub().

◆ tmcomp()

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

Definition at line 2091 of file localtime.c.

2092{
2093 int result;
2094
2095 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
2096 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
2097 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
2098 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
2099 (result = (atmp->tm_min - btmp->tm_min)) == 0 &&
2100 (result = (atmp->tm_sec - btmp->tm_sec)) == 0)
2101 result = atmp->tm_usec - btmp->tm_usec;
2102 return result;
2103}
int tm_mday
Definition: localtime.h:39
int tm_sec
Definition: localtime.h:36
int tm_hour
Definition: localtime.h:38
int tm_min
Definition: localtime.h:37
int tm_year
Definition: localtime.h:41
int tm_mon
Definition: localtime.h:40

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

Referenced by time2sub().

◆ transtime()

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

Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect.

Definition at line 1295 of file localtime.c.

1296{
1297 int leapyear;
1298 time_t value;
1299 int i;
1300 int d, m1, yy0, yy1, yy2, dow;
1301
1303 leapyear = isleap(year);
1304 switch (rulep->r_type) {
1305
1306 case JULIAN_DAY:
1307 /*
1308 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
1309 ** years.
1310 ** In non-leap years, or if the day number is 59 or less, just
1311 ** add SECSPERDAY times the day number-1 to the time of
1312 ** January 1, midnight, to get the day.
1313 */
1314 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
1315 if (leapyear && rulep->r_day >= 60)
1316 value += SECSPERDAY;
1317 break;
1318
1319 case DAY_OF_YEAR:
1320 /*
1321 ** n - day of year.
1322 ** Just add SECSPERDAY times the day number to the time of
1323 ** January 1, midnight, to get the day.
1324 */
1325 value = janfirst + rulep->r_day * SECSPERDAY;
1326 break;
1327
1329 /*
1330 ** Mm.n.d - nth "dth day" of month m.
1331 */
1332 value = janfirst;
1333 for (i = 0; i < rulep->r_mon - 1; ++i)
1334 value += mon_lengths[leapyear][i] * SECSPERDAY;
1335
1336 /*
1337 ** Use Zeller's Congruence to get day-of-week of first day of
1338 ** month.
1339 */
1340 m1 = (rulep->r_mon + 9) % 12 + 1;
1341 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
1342 yy1 = yy0 / 100;
1343 yy2 = yy0 % 100;
1344 dow = ((26 * m1 - 2) / 10 +
1345 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1346 if (dow < 0)
1347 dow += DAYSPERWEEK;
1348
1349 /*
1350 ** "dow" is the day-of-week of the first day of the month. Get
1351 ** the day-of-month (zero-origin) of the first "dow" day of the
1352 ** month.
1353 */
1354 d = rulep->r_day - dow;
1355 if (d < 0)
1356 d += DAYSPERWEEK;
1357 for (i = 1; i < rulep->r_week; ++i) {
1358 if (d + DAYSPERWEEK >=
1359 mon_lengths[leapyear][rulep->r_mon - 1])
1360 break;
1361 d += DAYSPERWEEK;
1362 }
1363
1364 /*
1365 ** "d" is the day-of-month (zero-origin) of the day we want.
1366 */
1367 value += d * SECSPERDAY;
1368 break;
1369 }
1370
1371 /*
1372 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
1373 ** question. To get the Epoch-relative time of the specified local
1374 ** time on that day, add the transition time and the current offset
1375 ** from UTC.
1376 */
1377 return value + rulep->r_time + offset;
1378}
#define INITIALIZE(x)
int value
Definition: syslog.c:37
static struct test_val d

References d, DAY_OF_YEAR, DAYSPERWEEK, INITIALIZE, isleap, JULIAN_DAY, mon_lengths, 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().

◆ tzload()

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

Definition at line 853 of file localtime.c.

854{
855 const char * p;
856 int i;
857 int fid;
858 int stored;
859 int nread;
860 union {
861 struct tzhead tzhead;
862 char buf[2 * sizeof(struct tzhead) +
863 2 * sizeof *sp +
864 4 * TZ_MAX_TIMES];
865 } u;
866
867 if (name == NULL && (name = TZDEFAULT) == NULL)
868 return -1;
869 {
870 int doaccess;
871 /*
872 ** Section 4.9.1 of the C standard says that
873 ** "FILENAME_MAX expands to an integral constant expression
874 ** that is the size needed for an array of char large enough
875 ** to hold the longest file name string that the implementation
876 ** guarantees can be opened."
877 */
878 char fullname[FILENAME_MAX + 1];
879
880 if (name[0] == ':')
881 ++name;
882 doaccess = name[0] == '/';
883 if (!doaccess) {
884 if ((p = TZDIR) == NULL)
885 return -1;
886 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
887 return -1;
888 (void) strcpy(fullname, p);
889 (void) strcat(fullname, "/");
890 (void) strcat(fullname, name);
891 /*
892 ** Set doaccess if '.' (as in "../") shows up in name.
893 */
894 if (strchr(name, '.') != NULL)
895 doaccess = TRUE;
896 name = fullname;
897 }
898 if (doaccess && access(name, R_OK) != 0)
899 return -1;
900 if ((fid = open(name, OPEN_MODE)) == -1)
901 return -1;
902 if (ast_fully_booted) {
903 /* If we don't wait until Asterisk is fully booted, it's possible
904 * that the watcher thread gets started in the parent process,
905 * before daemon(3) is called, and the thread won't propagate to
906 * the child. Given that bootup only takes a few seconds, it's
907 * reasonable to only start the watcher later. */
908 add_notify(sp, name);
909 }
910 }
911 nread = read(fid, u.buf, sizeof u.buf);
912 /* comp nread < sizeof u.tzhead against unexpected short files */
913 if (close(fid) < 0 || nread < sizeof u.tzhead)
914 return -1;
915 for (stored = 4; stored <= 8; stored *= 2) {
916 int ttisstdcnt;
917 int ttisgmtcnt;
918
919 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
920 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
921 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
922 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
923 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
924 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
925 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
926 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
927 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
928 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
929 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
930 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
931 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
932 return -1;
933 if (nread - (p - u.buf) <
934 sp->timecnt * stored + /* ats */
935 sp->timecnt + /* types */
936 sp->typecnt * 6 + /* ttinfos */
937 sp->charcnt + /* chars */
938 sp->leapcnt * (stored + 4) + /* lsinfos */
939 ttisstdcnt + /* ttisstds */
940 ttisgmtcnt) /* ttisgmts */
941 return -1;
942 for (i = 0; i < sp->timecnt; ++i) {
943 sp->ats[i] = (stored == 4) ?
944 detzcode(p) : detzcode64(p);
945 p += stored;
946 }
947 for (i = 0; i < sp->timecnt; ++i) {
948 sp->types[i] = (unsigned char) *p++;
949 if (sp->types[i] >= sp->typecnt)
950 return -1;
951 }
952 for (i = 0; i < sp->typecnt; ++i) {
953 struct ttinfo * ttisp;
954
955 ttisp = &sp->ttis[i];
956 ttisp->tt_gmtoff = detzcode(p);
957 p += 4;
958 ttisp->tt_isdst = (unsigned char) *p++;
959 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
960 return -1;
961 ttisp->tt_abbrind = (unsigned char) *p++;
962 if (ttisp->tt_abbrind < 0 ||
963 ttisp->tt_abbrind > sp->charcnt)
964 return -1;
965 }
966 for (i = 0; i < sp->charcnt; ++i)
967 sp->chars[i] = *p++;
968 sp->chars[i] = '\0'; /* ensure '\0' at end */
969 for (i = 0; i < sp->leapcnt; ++i) {
970 struct lsinfo * lsisp;
971
972 lsisp = &sp->lsis[i];
973 lsisp->ls_trans = (stored == 4) ?
974 detzcode(p) : detzcode64(p);
975 p += stored;
976 lsisp->ls_corr = detzcode(p);
977 p += 4;
978 }
979 for (i = 0; i < sp->typecnt; ++i) {
980 struct ttinfo * ttisp;
981
982 ttisp = &sp->ttis[i];
983 if (ttisstdcnt == 0)
984 ttisp->tt_ttisstd = FALSE;
985 else {
986 ttisp->tt_ttisstd = *p++;
987 if (ttisp->tt_ttisstd != TRUE &&
988 ttisp->tt_ttisstd != FALSE)
989 return -1;
990 }
991 }
992 for (i = 0; i < sp->typecnt; ++i) {
993 struct ttinfo * ttisp;
994
995 ttisp = &sp->ttis[i];
996 if (ttisgmtcnt == 0)
997 ttisp->tt_ttisgmt = FALSE;
998 else {
999 ttisp->tt_ttisgmt = *p++;
1000 if (ttisp->tt_ttisgmt != TRUE &&
1001 ttisp->tt_ttisgmt != FALSE)
1002 return -1;
1003 }
1004 }
1005 /*
1006 ** Out-of-sort ats should mean we're running on a
1007 ** signed time_t system but using a data file with
1008 ** unsigned values (or vice versa).
1009 */
1010 for (i = 0; i < sp->timecnt - 2; ++i)
1011 if (sp->ats[i] > sp->ats[i + 1]) {
1012 ++i;
1013 if (TYPE_SIGNED(time_t)) {
1014 /*
1015 ** Ignore the end (easy).
1016 */
1017 sp->timecnt = i;
1018 } else {
1019 /*
1020 ** Ignore the beginning (harder).
1021 */
1022 int j;
1023
1024 for (j = 0; j + i < sp->timecnt; ++j) {
1025 sp->ats[j] = sp->ats[j + i];
1026 sp->types[j] = sp->types[j + i];
1027 }
1028 sp->timecnt = j;
1029 }
1030 break;
1031 }
1032 /*
1033 ** If this is an old file, we're done.
1034 */
1035 if (u.tzhead.tzh_version[0] == '\0')
1036 break;
1037 nread -= p - u.buf;
1038 for (i = 0; i < nread; ++i)
1039 u.buf[i] = p[i];
1040 /* next loop iter. will assume at least
1041 sizeof(struct tzhead) bytes */
1042 if (nread < sizeof(u.tzhead)) {
1043 break;
1044 }
1045 /*
1046 ** If this is a narrow integer time_t system, we're done.
1047 */
1048 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
1049 break;
1050 }
1051 if (doextend && nread > 2 &&
1052 u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
1053 sp->typecnt + 2 <= TZ_MAX_TYPES) {
1054 struct state ts;
1055 int result;
1056
1057 /* for temporary struct state --
1058 * macro flags the struct as a stack temp.
1059 * to prevent use within add_notify()
1060 */
1061 SP_STACK_INIT(ts);
1062
1063 u.buf[nread - 1] = '\0';
1064 result = tzparse(&u.buf[1], &ts, FALSE);
1065 if (result == 0 && ts.typecnt == 2 &&
1066 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
1067 for (i = 0; i < 2; ++i)
1068 ts.ttis[i].tt_abbrind +=
1069 sp->charcnt;
1070 for (i = 0; i < ts.charcnt; ++i)
1071 sp->chars[sp->charcnt++] =
1072 ts.chars[i];
1073 i = 0;
1074 while (i < ts.timecnt &&
1075 ts.ats[i] <=
1076 sp->ats[sp->timecnt - 1])
1077 ++i;
1078 while (i < ts.timecnt &&
1079 sp->timecnt < TZ_MAX_TIMES) {
1080 sp->ats[sp->timecnt] =
1081 ts.ats[i];
1082 sp->types[sp->timecnt] =
1083 sp->typecnt +
1084 ts.types[i];
1085 ++sp->timecnt;
1086 ++i;
1087 }
1088 sp->ttis[sp->typecnt++] = ts.ttis[0];
1089 sp->ttis[sp->typecnt++] = ts.ttis[1];
1090 }
1091 }
1092 i = 2 * YEARSPERREPEAT;
1093 sp->goback = sp->goahead = sp->timecnt > i;
1094 sp->goback = sp->goback && sp->types[i] == sp->types[0] &&
1095 differ_by_repeat(sp->ats[i], sp->ats[0]);
1096 sp->goahead = sp->goahead &&
1097 sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
1098 differ_by_repeat(sp->ats[sp->timecnt - 1],
1099 sp->ats[sp->timecnt - 1 - i]);
1100 return 0;
1101}
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
static int differ_by_repeat(const time_t t1, const time_t t0)
Definition: localtime.c:844
static long detzcode(const char *const codep)
Definition: localtime.c:822
#define OPEN_MODE
Definition: localtime.c:107
#define SP_STACK_INIT(sp)
Definition: localtime.c:191
static time_t detzcode64(const char *const codep)
Definition: localtime.c:833
#define ast_fully_booted
Definition: options.h:117
int charcnt
Definition: localtime.c:164
int tt_ttisgmt
Definition: localtime.c:137
int tt_ttisstd
Definition: localtime.c:136
Definition: tzfile.h:54
#define TZ_MAX_CHARS
Definition: tzfile.h:124
#define TZ_MAX_TIMES
Definition: tzfile.h:107
#define TZ_MAX_LEAPS
Definition: tzfile.h:129

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

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

◆ tzparse()

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

Definition at line 1385 of file localtime.c.

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

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

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

Variable Documentation

◆ elsieid

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

Definition at line 82 of file localtime.c.

◆ gmt

const char gmt[] = "GMT"
static

Definition at line 110 of file localtime.c.

Referenced by gmtload().

◆ initialization

ast_cond_t initialization
static

Definition at line 322 of file localtime.c.

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

◆ initialization_lock

ast_mutex_t initialization_lock
static

Definition at line 323 of file localtime.c.

Referenced by add_notify(), and inotify_daemon().

◆ inotify_fd

int inotify_fd = -1
static

Definition at line 351 of file localtime.c.

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

◆ inotify_thread

pthread_t inotify_thread = AST_PTHREADT_NULL
static

Definition at line 321 of file localtime.c.

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

◆ localelist

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

◆ mon_lengths

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

Definition at line 1103 of file localtime.c.

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

◆ WRONG

const struct timeval WRONG = { 0, 0 }
static

Definition at line 111 of file localtime.c.

Referenced by ast_mktime(), time1(), and time2sub().

◆ year_lengths

const int year_lengths[2]
static
Initial value:

Definition at line 1108 of file localtime.c.

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

◆ zonelist

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