Sat Mar 10 01:55:29 2012

Asterisk developer's documentation


localtime.c File Reference

#include "asterisk.h"
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <float.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include "private.h"
#include "tzfile.h"
#include "asterisk/lock.h"
#include "asterisk/localtime.h"
#include "asterisk/strings.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/test.h"

Go to the source code of this file.

Data Structures

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

Defines

#define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
#define DAY_OF_YEAR   1
#define JULIAN_DAY   0
#define MONTH_NTH_DAY_OF_WEEK   2
#define MY_TZNAME_MAX   255
#define OPEN_MODE   O_RDONLY
#define TZ_ABBR_CHAR_SET   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
#define TZ_ABBR_ERR_CHAR   '_'
#define TZ_ABBR_MAX_LEN   16
#define TZ_STRLEN_MAX   255
#define TZDEFRULESTRING   ",M4.1.0,M10.5.0"

Functions

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

Variables

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


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.


Define Documentation

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

Definition at line 143 of file localtime.c.

#define DAY_OF_YEAR   1

Definition at line 200 of file localtime.c.

Referenced by getrule(), and transtime().

#define JULIAN_DAY   0

Definition at line 199 of file localtime.c.

Referenced by getrule(), and transtime().

#define MONTH_NTH_DAY_OF_WEEK   2

Definition at line 201 of file localtime.c.

Referenced by getrule(), and transtime().

#define MY_TZNAME_MAX   255

Definition at line 149 of file localtime.c.

#define OPEN_MODE   O_RDONLY

Definition at line 104 of file localtime.c.

Referenced by tzload().

#define TZ_ABBR_CHAR_SET   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"

Definition at line 88 of file localtime.c.

#define TZ_ABBR_ERR_CHAR   '_'

Definition at line 93 of file localtime.c.

#define TZ_ABBR_MAX_LEN   16

Definition at line 84 of file localtime.c.

#define TZ_STRLEN_MAX   255

Definition at line 152 of file localtime.c.

#define TZDEFRULESTRING   ",M4.1.0,M10.5.0"

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

Definition at line 125 of file localtime.c.

Referenced by tzparse().


Function Documentation

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

Definition at line 323 of file localtime.c.

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

Referenced by tzload().

00324 {
00325    if (inotify_thread == AST_PTHREADT_NULL) {
00326       ast_cond_init(&initialization, NULL);
00327       ast_mutex_init(&initialization_lock);
00328       ast_mutex_lock(&initialization_lock);
00329       if (!(ast_pthread_create_background(&inotify_thread, NULL, inotify_daemon, NULL))) {
00330          /* Give the thread a chance to initialize */
00331          ast_cond_wait(&initialization, &initialization_lock);
00332       } else {
00333          fprintf(stderr, "Unable to start notification thread\n");
00334          ast_mutex_unlock(&initialization_lock);
00335          return;
00336       }
00337       ast_mutex_unlock(&initialization_lock);
00338    }
00339 
00340    if (inotify_fd > -1) {
00341       char fullpath[FILENAME_MAX + 1] = "";
00342       if (readlink(path, fullpath, sizeof(fullpath) - 1) != -1) {
00343          /* If file the symlink points to changes */
00344          sp->wd[1] = inotify_add_watch(inotify_fd, fullpath, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE );
00345       } else {
00346          sp->wd[1] = -1;
00347       }
00348       /* or if the symlink itself changes (or the real file is here, if path is not a symlink) */
00349       sp->wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE
00350 #ifdef IN_DONT_FOLLOW   /* Only defined in glibc 2.5 and above */
00351          | IN_DONT_FOLLOW
00352 #endif
00353       );
00354    }
00355 }

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

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

Referenced by set_timezone_variables().

01563 {
01564    int i;   
01565    int transition1 = -1;
01566    int transition2 = -1;
01567    time_t      seconds;
01568    int  bounds_exceeded = 0;
01569    time_t  t = *timep;
01570    const struct state *sp;
01571    
01572    if (NULL == dst_enabled)
01573       return;
01574    *dst_enabled = 0;
01575 
01576    if (NULL == dst_start || NULL == dst_end || NULL == gmt_off)
01577       return;
01578 
01579    *gmt_off = 0; 
01580    
01581    sp = ast_tzset(zone);
01582    if (NULL == sp) 
01583       return;
01584    
01585    /* If the desired time exceeds the bounds of the defined time transitions  
01586    * then give give up on determining DST info and simply look for gmt offset 
01587    * This requires that I adjust the given time using increments of Gregorian 
01588    * repeats to place the time within the defined time transitions in the 
01589    * timezone structure.  
01590    */
01591    if ((sp->goback && t < sp->ats[0]) ||
01592          (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
01593       time_t      tcycles;
01594       int_fast64_t   icycles;
01595 
01596       if (t < sp->ats[0])
01597          seconds = sp->ats[0] - t;
01598       else  seconds = t - sp->ats[sp->timecnt - 1];
01599       --seconds;
01600       tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
01601       ++tcycles;
01602       icycles = tcycles;
01603       if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
01604          return;
01605       seconds = icycles;
01606       seconds *= YEARSPERREPEAT;
01607       seconds *= AVGSECSPERYEAR;
01608       if (t < sp->ats[0])
01609          t += seconds;
01610       else
01611          t -= seconds;
01612       
01613       if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1])
01614          return;  /* "cannot happen" */
01615 
01616       bounds_exceeded = 1;
01617    }
01618 
01619    if (sp->timecnt == 0 || t < sp->ats[0]) {
01620       /* I have no transition times or I'm before time */
01621       *dst_enabled = 0;
01622       /* Find where I can get gmtoff */
01623       i = 0;
01624       while (sp->ttis[i].tt_isdst)
01625          if (++i >= sp->typecnt) {
01626          i = 0;
01627          break;
01628          }
01629          *gmt_off = sp->ttis[i].tt_gmtoff;
01630          return;
01631    } 
01632 
01633    for (i = 1; i < sp->timecnt; ++i) {
01634       if (t < sp->ats[i]) {
01635          transition1 = sp->types[i - 1];
01636          transition2 = sp->types[i];
01637          break;
01638       } 
01639    }
01640    /* if I found transition times that do not bounded the given time and these correspond to 
01641       or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */
01642    if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 ||
01643          (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) {
01644       *dst_enabled = 0;
01645       *gmt_off     = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff;
01646    } else {
01647       /* I have valid daylight savings information. */
01648       if(sp->ttis[transition2].tt_isdst) 
01649          *gmt_off = sp->ttis[transition1].tt_gmtoff;
01650       else 
01651          *gmt_off = sp->ttis[transition2].tt_gmtoff;
01652 
01653       /* If I adjusted the time earlier, indicate that the dst is invalid */
01654       if (!bounds_exceeded) {
01655          *dst_enabled = 1;
01656          /* Determine which of the bounds is the start of daylight savings and which is the end */
01657          if(sp->ttis[transition2].tt_isdst) {
01658             *dst_start = sp->ats[i];
01659             *dst_end = sp->ats[i -1];
01660          } else {
01661             *dst_start = sp->ats[i -1];
01662             *dst_end = sp->ats[i];
01663          }
01664       }
01665    }  
01666    return;
01667 }

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:
timep Current time, including microseconds
p_tm Pointer to memory where the broken-out time will be stored
zone Text string of a standard system zoneinfo file. If NULL, the system localtime will be used.
Return values:
p_tm is returned for convenience

Definition at line 1547 of file localtime.c.

References ast_tzset(), and localsub().

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

01548 {
01549    const struct state *sp = ast_tzset(zone);
01550    memset(tmp, 0, sizeof(*tmp));
01551    return sp ? localsub(timep, 0L, tmp, sp) : NULL;
01552 }

void ast_localtime_wakeup_monitor ( struct ast_test *  info  ) 

Definition at line 602 of file localtime.c.

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

00603 {
00604    if (inotify_thread != AST_PTHREADT_NULL) {
00605       AST_LIST_LOCK(&zonelist);
00606 #ifdef TEST_FRAMEWORK
00607       test = info;
00608 #endif
00609       pthread_kill(inotify_thread, SIGURG);
00610       ast_cond_wait(&initialization, &(&zonelist)->lock);
00611 #ifdef TEST_FRAMEWORK
00612       test = NULL;
00613 #endif
00614       AST_LIST_UNLOCK(&zonelist);
00615    }
00616 }

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

Timezone-independent version of mktime(3).

Parameters:
tmp Current broken-out time, including microseconds
zone Text string of a standard system zoneinfo file. If NULL, the system localtime will be used.
Return values:
A structure containing both seconds and fractional thereof since January 1st, 1970 UTC

Definition at line 2162 of file localtime.c.

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

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

02163 {
02164    const struct state *sp;
02165    if (!(sp = ast_tzset(zone)))
02166       return WRONG;
02167    return time1(tmp, localsub, 0L, sp);
02168 }

const char* ast_setlocale ( const char *  locale  ) 

Set the thread-local representation of the current locale.

Definition at line 2225 of file localtime.c.

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

Referenced by ast_strftime_locale(), and ast_strptime_locale().

02226 {
02227    struct locale_entry *cur;
02228    locale_t prevlocale = LC_GLOBAL_LOCALE;
02229 
02230    if (locale == NULL) {
02231       return store_by_locale(uselocale(LC_GLOBAL_LOCALE));
02232    }
02233 
02234    AST_LIST_LOCK(&localelist);
02235    if ((cur = find_by_name(locale))) {
02236       prevlocale = uselocale(cur->locale);
02237    }
02238 
02239    if (!cur) {
02240       if ((cur = ast_calloc(1, sizeof(*cur) + strlen(locale) + 1))) {
02241          cur->locale = newlocale(LC_ALL_MASK, locale, NULL);
02242          strcpy(cur->name, locale); /* SAFE */
02243          AST_LIST_INSERT_TAIL(&localelist, cur, list);
02244          prevlocale = uselocale(cur->locale);
02245       }
02246    }
02247    AST_LIST_UNLOCK(&localelist);
02248    return store_by_locale(prevlocale);
02249 }

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:
buf Address in memory where the resulting string will be stored.
len Size of the chunk of memory buf.
format A string specifying the format of time to be placed into buf.
tm Pointer to the broken out time to be used for the format.
locale Text string specifying the locale to be used for language strings.
Return values:
An integer value specifying the number of bytes placed into buf or -1 on error.

Definition at line 2328 of file localtime.c.

References ast_strftime_locale().

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

02329 {
02330    return ast_strftime_locale(buf, len, tmp, tm, NULL);
02331 }

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

Definition at line 2257 of file localtime.c.

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

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

02258 {
02259    size_t fmtlen = strlen(tmp) + 1;
02260    char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt;
02261    int decimals = -1, i, res;
02262    long fraction;
02263    const char *prevlocale;
02264 
02265    if (!format) {
02266       return -1;
02267    }
02268    for (; *tmp; tmp++) {
02269       if (*tmp == '%') {
02270          switch (tmp[1]) {
02271          case '1':
02272          case '2':
02273          case '3':
02274          case '4':
02275          case '5':
02276          case '6':
02277             if (tmp[2] != 'q') {
02278                goto defcase;
02279             }
02280             decimals = tmp[1] - '0';
02281             tmp++;
02282             /* Fall through */
02283          case 'q': /* Milliseconds */
02284             if (decimals == -1) {
02285                decimals = 3;
02286             }
02287 
02288             /* Juggle some memory to fit the item */
02289             newfmt = ast_realloc(format, fmtlen + decimals);
02290             if (!newfmt) {
02291                ast_free(format);
02292                return -1;
02293             }
02294             fptr = fptr - format + newfmt;
02295             format = newfmt;
02296             fmtlen += decimals;
02297 
02298             /* Reduce the fraction of time to the accuracy needed */
02299             for (i = 6, fraction = tm->tm_usec; i > decimals; i--) {
02300                fraction /= 10;
02301             }
02302             fptr += sprintf(fptr, "%0*ld", decimals, fraction);
02303 
02304             /* Reset, in case more than one 'q' specifier exists */
02305             decimals = -1;
02306             tmp++;
02307             break;
02308          default:
02309             goto defcase;
02310          }
02311       } else {
02312 defcase: *fptr++ = *tmp;
02313       }
02314    }
02315    *fptr = '\0';
02316 #undef strftime
02317    if (locale) {
02318       prevlocale = ast_setlocale(locale);
02319    }
02320    res = (int)strftime(buf, len, format, (struct tm *)tm);
02321    if (locale) {
02322       ast_setlocale(prevlocale);
02323    }
02324    ast_free(format);
02325    return res;
02326 }

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:
s A string specifying some portion of a date and time.
format The format in which the string, s, is expected.
tm The broken-out time structure into which the parsed data is expected.
locale Text string specifying the locale to be used for language strings.
Return values:
A pointer to the first character within s not used to parse the date and time.

Definition at line 2350 of file localtime.c.

References ast_strptime_locale().

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

02351 {
02352    return ast_strptime_locale(s, format, tm, NULL);
02353 }

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

Definition at line 2333 of file localtime.c.

References ast_setlocale().

Referenced by ast_strptime().

02334 {
02335    struct tm tm2 = { 0, };
02336    char *res;
02337    const char *prevlocale;
02338 
02339    prevlocale = ast_setlocale(locale);
02340    res = strptime(s, format, &tm2);
02341    ast_setlocale(prevlocale);
02342    memcpy(tm, &tm2, sizeof(*tm));
02343    tm->tm_usec = 0;
02344    /* strptime(3) doesn't set .tm_isdst correctly, so to force ast_mktime(3)
02345     * to deal with it correctly, we set it to -1. */
02346    tm->tm_isdst = -1;
02347    return res;
02348 }

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

Definition at line 1409 of file localtime.c.

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

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

01410 {
01411    struct state *sp;
01412 
01413    if (ast_strlen_zero(zone)) {
01414 #ifdef SOLARIS
01415       zone = getenv("TZ");
01416       if (ast_strlen_zero(zone)) {
01417          zone = "GMT";
01418       }
01419 #else
01420       zone = "/etc/localtime";
01421 #endif
01422    }
01423 
01424    AST_LIST_LOCK(&zonelist);
01425    AST_LIST_TRAVERSE(&zonelist, sp, list) {
01426       if (!strcmp(sp->name, zone)) {
01427          AST_LIST_UNLOCK(&zonelist);
01428          return sp;
01429       }
01430    }
01431    AST_LIST_UNLOCK(&zonelist);
01432 
01433    if (!(sp = ast_calloc(1, sizeof *sp)))
01434       return NULL;
01435 
01436    if (tzload(zone, sp, TRUE) != 0) {
01437       if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0)
01438          (void) gmtload(sp);
01439    }
01440    ast_copy_string(sp->name, zone, sizeof(sp->name));
01441    AST_LIST_LOCK(&zonelist);
01442    AST_LIST_INSERT_TAIL(&zonelist, sp, list);
01443    AST_LIST_UNLOCK(&zonelist);
01444    return sp;
01445 }

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

Referenced by tzload().

00627 {
00628    long  result;
00629    int   i;
00630 
00631    result = (codep[0] & 0x80) ? ~0L : 0;
00632    for (i = 0; i < 4; ++i)
00633       result = (result << 8) | (codep[i] & 0xff);
00634    return result;
00635 }

static time_t detzcode64 ( const char *const   codep  )  [static]

Definition at line 637 of file localtime.c.

Referenced by tzload().

00638 {
00639    time_t   result;
00640    int   i;
00641 
00642    result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
00643    for (i = 0; i < 8; ++i)
00644       result = result * 256 + (codep[i] & 0xff);
00645    return result;
00646 }

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

Definition at line 648 of file localtime.c.

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

00649 {
00650    const long long at1 = t1, at0 = t0;
00651    if (TYPE_INTEGRAL(time_t) &&
00652       TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
00653          return 0;
00654    return at1 - at0 == SECSPERREPEAT;
00655 }

static struct locale_entry* find_by_locale ( locale_t  locale  )  [static]

Definition at line 2171 of file localtime.c.

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

Referenced by store_by_locale().

02172 {
02173    struct locale_entry *cur;
02174    AST_LIST_TRAVERSE(&localelist, cur, list) {
02175       if (locale == cur->locale) {
02176          return cur;
02177       }
02178    }
02179    return NULL;
02180 }

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

Definition at line 2182 of file localtime.c.

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

02183 {
02184    struct locale_entry *cur;
02185    AST_LIST_TRAVERSE(&localelist, cur, list) {
02186       if (strcmp(name, cur->name) == 0) {
02187          return cur;
02188       }
02189    }
02190    return NULL;
02191 }

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

References is_digit.

Referenced by getrule(), and getsecs().

00939 {
00940    char  c;
00941    int   num;
00942 
00943    if (strp == NULL || !is_digit(c = *strp))
00944       return NULL;
00945    num = 0;
00946    do {
00947       num = num * 10 + (c - '0');
00948       if (num > max)
00949          return NULL;   /* illegal value */
00950       c = *++strp;
00951    } while (is_digit(c));
00952    if (num < min)
00953       return NULL;      /* illegal value */
00954    *nump = num;
00955    return strp;
00956 }

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

References getsecs().

Referenced by tzparse().

01006 {
01007    int   neg = 0;
01008 
01009    if (*strp == '-') {
01010       neg = 1;
01011       ++strp;
01012    } else if (*strp == '+')
01013       ++strp;
01014    strp = getsecs(strp, offsetp);
01015    if (strp == NULL)
01016       return NULL;      /* illegal time */
01017    if (neg)
01018       *offsetp = -*offsetp;
01019    return strp;
01020 }

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

Referenced by tzparse().

00923 {
00924    int   c;
00925 
00926    while ((c = *strp) != '\0' && c != delim)
00927       ++strp;
00928    return strp;
00929 }

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

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

Referenced by tzparse().

01030 {
01031    if (*strp == 'J') {
01032       /*
01033       ** Julian day.
01034       */
01035       rulep->r_type = JULIAN_DAY;
01036       ++strp;
01037       strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
01038    } else if (*strp == 'M') {
01039       /*
01040       ** Month, week, day.
01041       */
01042       rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
01043       ++strp;
01044       strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
01045       if (strp == NULL)
01046          return NULL;
01047       if (*strp++ != '.')
01048          return NULL;
01049       strp = getnum(strp, &rulep->r_week, 1, 5);
01050       if (strp == NULL)
01051          return NULL;
01052       if (*strp++ != '.')
01053          return NULL;
01054       strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
01055    } else if (is_digit(*strp)) {
01056       /*
01057       ** Day of year.
01058       */
01059       rulep->r_type = DAY_OF_YEAR;
01060       strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
01061    } else   return NULL;      /* invalid format */
01062    if (strp == NULL)
01063       return NULL;
01064    if (*strp == '/') {
01065       /*
01066       ** Time specified.
01067       */
01068       ++strp;
01069       strp = getsecs(strp, &rulep->r_time);
01070    } else   rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
01071    return strp;
01072 }

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

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

Referenced by getoffset(), and getrule().

00967 {
00968    int   num;
00969 
00970    /*
00971    ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
00972    ** "M10.4.6/26", which does not conform to Posix,
00973    ** but which specifies the equivalent of
00974    ** ``02:00 on the first Sunday on or after 23 Oct''.
00975    */
00976    strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
00977    if (strp == NULL)
00978       return NULL;
00979    *secsp = num * (long) SECSPERHOUR;
00980    if (*strp == ':') {
00981       ++strp;
00982       strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
00983       if (strp == NULL)
00984          return NULL;
00985       *secsp += num * SECSPERMIN;
00986       if (*strp == ':') {
00987          ++strp;
00988          /* `SECSPERMIN' allows for leap seconds. */
00989          strp = getnum(strp, &num, 0, SECSPERMIN);
00990          if (strp == NULL)
00991             return NULL;
00992          *secsp += num;
00993       }
00994    }
00995    return strp;
00996 }

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

References is_digit.

Referenced by tzparse().

00904 {
00905    char  c;
00906 
00907    while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
00908       c != '+')
00909          ++strp;
00910    return strp;
00911 }

static int gmtload ( struct state sp  )  [static]

Definition at line 1401 of file localtime.c.

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

Referenced by ast_tzset(), and gmtsub().

01402 {
01403    if (tzload(gmt, sp, TRUE) != 0)
01404       return tzparse(gmt, sp, TRUE);
01405    else
01406       return -1;
01407 }

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

Definition at line 1673 of file localtime.c.

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

Referenced by localsub().

01674 {
01675    struct ast_tm *   result;
01676    struct state *sp;
01677 
01678    AST_LIST_LOCK(&zonelist);
01679    AST_LIST_TRAVERSE(&zonelist, sp, list) {
01680       if (!strcmp(sp->name, "UTC"))
01681          break;
01682    }
01683 
01684    if (!sp) {
01685       if (!(sp = (struct state *) ast_calloc(1, sizeof *sp)))
01686          return NULL;
01687       gmtload(sp);
01688       AST_LIST_INSERT_TAIL(&zonelist, sp, list);
01689    }
01690    AST_LIST_UNLOCK(&zonelist);
01691 
01692    result = timesub(timep, offset, sp, tmp);
01693 #ifdef TM_ZONE
01694    /*
01695    ** Could get fancy here and deliver something such as
01696    ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
01697    ** but this is no time for a treasure hunt.
01698    */
01699    if (offset != 0)
01700       tmp->TM_ZONE = "    ";
01701    else
01702       tmp->TM_ZONE = sp->chars;
01703 #endif /* defined TM_ZONE */
01704    return result;
01705 }

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

Simplified normalize logic courtesy Paul Eggert.

Definition at line 1856 of file localtime.c.

Referenced by normalize_overflow(), and timesub().

01857 {
01858    int   number0;
01859 
01860    number0 = *number;
01861    *number += delta;
01862    return (*number < number0) != (delta < 0);
01863 }

static void* inotify_daemon ( void *  data  )  [static]

Definition at line 267 of file localtime.c.

References ast_cond_broadcast, ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, errno, FILENAME_MAX, initialization_lock, state::list, LOG_ERROR, state::name, and state::wd.

Referenced by add_notify().

00268 {
00269    struct {
00270       struct inotify_event iev;
00271       char name[FILENAME_MAX + 1];
00272    } buf;
00273    ssize_t res;
00274    struct state *cur;
00275 
00276    inotify_fd = inotify_init();
00277 
00278    ast_mutex_lock(&initialization_lock);
00279    ast_cond_broadcast(&initialization);
00280    ast_mutex_unlock(&initialization_lock);
00281 
00282    if (inotify_fd < 0) {
00283       ast_log(LOG_ERROR, "Cannot initialize file notification service: %s (%d)\n", strerror(errno), errno);
00284       inotify_thread = AST_PTHREADT_NULL;
00285       return NULL;
00286    }
00287 
00288    for (;/*ever*/;) {
00289       /* This read should block, most of the time. */
00290       if ((res = read(inotify_fd, &buf, sizeof(buf))) < sizeof(buf.iev) && res > 0) {
00291          /* This should never happen */
00292          ast_log(LOG_ERROR, "Inotify read less than a full event (%zd < %zd)?!!\n", res, sizeof(buf.iev));
00293          break;
00294       } else if (res < 0) {
00295          if (errno == EINTR || errno == EAGAIN) {
00296             /* If read fails, try again */
00297             AST_LIST_LOCK(&zonelist);
00298             ast_cond_broadcast(&initialization);
00299             AST_LIST_UNLOCK(&zonelist);
00300             continue;
00301          }
00302          /* Sanity check -- this should never happen, either */
00303          ast_log(LOG_ERROR, "Inotify failed: %s\n", strerror(errno));
00304          break;
00305       }
00306       AST_LIST_LOCK(&zonelist);
00307       AST_LIST_TRAVERSE_SAFE_BEGIN(&zonelist, cur, list) {
00308          if (cur->wd[0] == buf.iev.wd || cur->wd[1] == buf.iev.wd) {
00309             AST_LIST_REMOVE_CURRENT(list);
00310             ast_free(cur);
00311             break;
00312          }
00313       }
00314       AST_LIST_TRAVERSE_SAFE_END
00315       ast_cond_broadcast(&initialization);
00316       AST_LIST_UNLOCK(&zonelist);
00317    }
00318    close(inotify_fd);
00319    inotify_thread = AST_PTHREADT_NULL;
00320    return NULL;
00321 }

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

Referenced by timesub().

01713 {
01714    return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
01715       -(leaps_thru_end_of(-(y + 1)) + 1);
01716 }

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

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

Referenced by ast_localtime(), and ast_mktime().

01457 {
01458    const struct ttinfo *   ttisp;
01459    int         i;
01460    struct ast_tm *      result;
01461    struct timeval t;
01462    memcpy(&t, timep, sizeof(t));
01463 
01464    if (sp == NULL)
01465       return gmtsub(timep, offset, tmp);
01466    if ((sp->goback && t.tv_sec < sp->ats[0]) ||
01467       (sp->goahead && t.tv_sec > sp->ats[sp->timecnt - 1])) {
01468          struct timeval newt = t;
01469          time_t      seconds;
01470          time_t      tcycles;
01471          int_fast64_t   icycles;
01472 
01473          if (t.tv_sec < sp->ats[0])
01474             seconds = sp->ats[0] - t.tv_sec;
01475          else  seconds = t.tv_sec - sp->ats[sp->timecnt - 1];
01476          --seconds;
01477          tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
01478          ++tcycles;
01479          icycles = tcycles;
01480          if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
01481             return NULL;
01482          seconds = icycles;
01483          seconds *= YEARSPERREPEAT;
01484          seconds *= AVGSECSPERYEAR;
01485          if (t.tv_sec < sp->ats[0])
01486             newt.tv_sec += seconds;
01487          else  newt.tv_sec -= seconds;
01488          if (newt.tv_sec < sp->ats[0] ||
01489             newt.tv_sec > sp->ats[sp->timecnt - 1])
01490                return NULL;   /* "cannot happen" */
01491          result = localsub(&newt, offset, tmp, sp);
01492          if (result == tmp) {
01493             time_t   newy;
01494 
01495             newy = tmp->tm_year;
01496             if (t.tv_sec < sp->ats[0])
01497                newy -= icycles * YEARSPERREPEAT;
01498             else
01499                newy += icycles * YEARSPERREPEAT;
01500             tmp->tm_year = newy;
01501             if (tmp->tm_year != newy)
01502                return NULL;
01503          }
01504          return result;
01505    }
01506    if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) {
01507       i = 0;
01508       while (sp->ttis[i].tt_isdst) {
01509          if (++i >= sp->typecnt) {
01510             i = 0;
01511             break;
01512          }
01513       }
01514    } else {
01515       int   lo = 1;
01516       int   hi = sp->timecnt;
01517 
01518       while (lo < hi) {
01519          int   mid = (lo + hi) >> 1;
01520 
01521          if (t.tv_sec < sp->ats[mid])
01522             hi = mid;
01523          else
01524             lo = mid + 1;
01525       }
01526       i = (int) sp->types[lo - 1];
01527    }
01528    ttisp = &sp->ttis[i];
01529    /*
01530    ** To get (wrong) behavior that's compatible with System V Release 2.0
01531    ** you'd replace the statement below with
01532    ** t += ttisp->tt_gmtoff;
01533    ** timesub(&t, 0L, sp, tmp);
01534    */
01535    result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
01536    tmp->tm_isdst = ttisp->tt_isdst;
01537 #ifndef SOLARIS /* Solaris doesn't have this element */
01538    tmp->tm_gmtoff = ttisp->tt_gmtoff;
01539 #endif
01540 #ifdef TM_ZONE
01541    tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
01542 #endif /* defined TM_ZONE */
01543    tmp->tm_usec = timep->tv_usec;
01544    return result;
01545 }

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

Definition at line 1865 of file localtime.c.

Referenced by long_normalize_overflow(), and time2sub().

01866 {
01867    long  number0;
01868 
01869    number0 = *number;
01870    *number += delta;
01871    return (*number < number0) != (delta < 0);
01872 }

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

Definition at line 1885 of file localtime.c.

References long_increment_overflow().

Referenced by time2sub().

01886 {
01887    int   tensdelta;
01888 
01889    tensdelta = (*unitsptr >= 0) ?
01890       (*unitsptr / base) :
01891       (-1 - (-1 - *unitsptr) / base);
01892    *unitsptr -= tensdelta * base;
01893    return long_increment_overflow(tensptr, tensdelta);
01894 }

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

Definition at line 1874 of file localtime.c.

References increment_overflow().

Referenced by time2sub().

01875 {
01876    int   tensdelta;
01877 
01878    tensdelta = (*unitsptr >= 0) ?
01879       (*unitsptr / base) :
01880       (-1 - (-1 - *unitsptr) / base);
01881    *unitsptr -= tensdelta * base;
01882    return increment_overflow(tensptr, tensdelta);
01883 }

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

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

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

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

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

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

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

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

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

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

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

static int leaps_thru_end_of P ( (int y)   )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

static const char* store_by_locale ( locale_t  prevlocale  )  [static]

Definition at line 2193 of file localtime.c.

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

Referenced by ast_setlocale().

02194 {
02195    struct locale_entry *cur;
02196    if (prevlocale == LC_GLOBAL_LOCALE) {
02197       return NULL;
02198    } else {
02199       /* Get a handle for this entry, if any */
02200       if ((cur = find_by_locale(prevlocale))) {
02201          return cur->name;
02202       } else {
02203          /* Create an entry, so it can be restored later */
02204          int x;
02205          cur = NULL;
02206          AST_LIST_LOCK(&localelist);
02207          for (x = 0; x < 10000; x++) {
02208             char name[5];
02209             snprintf(name, sizeof(name), "%04d", x);
02210             if (!find_by_name(name)) {
02211                if ((cur = ast_calloc(1, sizeof(*cur) + strlen(name) + 1))) {
02212                   cur->locale = prevlocale;
02213                   strcpy(cur->name, name); /* SAFE */
02214                   AST_LIST_INSERT_TAIL(&localelist, cur, list);
02215                }
02216                break;
02217             }
02218          }
02219          AST_LIST_UNLOCK(&localelist);
02220          return cur ? cur->name : NULL;
02221       }
02222    }
02223 }

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

References FALSE, time2(), state::timecnt, TRUE, state::typecnt, state::types, and TZ_MAX_TYPES.

Referenced by ast_mktime().

02098 {
02099    struct timeval       t;
02100    int         samei, otheri;
02101    int         sameind, otherind;
02102    int         i;
02103    int         nseen;
02104    int            seen[TZ_MAX_TYPES];
02105    int            types[TZ_MAX_TYPES];
02106    int            okay;
02107 
02108    if (tmp->tm_isdst > 1)
02109       tmp->tm_isdst = 1;
02110    t = time2(tmp, funcp, offset, &okay, sp);
02111 #ifdef PCTS
02112    /*
02113    ** PCTS code courtesy Grant Sullivan.
02114    */
02115    if (okay)
02116       return t;
02117    if (tmp->tm_isdst < 0)
02118       tmp->tm_isdst = 0;   /* reset to std and try again */
02119 #endif /* defined PCTS */
02120 #ifndef PCTS
02121    if (okay || tmp->tm_isdst < 0)
02122       return t;
02123 #endif /* !defined PCTS */
02124    /*
02125    ** We're supposed to assume that somebody took a time of one type
02126    ** and did some math on it that yielded a "struct ast_tm" that's bad.
02127    ** We try to divine the type they started from and adjust to the
02128    ** type they need.
02129    */
02130    if (sp == NULL)
02131       return WRONG;
02132    for (i = 0; i < sp->typecnt; ++i)
02133       seen[i] = FALSE;
02134    nseen = 0;
02135    for (i = sp->timecnt - 1; i >= 0; --i)
02136       if (!seen[sp->types[i]]) {
02137          seen[sp->types[i]] = TRUE;
02138          types[nseen++] = sp->types[i];
02139       }
02140    for (sameind = 0; sameind < nseen; ++sameind) {
02141       samei = types[sameind];
02142       if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
02143          continue;
02144       for (otherind = 0; otherind < nseen; ++otherind) {
02145          otheri = types[otherind];
02146          if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
02147             continue;
02148          tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
02149                sp->ttis[samei].tt_gmtoff;
02150          tmp->tm_isdst = !tmp->tm_isdst;
02151          t = time2(tmp, funcp, offset, &okay, sp);
02152          if (okay)
02153             return t;
02154          tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
02155                sp->ttis[samei].tt_gmtoff;
02156          tmp->tm_isdst = !tmp->tm_isdst;
02157       }
02158    }
02159    return WRONG;
02160 }

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]

Definition at line 2084 of file localtime.c.

References FALSE, time2sub(), and TRUE.

Referenced by time1().

02085 {
02086    struct timeval t;
02087 
02088    /*! \note
02089    ** First try without normalization of seconds
02090    ** (in case tm_sec contains a value associated with a leap second).
02091    ** If that fails, try with normalization of seconds.
02092    */
02093    t = time2sub(tmp, funcp, offset, okayp, FALSE, sp);
02094    return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp);
02095 }

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

References DAYSPERLYEAR, FALSE, HOURSPERDAY, isleap, long_increment_overflow(), long_normalize_overflow(), MINSPERHOUR, mon_lengths, MONSPERYEAR, normalize_overflow(), SECSPERMIN, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_year, TM_YEAR_BASE, and year_lengths.

Referenced by time2().

01911 {
01912    int         dir;
01913    int         i, j;
01914    int         saved_seconds;
01915    long        li;
01916    time_t         lo;
01917    time_t         hi;
01918    long           y;
01919    struct timeval       newt = { 0, 0 };
01920    struct timeval       t = { 0, 0 };
01921    struct ast_tm        yourtm, mytm;
01922 
01923    *okayp = FALSE;
01924    yourtm = *tmp;
01925    if (do_norm_secs) {
01926       if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
01927          SECSPERMIN))
01928             return WRONG;
01929    }
01930    if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
01931       return WRONG;
01932    if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
01933       return WRONG;
01934    y = yourtm.tm_year;
01935    if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
01936       return WRONG;
01937    /*
01938    ** Turn y into an actual year number for now.
01939    ** It is converted back to an offset from TM_YEAR_BASE later.
01940    */
01941    if (long_increment_overflow(&y, TM_YEAR_BASE))
01942       return WRONG;
01943    while (yourtm.tm_mday <= 0) {
01944       if (long_increment_overflow(&y, -1))
01945          return WRONG;
01946       li = y + (1 < yourtm.tm_mon);
01947       yourtm.tm_mday += year_lengths[isleap(li)];
01948    }
01949    while (yourtm.tm_mday > DAYSPERLYEAR) {
01950       li = y + (1 < yourtm.tm_mon);
01951       yourtm.tm_mday -= year_lengths[isleap(li)];
01952       if (long_increment_overflow(&y, 1))
01953          return WRONG;
01954    }
01955    for ( ; ; ) {
01956       i = mon_lengths[isleap(y)][yourtm.tm_mon];
01957       if (yourtm.tm_mday <= i)
01958          break;
01959       yourtm.tm_mday -= i;
01960       if (++yourtm.tm_mon >= MONSPERYEAR) {
01961          yourtm.tm_mon = 0;
01962          if (long_increment_overflow(&y, 1))
01963             return WRONG;
01964       }
01965    }
01966    if (long_increment_overflow(&y, -TM_YEAR_BASE))
01967       return WRONG;
01968    yourtm.tm_year = y;
01969    if (yourtm.tm_year != y)
01970       return WRONG;
01971    if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
01972       saved_seconds = 0;
01973    else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
01974       /*
01975       ** We can't set tm_sec to 0, because that might push the
01976       ** time below the minimum representable time.
01977       ** Set tm_sec to 59 instead.
01978       ** This assumes that the minimum representable time is
01979       ** not in the same minute that a leap second was deleted from,
01980       ** which is a safer assumption than using 58 would be.
01981       */
01982       if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
01983          return WRONG;
01984       saved_seconds = yourtm.tm_sec;
01985       yourtm.tm_sec = SECSPERMIN - 1;
01986    } else {
01987       saved_seconds = yourtm.tm_sec;
01988       yourtm.tm_sec = 0;
01989    }
01990    /*
01991    ** Do a binary search (this works whatever time_t's type is).
01992    */
01993    if (!TYPE_SIGNED(time_t)) {
01994       lo = 0;
01995       hi = lo - 1;
01996    } else if (!TYPE_INTEGRAL(time_t)) {
01997       if (sizeof(time_t) > sizeof(float))
01998          hi = (time_t) DBL_MAX;
01999       else  hi = (time_t) FLT_MAX;
02000       lo = -hi;
02001    } else {
02002       lo = 1;
02003       for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
02004          lo *= 2;
02005       hi = -(lo + 1);
02006    }
02007    for ( ; ; ) {
02008       t.tv_sec = lo / 2 + hi / 2;
02009       if (t.tv_sec < lo)
02010          t.tv_sec = lo;
02011       else if (t.tv_sec > hi)
02012          t.tv_sec = hi;
02013       if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
02014          /*
02015          ** Assume that t is too extreme to be represented in
02016          ** a struct ast_tm; arrange things so that it is less
02017          ** extreme on the next pass.
02018          */
02019          dir = (t.tv_sec > 0) ? 1 : -1;
02020       } else   dir = tmcomp(&mytm, &yourtm);
02021       if (dir != 0) {
02022          if (t.tv_sec == lo) {
02023             ++t.tv_sec;
02024             if (t.tv_sec <= lo)
02025                return WRONG;
02026             ++lo;
02027          } else if (t.tv_sec == hi) {
02028             --t.tv_sec;
02029             if (t.tv_sec >= hi)
02030                return WRONG;
02031             --hi;
02032          }
02033          if (lo > hi)
02034             return WRONG;
02035          if (dir > 0)
02036             hi = t.tv_sec;
02037          else  lo = t.tv_sec;
02038          continue;
02039       }
02040       if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
02041          break;
02042       /*
02043       ** Right time, wrong type.
02044       ** Hunt for right time, right type.
02045       ** It's okay to guess wrong since the guess
02046       ** gets checked.
02047       */
02048       /*
02049       ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
02050       */
02051       for (i = sp->typecnt - 1; i >= 0; --i) {
02052          if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
02053             continue;
02054          for (j = sp->typecnt - 1; j >= 0; --j) {
02055             if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
02056                continue;
02057             newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff -
02058                sp->ttis[i].tt_gmtoff;
02059             if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
02060                continue;
02061             if (tmcomp(&mytm, &yourtm) != 0)
02062                continue;
02063             if (mytm.tm_isdst != yourtm.tm_isdst)
02064                continue;
02065             /*
02066             ** We have a match.
02067             */
02068             t = newt;
02069             goto label;
02070          }
02071       }
02072       return WRONG;
02073    }
02074 label:
02075    newt.tv_sec = t.tv_sec + saved_seconds;
02076    if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0))
02077       return WRONG;
02078    t.tv_sec = newt.tv_sec;
02079    if ((*funcp)(&t, offset, tmp, sp))
02080       *okayp = TRUE;
02081    return t;
02082 }

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

Definition at line 1718 of file localtime.c.

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

Referenced by gmtsub(), and localsub().

01719 {
01720    const struct lsinfo *   lp;
01721    time_t         tdays;
01722    int         idays;   /* unsigned would be so 2003 */
01723    long        rem;
01724    int            y;
01725    const int *    ip;
01726    long        corr;
01727    int         hit;
01728    int         i;
01729    long  seconds;
01730 
01731 
01732    corr = 0;
01733    hit = 0;
01734    i = (sp == NULL) ? 0 : sp->leapcnt;
01735    while (--i >= 0) {
01736       lp = &sp->lsis[i];
01737       if (timep->tv_sec >= lp->ls_trans) {
01738          if (timep->tv_sec == lp->ls_trans) {
01739             hit = ((i == 0 && lp->ls_corr > 0) ||
01740                lp->ls_corr > sp->lsis[i - 1].ls_corr);
01741             if (hit)
01742                while (i > 0 &&
01743                   sp->lsis[i].ls_trans ==
01744                   sp->lsis[i - 1].ls_trans + 1 &&
01745                   sp->lsis[i].ls_corr ==
01746                   sp->lsis[i - 1].ls_corr + 1) {
01747                      ++hit;
01748                      --i;
01749                }
01750          }
01751          corr = lp->ls_corr;
01752          break;
01753       }
01754    }
01755    y = EPOCH_YEAR;
01756    tdays = timep->tv_sec / SECSPERDAY;
01757    rem = timep->tv_sec - tdays * SECSPERDAY;
01758    while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
01759       int      newy;
01760       time_t   tdelta;
01761       int   idelta;
01762       int   leapdays;
01763 
01764       tdelta = tdays / DAYSPERLYEAR;
01765       idelta = tdelta;
01766       if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
01767          return NULL;
01768       if (idelta == 0)
01769          idelta = (tdays < 0) ? -1 : 1;
01770       newy = y;
01771       if (increment_overflow(&newy, idelta))
01772          return NULL;
01773       leapdays = leaps_thru_end_of(newy - 1) -
01774          leaps_thru_end_of(y - 1);
01775       tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
01776       tdays -= leapdays;
01777       y = newy;
01778    }
01779 
01780    seconds = tdays * SECSPERDAY + 0.5;
01781    tdays = seconds / SECSPERDAY;
01782    rem += seconds - tdays * SECSPERDAY;
01783 
01784    /*
01785    ** Given the range, we can now fearlessly cast...
01786    */
01787    idays = tdays;
01788    rem += offset - corr;
01789    while (rem < 0) {
01790       rem += SECSPERDAY;
01791       --idays;
01792    }
01793    while (rem >= SECSPERDAY) {
01794       rem -= SECSPERDAY;
01795       ++idays;
01796    }
01797    while (idays < 0) {
01798       if (increment_overflow(&y, -1))
01799          return NULL;
01800       idays += year_lengths[isleap(y)];
01801    }
01802    while (idays >= year_lengths[isleap(y)]) {
01803       idays -= year_lengths[isleap(y)];
01804       if (increment_overflow(&y, 1))
01805          return NULL;
01806    }
01807    tmp->tm_year = y;
01808    if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
01809       return NULL;
01810    tmp->tm_yday = idays;
01811    /*
01812    ** The "extra" mods below avoid overflow problems.
01813    */
01814    tmp->tm_wday = EPOCH_WDAY +
01815       ((y - EPOCH_YEAR) % DAYSPERWEEK) *
01816       (DAYSPERNYEAR % DAYSPERWEEK) +
01817       leaps_thru_end_of(y - 1) -
01818       leaps_thru_end_of(EPOCH_YEAR - 1) +
01819       idays;
01820    tmp->tm_wday %= DAYSPERWEEK;
01821    if (tmp->tm_wday < 0)
01822       tmp->tm_wday += DAYSPERWEEK;
01823    tmp->tm_hour = (int) (rem / SECSPERHOUR);
01824    rem %= SECSPERHOUR;
01825    tmp->tm_min = (int) (rem / SECSPERMIN);
01826    /*
01827    ** A positive leap second requires a special
01828    ** representation. This uses "... ??:59:60" et seq.
01829    */
01830    tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
01831    ip = mon_lengths[isleap(y)];
01832    for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
01833       idays -= ip[tmp->tm_mon];
01834    tmp->tm_mday = (int) (idays + 1);
01835    tmp->tm_isdst = 0;
01836 #ifdef TM_GMTOFF
01837    tmp->TM_GMTOFF = offset;
01838 #endif /* defined TM_GMTOFF */
01839    tmp->tm_usec = timep->tv_usec;
01840    return tmp;
01841 }

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

Definition at line 1896 of file localtime.c.

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

01897 {
01898    int   result;
01899 
01900    if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
01901       (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
01902       (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
01903       (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
01904       (result = (atmp->tm_min - btmp->tm_min)) == 0 &&
01905       (result = (atmp->tm_sec - btmp->tm_sec)) == 0)
01906          result = atmp->tm_usec - btmp->tm_usec;
01907    return result;
01908 }

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

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

Referenced by tzparse().

01081 {
01082    int   leapyear;
01083    time_t   value;
01084    int   i;
01085    int      d, m1, yy0, yy1, yy2, dow;
01086 
01087    INITIALIZE(value);
01088    leapyear = isleap(year);
01089    switch (rulep->r_type) {
01090 
01091    case JULIAN_DAY:
01092       /*
01093       ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
01094       ** years.
01095       ** In non-leap years, or if the day number is 59 or less, just
01096       ** add SECSPERDAY times the day number-1 to the time of
01097       ** January 1, midnight, to get the day.
01098       */
01099       value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
01100       if (leapyear && rulep->r_day >= 60)
01101          value += SECSPERDAY;
01102       break;
01103 
01104    case DAY_OF_YEAR:
01105       /*
01106       ** n - day of year.
01107       ** Just add SECSPERDAY times the day number to the time of
01108       ** January 1, midnight, to get the day.
01109       */
01110       value = janfirst + rulep->r_day * SECSPERDAY;
01111       break;
01112 
01113    case MONTH_NTH_DAY_OF_WEEK:
01114       /*
01115       ** Mm.n.d - nth "dth day" of month m.
01116       */
01117       value = janfirst;
01118       for (i = 0; i < rulep->r_mon - 1; ++i)
01119          value += mon_lengths[leapyear][i] * SECSPERDAY;
01120 
01121       /*
01122       ** Use Zeller's Congruence to get day-of-week of first day of
01123       ** month.
01124       */
01125       m1 = (rulep->r_mon + 9) % 12 + 1;
01126       yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
01127       yy1 = yy0 / 100;
01128       yy2 = yy0 % 100;
01129       dow = ((26 * m1 - 2) / 10 +
01130          1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
01131       if (dow < 0)
01132          dow += DAYSPERWEEK;
01133 
01134       /*
01135       ** "dow" is the day-of-week of the first day of the month. Get
01136       ** the day-of-month (zero-origin) of the first "dow" day of the
01137       ** month.
01138       */
01139       d = rulep->r_day - dow;
01140       if (d < 0)
01141          d += DAYSPERWEEK;
01142       for (i = 1; i < rulep->r_week; ++i) {
01143          if (d + DAYSPERWEEK >=
01144             mon_lengths[leapyear][rulep->r_mon - 1])
01145                break;
01146          d += DAYSPERWEEK;
01147       }
01148 
01149       /*
01150       ** "d" is the day-of-month (zero-origin) of the day we want.
01151       */
01152       value += d * SECSPERDAY;
01153       break;
01154    }
01155 
01156    /*
01157    ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
01158    ** question. To get the Epoch-relative time of the specified local
01159    ** time on that day, add the transition time and the current offset
01160    ** from UTC.
01161    */
01162    return value + rulep->r_time + offset;
01163 }

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

Definition at line 657 of file localtime.c.

References add_notify(), state::ats, state::charcnt, state::chars, detzcode(), detzcode64(), FALSE, FILENAME_MAX, state::leapcnt, lsinfo::ls_trans, state::lsis, OPEN_MODE, state::timecnt, TRUE, ttinfo::tt_gmtoff, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, state::ttis, state::typecnt, state::types, TZ_MAX_CHARS, TZ_MAX_LEAPS, TZ_MAX_TIMES, TZ_MAX_TYPES, TZDEFAULT, and TZDIR.

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

00658 {
00659    const char *      p;
00660    int         i;
00661    int         fid;
00662    int         stored;
00663    int         nread;
00664    union {
00665       struct tzhead  tzhead;
00666       char     buf[2 * sizeof(struct tzhead) +
00667                2 * sizeof *sp +
00668                4 * TZ_MAX_TIMES];
00669    } u;
00670 
00671    if (name == NULL && (name = TZDEFAULT) == NULL)
00672       return -1;
00673    {
00674       int   doaccess;
00675       /*
00676       ** Section 4.9.1 of the C standard says that
00677       ** "FILENAME_MAX expands to an integral constant expression
00678       ** that is the size needed for an array of char large enough
00679       ** to hold the longest file name string that the implementation
00680       ** guarantees can be opened."
00681       */
00682       char     fullname[FILENAME_MAX + 1];
00683 
00684       if (name[0] == ':')
00685          ++name;
00686       doaccess = name[0] == '/';
00687       if (!doaccess) {
00688          if ((p = TZDIR) == NULL)
00689             return -1;
00690          if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
00691             return -1;
00692          (void) strcpy(fullname, p);
00693          (void) strcat(fullname, "/");
00694          (void) strcat(fullname, name);
00695          /*
00696          ** Set doaccess if '.' (as in "../") shows up in name.
00697          */
00698          if (strchr(name, '.') != NULL)
00699             doaccess = TRUE;
00700          name = fullname;
00701       }
00702       if (doaccess && access(name, R_OK) != 0)
00703          return -1;
00704       if ((fid = open(name, OPEN_MODE)) == -1)
00705          return -1;
00706       add_notify(sp, name);
00707    }
00708    nread = read(fid, u.buf, sizeof u.buf);
00709    if (close(fid) < 0 || nread <= 0)
00710       return -1;
00711    for (stored = 4; stored <= 8; stored *= 2) {
00712       int      ttisstdcnt;
00713       int      ttisgmtcnt;
00714 
00715       ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
00716       ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
00717       sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
00718       sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
00719       sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
00720       sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
00721       p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
00722       if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
00723          sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
00724          sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
00725          sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
00726          (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
00727          (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
00728             return -1;
00729       if (nread - (p - u.buf) <
00730          sp->timecnt * stored +     /* ats */
00731          sp->timecnt +        /* types */
00732          sp->typecnt * 6 +    /* ttinfos */
00733          sp->charcnt +        /* chars */
00734          sp->leapcnt * (stored + 4) +  /* lsinfos */
00735          ttisstdcnt +         /* ttisstds */
00736          ttisgmtcnt)       /* ttisgmts */
00737             return -1;
00738       for (i = 0; i < sp->timecnt; ++i) {
00739          sp->ats[i] = (stored == 4) ?
00740             detzcode(p) : detzcode64(p);
00741          p += stored;
00742       }
00743       for (i = 0; i < sp->timecnt; ++i) {
00744          sp->types[i] = (unsigned char) *p++;
00745          if (sp->types[i] >= sp->typecnt)
00746             return -1;
00747       }
00748       for (i = 0; i < sp->typecnt; ++i) {
00749          struct ttinfo *   ttisp;
00750 
00751          ttisp = &sp->ttis[i];
00752          ttisp->tt_gmtoff = detzcode(p);
00753          p += 4;
00754          ttisp->tt_isdst = (unsigned char) *p++;
00755          if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
00756             return -1;
00757          ttisp->tt_abbrind = (unsigned char) *p++;
00758          if (ttisp->tt_abbrind < 0 ||
00759             ttisp->tt_abbrind > sp->charcnt)
00760                return -1;
00761       }
00762       for (i = 0; i < sp->charcnt; ++i)
00763          sp->chars[i] = *p++;
00764       sp->chars[i] = '\0'; /* ensure '\0' at end */
00765       for (i = 0; i < sp->leapcnt; ++i) {
00766          struct lsinfo *   lsisp;
00767 
00768          lsisp = &sp->lsis[i];
00769          lsisp->ls_trans = (stored == 4) ?
00770             detzcode(p) : detzcode64(p);
00771          p += stored;
00772          lsisp->ls_corr = detzcode(p);
00773          p += 4;
00774       }
00775       for (i = 0; i < sp->typecnt; ++i) {
00776          struct ttinfo *   ttisp;
00777 
00778          ttisp = &sp->ttis[i];
00779          if (ttisstdcnt == 0)
00780             ttisp->tt_ttisstd = FALSE;
00781          else {
00782             ttisp->tt_ttisstd = *p++;
00783             if (ttisp->tt_ttisstd != TRUE &&
00784                ttisp->tt_ttisstd != FALSE)
00785                   return -1;
00786          }
00787       }
00788       for (i = 0; i < sp->typecnt; ++i) {
00789          struct ttinfo *   ttisp;
00790 
00791          ttisp = &sp->ttis[i];
00792          if (ttisgmtcnt == 0)
00793             ttisp->tt_ttisgmt = FALSE;
00794          else {
00795             ttisp->tt_ttisgmt = *p++;
00796             if (ttisp->tt_ttisgmt != TRUE &&
00797                ttisp->tt_ttisgmt != FALSE)
00798                   return -1;
00799          }
00800       }
00801       /*
00802       ** Out-of-sort ats should mean we're running on a
00803       ** signed time_t system but using a data file with
00804       ** unsigned values (or vice versa).
00805       */
00806       for (i = 0; i < sp->timecnt - 2; ++i)
00807          if (sp->ats[i] > sp->ats[i + 1]) {
00808             ++i;
00809             if (TYPE_SIGNED(time_t)) {
00810                /*
00811                ** Ignore the end (easy).
00812                */
00813                sp->timecnt = i;
00814             } else {
00815                /*
00816                ** Ignore the beginning (harder).
00817                */
00818                int   j;
00819 
00820                for (j = 0; j + i < sp->timecnt; ++j) {
00821                   sp->ats[j] = sp->ats[j + i];
00822                   sp->types[j] = sp->types[j + i];
00823                }
00824                sp->timecnt = j;
00825             }
00826             break;
00827          }
00828       /*
00829       ** If this is an old file, we're done.
00830       */
00831       if (u.tzhead.tzh_version[0] == '\0')
00832          break;
00833       nread -= p - u.buf;
00834       for (i = 0; i < nread; ++i)
00835          u.buf[i] = p[i];
00836       /*
00837       ** If this is a narrow integer time_t system, we're done.
00838       */
00839       if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
00840          break;
00841    }
00842    if (doextend && nread > 2 &&
00843       u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
00844       sp->typecnt + 2 <= TZ_MAX_TYPES) {
00845          struct state   ts;
00846          int   result;
00847 
00848          u.buf[nread - 1] = '\0';
00849          result = tzparse(&u.buf[1], &ts, FALSE);
00850          if (result == 0 && ts.typecnt == 2 &&
00851             sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
00852                for (i = 0; i < 2; ++i)
00853                   ts.ttis[i].tt_abbrind +=
00854                      sp->charcnt;
00855                for (i = 0; i < ts.charcnt; ++i)
00856                   sp->chars[sp->charcnt++] =
00857                      ts.chars[i];
00858                i = 0;
00859                while (i < ts.timecnt &&
00860                   ts.ats[i] <=
00861                   sp->ats[sp->timecnt - 1])
00862                      ++i;
00863                while (i < ts.timecnt &&
00864                    sp->timecnt < TZ_MAX_TIMES) {
00865                   sp->ats[sp->timecnt] =
00866                      ts.ats[i];
00867                   sp->types[sp->timecnt] =
00868                      sp->typecnt +
00869                      ts.types[i];
00870                   ++sp->timecnt;
00871                   ++i;
00872                }
00873                sp->ttis[sp->typecnt++] = ts.ttis[0];
00874                sp->ttis[sp->typecnt++] = ts.ttis[1];
00875          }
00876    }
00877    i = 2 * YEARSPERREPEAT;
00878    sp->goback = sp->goahead = sp->timecnt > i;
00879    sp->goback = sp->goback && sp->types[i] == sp->types[0] &&
00880       differ_by_repeat(sp->ats[i], sp->ats[0]);
00881    sp->goahead = sp->goahead &&
00882       sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] &&
00883       differ_by_repeat(sp->ats[sp->timecnt - 1],
00884           sp->ats[sp->timecnt - 1 - i]);
00885    return 0;
00886 }

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

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

Referenced by ast_tzset(), and gmtload().

01171 {
01172    const char *         stdname;
01173    const char *         dstname;
01174    size_t            stdlen;
01175    size_t            dstlen;
01176    long           stdoffset;
01177    long           dstoffset;
01178    time_t *    atp;
01179    unsigned char *   typep;
01180    char *         cp;
01181    int         load_result;
01182 
01183    INITIALIZE(dstname);
01184    stdname = name;
01185    if (lastditch) {
01186       stdlen = strlen(name);  /* length of standard zone name */
01187       name += stdlen;
01188       if (stdlen >= sizeof sp->chars)
01189          stdlen = (sizeof sp->chars) - 1;
01190       stdoffset = 0;
01191    } else {
01192       if (*name == '<') {
01193          name++;
01194          stdname = name;
01195          name = getqzname(name, '>');
01196          if (*name != '>')
01197             return -1;
01198          stdlen = name - stdname;
01199          name++;
01200       } else {
01201          name = getzname(name);
01202          stdlen = name - stdname;
01203       }
01204       if (*name == '\0')
01205          return -1;
01206       name = getoffset(name, &stdoffset);
01207       if (name == NULL)
01208          return -1;
01209    }
01210    load_result = tzload(TZDEFRULES, sp, FALSE);
01211    if (load_result != 0)
01212       sp->leapcnt = 0;     /* so, we're off a little */
01213    if (*name != '\0') {
01214       if (*name == '<') {
01215          dstname = ++name;
01216          name = getqzname(name, '>');
01217          if (*name != '>')
01218             return -1;
01219          dstlen = name - dstname;
01220          name++;
01221       } else {
01222          dstname = name;
01223          name = getzname(name);
01224          dstlen = name - dstname; /* length of DST zone name */
01225       }
01226       if (*name != '\0' && *name != ',' && *name != ';') {
01227          name = getoffset(name, &dstoffset);
01228          if (name == NULL)
01229             return -1;
01230       } else   dstoffset = stdoffset - SECSPERHOUR;
01231       if (*name == '\0' && load_result != 0)
01232          name = TZDEFRULESTRING;
01233       if (*name == ',' || *name == ';') {
01234          struct rule start;
01235          struct rule end;
01236          int   year;
01237          time_t   janfirst;
01238          time_t      starttime;
01239          time_t      endtime;
01240 
01241          ++name;
01242          if ((name = getrule(name, &start)) == NULL)
01243             return -1;
01244          if (*name++ != ',')
01245             return -1;
01246          if ((name = getrule(name, &end)) == NULL)
01247             return -1;
01248          if (*name != '\0')
01249             return -1;
01250          sp->typecnt = 2;  /* standard time and DST */
01251          /*
01252          ** Two transitions per year, from EPOCH_YEAR forward.
01253          */
01254          sp->ttis[0].tt_gmtoff = -dstoffset;
01255          sp->ttis[0].tt_isdst = 1;
01256          sp->ttis[0].tt_abbrind = stdlen + 1;
01257          sp->ttis[1].tt_gmtoff = -stdoffset;
01258          sp->ttis[1].tt_isdst = 0;
01259          sp->ttis[1].tt_abbrind = 0;
01260          atp = sp->ats;
01261          typep = sp->types;
01262          janfirst = 0;
01263          sp->timecnt = 0;
01264          for (year = EPOCH_YEAR;
01265              sp->timecnt + 2 <= TZ_MAX_TIMES;
01266              ++year) {
01267                time_t   newfirst;
01268 
01269             starttime = transtime(janfirst, year, &start,
01270                stdoffset);
01271             endtime = transtime(janfirst, year, &end,
01272                dstoffset);
01273             if (starttime > endtime) {
01274                *atp++ = endtime;
01275                *typep++ = 1;  /* DST ends */
01276                *atp++ = starttime;
01277                *typep++ = 0;  /* DST begins */
01278             } else {
01279                *atp++ = starttime;
01280                *typep++ = 0;  /* DST begins */
01281                *atp++ = endtime;
01282                *typep++ = 1;  /* DST ends */
01283             }
01284             sp->timecnt += 2;
01285             newfirst = janfirst;
01286             newfirst += year_lengths[isleap(year)] *
01287                SECSPERDAY;
01288             if (newfirst <= janfirst)
01289                break;
01290             janfirst = newfirst;
01291          }
01292       } else {
01293          long  theirstdoffset;
01294          long  theirdstoffset;
01295          long  theiroffset;
01296          int   isdst;
01297          int   i;
01298          int   j;
01299 
01300          if (*name != '\0')
01301             return -1;
01302          /*
01303          ** Initial values of theirstdoffset and theirdstoffset.
01304          */
01305          theirstdoffset = 0;
01306          for (i = 0; i < sp->timecnt; ++i) {
01307             j = sp->types[i];
01308             if (!sp->ttis[j].tt_isdst) {
01309                theirstdoffset =
01310                   -sp->ttis[j].tt_gmtoff;
01311                break;
01312             }
01313          }
01314          theirdstoffset = 0;
01315          for (i = 0; i < sp->timecnt; ++i) {
01316             j = sp->types[i];
01317             if (sp->ttis[j].tt_isdst) {
01318                theirdstoffset =
01319                   -sp->ttis[j].tt_gmtoff;
01320                break;
01321             }
01322          }
01323          /*
01324          ** Initially we're assumed to be in standard time.
01325          */
01326          isdst = FALSE;
01327          theiroffset = theirstdoffset;
01328          /*
01329          ** Now juggle transition times and types
01330          ** tracking offsets as you do.
01331          */
01332          for (i = 0; i < sp->timecnt; ++i) {
01333             j = sp->types[i];
01334             sp->types[i] = sp->ttis[j].tt_isdst;
01335             if (sp->ttis[j].tt_ttisgmt) {
01336                /* No adjustment to transition time */
01337             } else {
01338                /*
01339                ** If summer time is in effect, and the
01340                ** transition time was not specified as
01341                ** standard time, add the summer time
01342                ** offset to the transition time;
01343                ** otherwise, add the standard time
01344                ** offset to the transition time.
01345                */
01346                /*
01347                ** Transitions from DST to DDST
01348                ** will effectively disappear since
01349                ** POSIX provides for only one DST
01350                ** offset.
01351                */
01352                if (isdst && !sp->ttis[j].tt_ttisstd) {
01353                   sp->ats[i] += dstoffset -
01354                      theirdstoffset;
01355                } else {
01356                   sp->ats[i] += stdoffset -
01357                      theirstdoffset;
01358                }
01359             }
01360             theiroffset = -sp->ttis[j].tt_gmtoff;
01361             if (sp->ttis[j].tt_isdst)
01362                theirdstoffset = theiroffset;
01363             else  theirstdoffset = theiroffset;
01364          }
01365          /*
01366          ** Finally, fill in ttis.
01367          ** ttisstd and ttisgmt need not be handled.
01368          */
01369          sp->ttis[0].tt_gmtoff = -stdoffset;
01370          sp->ttis[0].tt_isdst = FALSE;
01371          sp->ttis[0].tt_abbrind = 0;
01372          sp->ttis[1].tt_gmtoff = -dstoffset;
01373          sp->ttis[1].tt_isdst = TRUE;
01374          sp->ttis[1].tt_abbrind = stdlen + 1;
01375          sp->typecnt = 2;
01376       }
01377    } else {
01378       dstlen = 0;
01379       sp->typecnt = 1;     /* only standard time */
01380       sp->timecnt = 0;
01381       sp->ttis[0].tt_gmtoff = -stdoffset;
01382       sp->ttis[0].tt_isdst = 0;
01383       sp->ttis[0].tt_abbrind = 0;
01384    }
01385    sp->charcnt = stdlen + 1;
01386    if (dstlen != 0)
01387       sp->charcnt += dstlen + 1;
01388    if ((size_t) sp->charcnt > sizeof sp->chars)
01389       return -1;
01390    cp = sp->chars;
01391    (void) strncpy(cp, stdname, stdlen);
01392    cp += stdlen;
01393    *cp++ = '\0';
01394    if (dstlen != 0) {
01395       (void) strncpy(cp, dstname, dstlen);
01396       *(cp + dstlen) = '\0';
01397    }
01398    return 0;
01399 }


Variable Documentation

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

Definition at line 79 of file localtime.c.

const char gmt[] = "GMT" [static]

Definition at line 107 of file localtime.c.

ast_cond_t initialization [static]

Definition at line 262 of file localtime.c.

Referenced by add_notify(), and ast_localtime_wakeup_monitor().

ast_mutex_t initialization_lock [static]

Definition at line 263 of file localtime.c.

Referenced by add_notify(), and inotify_daemon().

int inotify_fd = -1 [static]

Definition at line 265 of file localtime.c.

Referenced by add_notify(), and scan_thread().

pthread_t inotify_thread = AST_PTHREADT_NULL [static]

Definition at line 261 of file localtime.c.

Referenced by add_notify(), and ast_localtime_wakeup_monitor().

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

Referenced by time2sub(), and timesub().

struct timeval WRONG = { 0, 0 } [static]

Definition at line 108 of file localtime.c.

const int year_lengths[2] [static]

Initial value:

Definition at line 893 of file localtime.c.

Referenced by time2sub(), and timesub().


Generated on Sat Mar 10 01:55:29 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7