#include "asterisk.h"
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <float.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include "private.h"
#include "tzfile.h"
#include "asterisk/_private.h"
#include "asterisk/lock.h"
#include "asterisk/localtime.h"
#include "asterisk/strings.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/test.h"
Go to the source code of this file.
Data Structures | |
struct | locale_entry |
struct | localelist |
struct | lsinfo |
leap second information More... | |
struct | rule |
struct | state |
struct | ttinfo |
time type information More... | |
struct | zonelist |
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) |
struct ast_tm * | ast_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) |
struct 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 state * | ast_tzset (const char *zone) |
void | clean_time_zones (void) |
static long | detzcode (const char *const codep) |
static time_t | detzcode64 (const char *const codep) |
static int | differ_by_repeat (const time_t t1, const time_t t0) |
static struct locale_entry * | find_by_locale (locale_t locale) |
static struct locale_entry * | find_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_tm * | gmtsub (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_tm * | localsub (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_tm * | timesub (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] |
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 BIGGEST | ( | a, | |||
b | ) | (((a) > (b)) ? (a) : (b)) |
Definition at line 148 of file localtime.c.
#define DAY_OF_YEAR 1 |
Definition at line 205 of file localtime.c.
Referenced by getrule(), and transtime().
#define JULIAN_DAY 0 |
Definition at line 204 of file localtime.c.
Referenced by getrule(), and transtime().
#define MONTH_NTH_DAY_OF_WEEK 2 |
Definition at line 206 of file localtime.c.
Referenced by getrule(), and transtime().
#define MY_TZNAME_MAX 255 |
Definition at line 154 of file localtime.c.
#define OPEN_MODE O_RDONLY |
Definition at line 109 of file localtime.c.
Referenced by tzload().
#define TZ_ABBR_CHAR_SET "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" |
Definition at line 93 of file localtime.c.
#define TZ_ABBR_ERR_CHAR '_' |
Definition at line 98 of file localtime.c.
#define TZ_ABBR_MAX_LEN 16 |
Definition at line 89 of file localtime.c.
#define TZ_STRLEN_MAX 255 |
Definition at line 157 of file localtime.c.
#define TZDEFRULESTRING ",M4.1.0,M10.5.0" |
Definition at line 130 of file localtime.c.
Referenced by tzparse().
static void add_notify | ( | struct state * | sp, | |
const char * | path | |||
) | [static] |
Definition at line 328 of file localtime.c.
References ast_cond_init, ast_cond_wait, ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, FILENAME_MAX, inotify_daemon(), and state::wd.
Referenced by tzload().
00329 { 00330 if (inotify_thread == AST_PTHREADT_NULL) { 00331 ast_cond_init(&initialization, NULL); 00332 ast_mutex_init(&initialization_lock); 00333 ast_mutex_lock(&initialization_lock); 00334 if (!(ast_pthread_create_background(&inotify_thread, NULL, inotify_daemon, NULL))) { 00335 /* Give the thread a chance to initialize */ 00336 ast_cond_wait(&initialization, &initialization_lock); 00337 } else { 00338 fprintf(stderr, "Unable to start notification thread\n"); 00339 ast_mutex_unlock(&initialization_lock); 00340 return; 00341 } 00342 ast_mutex_unlock(&initialization_lock); 00343 } 00344 00345 if (inotify_fd > -1) { 00346 char fullpath[FILENAME_MAX + 1] = ""; 00347 if (readlink(path, fullpath, sizeof(fullpath) - 1) != -1) { 00348 /* If file the symlink points to changes */ 00349 sp->wd[1] = inotify_add_watch(inotify_fd, fullpath, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE ); 00350 } else { 00351 sp->wd[1] = -1; 00352 } 00353 /* or if the symlink itself changes (or the real file is here, if path is not a symlink) */ 00354 sp->wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE 00355 #ifdef IN_DONT_FOLLOW /* Only defined in glibc 2.5 and above */ 00356 | IN_DONT_FOLLOW 00357 #endif 00358 ); 00359 } 00360 }
void ast_get_dst_info | ( | const time_t *const | timep, | |
int * | dst_enabled, | |||
time_t * | dst_start, | |||
time_t * | dst_end, | |||
int * | gmt_off, | |||
const char *const | zone | |||
) |
Definition at line 1585 of file localtime.c.
References ast_tzset(), state::ats, AVGSECSPERYEAR, state::goahead, state::goback, int_fast64_t, state::timecnt, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.
Referenced by set_timezone_variables().
01586 { 01587 int i; 01588 int transition1 = -1; 01589 int transition2 = -1; 01590 time_t seconds; 01591 int bounds_exceeded = 0; 01592 time_t t = *timep; 01593 const struct state *sp; 01594 01595 if (NULL == dst_enabled) 01596 return; 01597 *dst_enabled = 0; 01598 01599 if (NULL == dst_start || NULL == dst_end || NULL == gmt_off) 01600 return; 01601 01602 *gmt_off = 0; 01603 01604 sp = ast_tzset(zone); 01605 if (NULL == sp) 01606 return; 01607 01608 /* If the desired time exceeds the bounds of the defined time transitions 01609 * then give give up on determining DST info and simply look for gmt offset 01610 * This requires that I adjust the given time using increments of Gregorian 01611 * repeats to place the time within the defined time transitions in the 01612 * timezone structure. 01613 */ 01614 if ((sp->goback && t < sp->ats[0]) || 01615 (sp->goahead && t > sp->ats[sp->timecnt - 1])) { 01616 time_t tcycles; 01617 int_fast64_t icycles; 01618 01619 if (t < sp->ats[0]) 01620 seconds = sp->ats[0] - t; 01621 else seconds = t - sp->ats[sp->timecnt - 1]; 01622 --seconds; 01623 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; 01624 ++tcycles; 01625 icycles = tcycles; 01626 if (tcycles - icycles >= 1 || icycles - tcycles >= 1) 01627 return; 01628 seconds = icycles; 01629 seconds *= YEARSPERREPEAT; 01630 seconds *= AVGSECSPERYEAR; 01631 if (t < sp->ats[0]) 01632 t += seconds; 01633 else 01634 t -= seconds; 01635 01636 if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1]) 01637 return; /* "cannot happen" */ 01638 01639 bounds_exceeded = 1; 01640 } 01641 01642 if (sp->timecnt == 0 || t < sp->ats[0]) { 01643 /* I have no transition times or I'm before time */ 01644 *dst_enabled = 0; 01645 /* Find where I can get gmtoff */ 01646 i = 0; 01647 while (sp->ttis[i].tt_isdst) 01648 if (++i >= sp->typecnt) { 01649 i = 0; 01650 break; 01651 } 01652 *gmt_off = sp->ttis[i].tt_gmtoff; 01653 return; 01654 } 01655 01656 for (i = 1; i < sp->timecnt; ++i) { 01657 if (t < sp->ats[i]) { 01658 transition1 = sp->types[i - 1]; 01659 transition2 = sp->types[i]; 01660 break; 01661 } 01662 } 01663 /* if I found transition times that do not bounded the given time and these correspond to 01664 or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */ 01665 if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 || 01666 (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) { 01667 *dst_enabled = 0; 01668 *gmt_off = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff; 01669 } else { 01670 /* I have valid daylight savings information. */ 01671 if(sp->ttis[transition2].tt_isdst) 01672 *gmt_off = sp->ttis[transition1].tt_gmtoff; 01673 else 01674 *gmt_off = sp->ttis[transition2].tt_gmtoff; 01675 01676 /* If I adjusted the time earlier, indicate that the dst is invalid */ 01677 if (!bounds_exceeded) { 01678 *dst_enabled = 1; 01679 /* Determine which of the bounds is the start of daylight savings and which is the end */ 01680 if(sp->ttis[transition2].tt_isdst) { 01681 *dst_start = sp->ats[i]; 01682 *dst_end = sp->ats[i -1]; 01683 } else { 01684 *dst_start = sp->ats[i -1]; 01685 *dst_end = sp->ats[i]; 01686 } 01687 } 01688 } 01689 return; 01690 }
struct ast_tm* ast_localtime | ( | const struct timeval * | timep, | |
struct ast_tm * | p_tm, | |||
const char * | zone | |||
) | [read] |
Timezone-independent version of localtime_r(3).
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. |
p_tm | is returned for convenience |
Definition at line 1570 of file localtime.c.
References ast_tzset(), and localsub().
Referenced by __ast_verbose_ap(), acf_strftime(), action_corestatus(), append_date(), ast_cel_fabricate_channel_from_event(), ast_check_timing2(), ast_http_send(), ast_log(), ast_queue_log(), ast_say_date_da(), ast_say_date_de(), ast_say_date_en(), ast_say_date_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(), 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().
void ast_localtime_wakeup_monitor | ( | struct ast_test * | info | ) |
Definition at line 607 of file localtime.c.
References ast_cond_wait, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, and lock.
00608 { 00609 if (inotify_thread != AST_PTHREADT_NULL) { 00610 AST_LIST_LOCK(&zonelist); 00611 #ifdef TEST_FRAMEWORK 00612 test = info; 00613 #endif 00614 pthread_kill(inotify_thread, SIGURG); 00615 ast_cond_wait(&initialization, &(&zonelist)->lock); 00616 #ifdef TEST_FRAMEWORK 00617 test = NULL; 00618 #endif 00619 AST_LIST_UNLOCK(&zonelist); 00620 } 00621 }
struct timeval ast_mktime | ( | struct ast_tm *const | tmp, | |
const char * | zone | |||
) | [read] |
Timezone-independent version of mktime(3).
tmp | Current broken-out time, including microseconds | |
zone | Text string of a standard system zoneinfo file. If NULL, the system localtime will be used. |
A | structure containing both seconds and fractional thereof since January 1st, 1970 UTC |
Definition at line 2185 of file localtime.c.
References ast_tzset(), localsub(), and time1().
Referenced by acf_strptime(), conf_run(), find_conf_realtime(), icalfloat_to_timet(), mstime_to_time_t(), rt_extend_conf(), sms_handleincoming_proto2(), sms_readfile(), testtime_write(), and unpackdate().
const char* ast_setlocale | ( | const char * | locale | ) |
Set the thread-local representation of the current locale.
Definition at line 2248 of file localtime.c.
References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, find_by_name(), locale_entry::locale, locale_entry::name, and store_by_locale().
Referenced by ast_strftime_locale(), and ast_strptime_locale().
02249 { 02250 struct locale_entry *cur; 02251 locale_t prevlocale = LC_GLOBAL_LOCALE; 02252 02253 if (locale == NULL) { 02254 return store_by_locale(uselocale(LC_GLOBAL_LOCALE)); 02255 } 02256 02257 AST_LIST_LOCK(&localelist); 02258 if ((cur = find_by_name(locale))) { 02259 prevlocale = uselocale(cur->locale); 02260 } 02261 02262 if (!cur) { 02263 if ((cur = ast_calloc(1, sizeof(*cur) + strlen(locale) + 1))) { 02264 cur->locale = newlocale(LC_ALL_MASK, locale, NULL); 02265 strcpy(cur->name, locale); /* SAFE */ 02266 AST_LIST_INSERT_TAIL(&localelist, cur, list); 02267 prevlocale = uselocale(cur->locale); 02268 } 02269 } 02270 AST_LIST_UNLOCK(&localelist); 02271 return store_by_locale(prevlocale); 02272 }
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.
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. |
An | integer value specifying the number of bytes placed into buf or -1 on error. |
Definition at line 2351 of file localtime.c.
References ast_strftime_locale().
Referenced by __ast_verbose_ap(), acf_strftime(), action_corestatus(), append_date(), ast_cel_fabricate_channel_from_event(), ast_http_send(), ast_log(), ast_queue_log(), build_radius_record(), cdr_get_tv(), cli_prompt(), conf_run(), dump_datetime(), epoch_to_string(), exchangecal_get_events_between(), execute_cb(), find_conf_realtime(), format_date(), get_date(), get_ewscal_ids_for(), handle_cli_odbc_show(), handle_minivm_show_stats(), handle_show_settings(), isodate(), leave_voicemail(), make_email_file(), manager_log(), mstime(), odbc_log(), pgsql_log(), rt_extend_conf(), sendmail(), sendpage(), sip_show_registry(), static_callback(), timeout_write(), and write_metadata().
02352 { 02353 return ast_strftime_locale(buf, len, tmp, tm, NULL); 02354 }
int ast_strftime_locale | ( | char * | buf, | |
size_t | len, | |||
const char * | tmp, | |||
const struct ast_tm * | tm, | |||
const char * | locale | |||
) |
Definition at line 2280 of file localtime.c.
References ast_calloc, ast_free, ast_realloc, ast_setlocale(), format, and ast_tm::tm_usec.
Referenced by ast_strftime(), make_email_file(), prep_email_sub_vars(), and sendpage().
02281 { 02282 size_t fmtlen = strlen(tmp) + 1; 02283 char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt; 02284 int decimals = -1, i, res; 02285 long fraction; 02286 const char *prevlocale; 02287 02288 if (!format) { 02289 return -1; 02290 } 02291 for (; *tmp; tmp++) { 02292 if (*tmp == '%') { 02293 switch (tmp[1]) { 02294 case '1': 02295 case '2': 02296 case '3': 02297 case '4': 02298 case '5': 02299 case '6': 02300 if (tmp[2] != 'q') { 02301 goto defcase; 02302 } 02303 decimals = tmp[1] - '0'; 02304 tmp++; 02305 /* Fall through */ 02306 case 'q': /* Milliseconds */ 02307 if (decimals == -1) { 02308 decimals = 3; 02309 } 02310 02311 /* Juggle some memory to fit the item */ 02312 newfmt = ast_realloc(format, fmtlen + decimals); 02313 if (!newfmt) { 02314 ast_free(format); 02315 return -1; 02316 } 02317 fptr = fptr - format + newfmt; 02318 format = newfmt; 02319 fmtlen += decimals; 02320 02321 /* Reduce the fraction of time to the accuracy needed */ 02322 for (i = 6, fraction = tm->tm_usec; i > decimals; i--) { 02323 fraction /= 10; 02324 } 02325 fptr += sprintf(fptr, "%0*ld", decimals, fraction); 02326 02327 /* Reset, in case more than one 'q' specifier exists */ 02328 decimals = -1; 02329 tmp++; 02330 break; 02331 default: 02332 goto defcase; 02333 } 02334 } else { 02335 defcase: *fptr++ = *tmp; 02336 } 02337 } 02338 *fptr = '\0'; 02339 #undef strftime 02340 if (locale) { 02341 prevlocale = ast_setlocale(locale); 02342 } 02343 res = (int)strftime(buf, len, format, (struct tm *)tm); 02344 if (locale) { 02345 ast_setlocale(prevlocale); 02346 } 02347 ast_free(format); 02348 return res; 02349 }
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.
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. |
A | pointer to the first character within s not used to parse the date and time. |
Definition at line 2377 of file localtime.c.
References ast_strptime_locale().
Referenced by acf_strptime(), conf_run(), find_conf_realtime(), mstime_to_time_t(), rt_extend_conf(), and testtime_write().
02378 { 02379 return ast_strptime_locale(s, format, tm, NULL); 02380 }
char* ast_strptime_locale | ( | const char * | s, | |
const char * | format, | |||
struct ast_tm * | tm, | |||
const char * | locale | |||
) |
Definition at line 2356 of file localtime.c.
References ast_setlocale(), ast_tm::tm_isdst, and ast_tm::tm_usec.
Referenced by ast_strptime().
02357 { 02358 struct tm tm2 = { 0, }; 02359 char *res; 02360 const char *prevlocale; 02361 02362 prevlocale = ast_setlocale(locale); 02363 res = strptime(s, format, &tm2); 02364 ast_setlocale(prevlocale); 02365 /* ast_time and tm are not the same size - tm is a subset of 02366 * ast_time. Hence, the size of tm needs to be used for the 02367 * memcpy 02368 */ 02369 memcpy(tm, &tm2, sizeof(tm2)); 02370 tm->tm_usec = 0; 02371 /* strptime(3) doesn't set .tm_isdst correctly, so to force ast_mktime(3) 02372 * to deal with it correctly, we set it to -1. */ 02373 tm->tm_isdst = -1; 02374 return res; 02375 }
static struct state* ast_tzset | ( | const char * | zone | ) | [static, read] |
Definition at line 1432 of file localtime.c.
References ast_calloc, ast_copy_string(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), FALSE, gmtload(), state::name, TRUE, tzload(), and tzparse().
Referenced by ast_get_dst_info(), ast_localtime(), and ast_mktime().
01433 { 01434 struct state *sp; 01435 01436 if (ast_strlen_zero(zone)) { 01437 #ifdef SOLARIS 01438 zone = getenv("TZ"); 01439 if (ast_strlen_zero(zone)) { 01440 zone = "GMT"; 01441 } 01442 #else 01443 zone = "/etc/localtime"; 01444 #endif 01445 } 01446 01447 AST_LIST_LOCK(&zonelist); 01448 AST_LIST_TRAVERSE(&zonelist, sp, list) { 01449 if (!strcmp(sp->name, zone)) { 01450 AST_LIST_UNLOCK(&zonelist); 01451 return sp; 01452 } 01453 } 01454 AST_LIST_UNLOCK(&zonelist); 01455 01456 if (!(sp = ast_calloc(1, sizeof *sp))) 01457 return NULL; 01458 01459 if (tzload(zone, sp, TRUE) != 0) { 01460 if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0) 01461 (void) gmtload(sp); 01462 } 01463 ast_copy_string(sp->name, zone, sizeof(sp->name)); 01464 AST_LIST_LOCK(&zonelist); 01465 AST_LIST_INSERT_TAIL(&zonelist, sp, list); 01466 AST_LIST_UNLOCK(&zonelist); 01467 return sp; 01468 }
void clean_time_zones | ( | void | ) |
Provided by localtime.c
Definition at line 1421 of file localtime.c.
References ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, and AST_LIST_UNLOCK.
Referenced by really_quit().
01422 { 01423 struct state *sp; 01424 01425 AST_LIST_LOCK(&zonelist); 01426 while ((sp = AST_LIST_REMOVE_HEAD(&zonelist, list))) { 01427 ast_free(sp); 01428 } 01429 AST_LIST_UNLOCK(&zonelist); 01430 }
static long detzcode | ( | const char *const | codep | ) | [static] |
Definition at line 631 of file localtime.c.
Referenced by tzload().
static time_t detzcode64 | ( | const char *const | codep | ) | [static] |
Definition at line 642 of file localtime.c.
References int_fast64_t.
Referenced by tzload().
00643 { 00644 time_t result; 00645 int i; 00646 00647 result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0; 00648 for (i = 0; i < 8; ++i) 00649 result = result * 256 + (codep[i] & 0xff); 00650 return result; 00651 }
static int differ_by_repeat | ( | const time_t | t1, | |
const time_t | t0 | |||
) | [static] |
Definition at line 653 of file localtime.c.
References SECSPERREPEAT, SECSPERREPEAT_BITS, TYPE_BIT, TYPE_INTEGRAL, and TYPE_SIGNED.
Referenced by tzload().
00654 { 00655 const long long at1 = t1, at0 = t0; 00656 if (TYPE_INTEGRAL(time_t) && 00657 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) 00658 return 0; 00659 return at1 - at0 == SECSPERREPEAT; 00660 }
static struct locale_entry* find_by_locale | ( | locale_t | locale | ) | [static, read] |
Definition at line 2194 of file localtime.c.
References AST_LIST_TRAVERSE, and locale_entry::locale.
Referenced by store_by_locale().
02195 { 02196 struct locale_entry *cur; 02197 AST_LIST_TRAVERSE(&localelist, cur, list) { 02198 if (locale == cur->locale) { 02199 return cur; 02200 } 02201 } 02202 return NULL; 02203 }
static struct locale_entry* find_by_name | ( | const char * | name | ) | [static, read] |
Definition at line 2205 of file localtime.c.
References AST_LIST_TRAVERSE, and locale_entry::name.
Referenced by ast_setlocale(), and store_by_locale().
02206 { 02207 struct locale_entry *cur; 02208 AST_LIST_TRAVERSE(&localelist, cur, list) { 02209 if (strcmp(name, cur->name) == 0) { 02210 return cur; 02211 } 02212 } 02213 return NULL; 02214 }
static const char* getnum | ( | const char * | strp, | |
int * | nump, | |||
const int | min, | |||
const int | max | |||
) | [static] |
Given a pointer into a time zone string, extract a number from that string. Check that the number is within a specified range; if it is not, return NULL. Otherwise, return a pointer to the first character not part of the number.
Definition at line 950 of file localtime.c.
References is_digit.
Referenced by getrule(), and getsecs().
00951 { 00952 char c; 00953 int num; 00954 00955 if (strp == NULL || !is_digit(c = *strp)) 00956 return NULL; 00957 num = 0; 00958 do { 00959 num = num * 10 + (c - '0'); 00960 if (num > max) 00961 return NULL; /* illegal value */ 00962 c = *++strp; 00963 } while (is_digit(c)); 00964 if (num < min) 00965 return NULL; /* illegal value */ 00966 *nump = num; 00967 return strp; 00968 }
static const char* getoffset | ( | const char * | strp, | |
long * | offsetp | |||
) | [static] |
Given a pointer into a time zone string, extract an offset, in [+-]hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the time.
Definition at line 1017 of file localtime.c.
References getsecs().
Referenced by tzparse().
01018 { 01019 int neg = 0; 01020 01021 if (*strp == '-') { 01022 neg = 1; 01023 ++strp; 01024 } else if (*strp == '+') 01025 ++strp; 01026 strp = getsecs(strp, offsetp); 01027 if (strp == NULL) 01028 return NULL; /* illegal time */ 01029 if (neg) 01030 *offsetp = -*offsetp; 01031 return strp; 01032 }
static const char* getqzname | ( | const char * | strp, | |
const int | delim | |||
) | [static] |
Given a pointer into an extended time zone string, scan until the ending delimiter of the zone name is located. Return a pointer to the delimiter.
As with getzname above, the legal character set is actually quite restricted, with other characters producing undefined results. We don't do any checking here; checking is done later in common-case code.
Definition at line 934 of file localtime.c.
Referenced by tzparse().
static const char* getrule | ( | const char * | strp, | |
struct rule * | rulep | |||
) | [static] |
Given a pointer into a time zone string, extract a rule in the form date[/time]. See POSIX section 8 for the format of "date" and "time". If a valid rule is not found, return NULL. Otherwise, return a pointer to the first character not part of the rule.
Definition at line 1041 of file localtime.c.
References DAY_OF_YEAR, DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, getnum(), getsecs(), is_digit, JULIAN_DAY, MONSPERYEAR, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, and SECSPERHOUR.
Referenced by tzparse().
01042 { 01043 if (*strp == 'J') { 01044 /* 01045 ** Julian day. 01046 */ 01047 rulep->r_type = JULIAN_DAY; 01048 ++strp; 01049 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); 01050 } else if (*strp == 'M') { 01051 /* 01052 ** Month, week, day. 01053 */ 01054 rulep->r_type = MONTH_NTH_DAY_OF_WEEK; 01055 ++strp; 01056 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); 01057 if (strp == NULL) 01058 return NULL; 01059 if (*strp++ != '.') 01060 return NULL; 01061 strp = getnum(strp, &rulep->r_week, 1, 5); 01062 if (strp == NULL) 01063 return NULL; 01064 if (*strp++ != '.') 01065 return NULL; 01066 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); 01067 } else if (is_digit(*strp)) { 01068 /* 01069 ** Day of year. 01070 */ 01071 rulep->r_type = DAY_OF_YEAR; 01072 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); 01073 } else return NULL; /* invalid format */ 01074 if (strp == NULL) 01075 return NULL; 01076 if (*strp == '/') { 01077 /* 01078 ** Time specified. 01079 */ 01080 ++strp; 01081 strp = getsecs(strp, &rulep->r_time); 01082 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ 01083 return strp; 01084 }
static const char* getsecs | ( | const char * | strp, | |
long *const | secsp | |||
) | [static] |
Given a pointer into a time zone string, extract a number of seconds, in hh[:mm[:ss]] form, from the string. If any error occurs, return NULL. Otherwise, return a pointer to the first character not part of the number of seconds.
Definition at line 978 of file localtime.c.
References DAYSPERWEEK, getnum(), HOURSPERDAY, MINSPERHOUR, SECSPERHOUR, and SECSPERMIN.
Referenced by getoffset(), and getrule().
00979 { 00980 int num; 00981 00982 /* 00983 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like 00984 ** "M10.4.6/26", which does not conform to Posix, 00985 ** but which specifies the equivalent of 00986 ** ``02:00 on the first Sunday on or after 23 Oct''. 00987 */ 00988 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); 00989 if (strp == NULL) 00990 return NULL; 00991 *secsp = num * (long) SECSPERHOUR; 00992 if (*strp == ':') { 00993 ++strp; 00994 strp = getnum(strp, &num, 0, MINSPERHOUR - 1); 00995 if (strp == NULL) 00996 return NULL; 00997 *secsp += num * SECSPERMIN; 00998 if (*strp == ':') { 00999 ++strp; 01000 /* `SECSPERMIN' allows for leap seconds. */ 01001 strp = getnum(strp, &num, 0, SECSPERMIN); 01002 if (strp == NULL) 01003 return NULL; 01004 *secsp += num; 01005 } 01006 } 01007 return strp; 01008 }
static const char* getzname | ( | const char * | strp | ) | [static] |
Given a pointer into a time zone string, scan until a character that is not a valid character in a zone name is found. Return a pointer to that character.
Definition at line 915 of file localtime.c.
References is_digit.
Referenced by tzparse().
00916 { 00917 char c; 00918 00919 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && 00920 c != '+') 00921 ++strp; 00922 return strp; 00923 }
static int gmtload | ( | struct state * | sp | ) | [static] |
static struct ast_tm* gmtsub | ( | const struct timeval * | timep, | |
const long | offset, | |||
struct ast_tm * | tmp | |||
) | [static, read] |
Definition at line 1696 of file localtime.c.
References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, state::chars, gmtload(), state::name, and timesub().
Referenced by localsub().
01697 { 01698 struct ast_tm * result; 01699 struct state *sp; 01700 01701 AST_LIST_LOCK(&zonelist); 01702 AST_LIST_TRAVERSE(&zonelist, sp, list) { 01703 if (!strcmp(sp->name, "UTC")) 01704 break; 01705 } 01706 01707 if (!sp) { 01708 if (!(sp = (struct state *) ast_calloc(1, sizeof *sp))) 01709 return NULL; 01710 gmtload(sp); 01711 AST_LIST_INSERT_TAIL(&zonelist, sp, list); 01712 } 01713 AST_LIST_UNLOCK(&zonelist); 01714 01715 result = timesub(timep, offset, sp, tmp); 01716 #ifdef TM_ZONE 01717 /* 01718 ** Could get fancy here and deliver something such as 01719 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, 01720 ** but this is no time for a treasure hunt. 01721 */ 01722 if (offset != 0) 01723 tmp->TM_ZONE = " "; 01724 else 01725 tmp->TM_ZONE = sp->chars; 01726 #endif /* defined TM_ZONE */ 01727 return result; 01728 }
static int increment_overflow | ( | int * | number, | |
int | delta | |||
) | [static] |
Simplified normalize logic courtesy Paul Eggert.
Definition at line 1879 of file localtime.c.
Referenced by normalize_overflow(), time2sub(), and timesub().
static void* inotify_daemon | ( | void * | data | ) | [static] |
Definition at line 272 of file localtime.c.
References ast_cond_broadcast, ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, errno, FILENAME_MAX, LOG_ERROR, state::name, and state::wd.
Referenced by add_notify().
00273 { 00274 struct { 00275 struct inotify_event iev; 00276 char name[FILENAME_MAX + 1]; 00277 } buf; 00278 ssize_t res; 00279 struct state *cur; 00280 00281 inotify_fd = inotify_init(); 00282 00283 ast_mutex_lock(&initialization_lock); 00284 ast_cond_broadcast(&initialization); 00285 ast_mutex_unlock(&initialization_lock); 00286 00287 if (inotify_fd < 0) { 00288 ast_log(LOG_ERROR, "Cannot initialize file notification service: %s (%d)\n", strerror(errno), errno); 00289 inotify_thread = AST_PTHREADT_NULL; 00290 return NULL; 00291 } 00292 00293 for (;/*ever*/;) { 00294 /* This read should block, most of the time. */ 00295 if ((res = read(inotify_fd, &buf, sizeof(buf))) < sizeof(buf.iev) && res > 0) { 00296 /* This should never happen */ 00297 ast_log(LOG_ERROR, "Inotify read less than a full event (%zd < %zu)?!!\n", res, sizeof(buf.iev)); 00298 break; 00299 } else if (res < 0) { 00300 if (errno == EINTR || errno == EAGAIN) { 00301 /* If read fails, try again */ 00302 AST_LIST_LOCK(&zonelist); 00303 ast_cond_broadcast(&initialization); 00304 AST_LIST_UNLOCK(&zonelist); 00305 continue; 00306 } 00307 /* Sanity check -- this should never happen, either */ 00308 ast_log(LOG_ERROR, "Inotify failed: %s\n", strerror(errno)); 00309 break; 00310 } 00311 AST_LIST_LOCK(&zonelist); 00312 AST_LIST_TRAVERSE_SAFE_BEGIN(&zonelist, cur, list) { 00313 if (cur->wd[0] == buf.iev.wd || cur->wd[1] == buf.iev.wd) { 00314 AST_LIST_REMOVE_CURRENT(list); 00315 ast_free(cur); 00316 break; 00317 } 00318 } 00319 AST_LIST_TRAVERSE_SAFE_END 00320 ast_cond_broadcast(&initialization); 00321 AST_LIST_UNLOCK(&zonelist); 00322 } 00323 close(inotify_fd); 00324 inotify_thread = AST_PTHREADT_NULL; 00325 return NULL; 00326 }
static int leaps_thru_end_of | ( | const int | y | ) | [static] |
Return the number of leap years through the end of the given year where, to make the math easy, the answer for year zero is defined as zero.
Definition at line 1735 of file localtime.c.
Referenced by timesub().
01736 { 01737 return (y >= 0) ? (y / 4 - y / 100 + y / 400) : 01738 -(leaps_thru_end_of(-(y + 1)) + 1); 01739 }
static struct ast_tm* localsub | ( | const struct timeval * | timep, | |
const long | offset, | |||
struct ast_tm * | tmp, | |||
const struct state * | sp | |||
) | [static, read] |
The unused offset argument is for the benefit of mktime variants.
Definition at line 1479 of file localtime.c.
References state::ats, AVGSECSPERYEAR, state::chars, gmtsub(), state::goahead, state::goback, int_fast64_t, state::timecnt, timesub(), ast_tm::tm_gmtoff, ast_tm::tm_isdst, ast_tm::tm_usec, ast_tm::tm_year, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and YEARSPERREPEAT.
Referenced by ast_localtime(), and ast_mktime().
01480 { 01481 const struct ttinfo * ttisp; 01482 int i; 01483 struct ast_tm * result; 01484 struct timeval t; 01485 memcpy(&t, timep, sizeof(t)); 01486 01487 if (sp == NULL) 01488 return gmtsub(timep, offset, tmp); 01489 if ((sp->goback && t.tv_sec < sp->ats[0]) || 01490 (sp->goahead && t.tv_sec > sp->ats[sp->timecnt - 1])) { 01491 struct timeval newt = t; 01492 time_t seconds; 01493 time_t tcycles; 01494 int_fast64_t icycles; 01495 01496 if (t.tv_sec < sp->ats[0]) 01497 seconds = sp->ats[0] - t.tv_sec; 01498 else seconds = t.tv_sec - sp->ats[sp->timecnt - 1]; 01499 --seconds; 01500 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; 01501 ++tcycles; 01502 icycles = tcycles; 01503 if (tcycles - icycles >= 1 || icycles - tcycles >= 1) 01504 return NULL; 01505 seconds = icycles; 01506 seconds *= YEARSPERREPEAT; 01507 seconds *= AVGSECSPERYEAR; 01508 if (t.tv_sec < sp->ats[0]) 01509 newt.tv_sec += seconds; 01510 else newt.tv_sec -= seconds; 01511 if (newt.tv_sec < sp->ats[0] || 01512 newt.tv_sec > sp->ats[sp->timecnt - 1]) 01513 return NULL; /* "cannot happen" */ 01514 result = localsub(&newt, offset, tmp, sp); 01515 if (result == tmp) { 01516 time_t newy; 01517 01518 newy = tmp->tm_year; 01519 if (t.tv_sec < sp->ats[0]) 01520 newy -= icycles * YEARSPERREPEAT; 01521 else 01522 newy += icycles * YEARSPERREPEAT; 01523 tmp->tm_year = newy; 01524 if (tmp->tm_year != newy) 01525 return NULL; 01526 } 01527 return result; 01528 } 01529 if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) { 01530 i = 0; 01531 while (sp->ttis[i].tt_isdst) { 01532 if (++i >= sp->typecnt) { 01533 i = 0; 01534 break; 01535 } 01536 } 01537 } else { 01538 int lo = 1; 01539 int hi = sp->timecnt; 01540 01541 while (lo < hi) { 01542 int mid = (lo + hi) >> 1; 01543 01544 if (t.tv_sec < sp->ats[mid]) 01545 hi = mid; 01546 else 01547 lo = mid + 1; 01548 } 01549 i = (int) sp->types[lo - 1]; 01550 } 01551 ttisp = &sp->ttis[i]; 01552 /* 01553 ** To get (wrong) behavior that's compatible with System V Release 2.0 01554 ** you'd replace the statement below with 01555 ** t += ttisp->tt_gmtoff; 01556 ** timesub(&t, 0L, sp, tmp); 01557 */ 01558 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); 01559 tmp->tm_isdst = ttisp->tt_isdst; 01560 #ifndef SOLARIS /* Solaris doesn't have this element */ 01561 tmp->tm_gmtoff = ttisp->tt_gmtoff; 01562 #endif 01563 #ifdef TM_ZONE 01564 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; 01565 #endif /* defined TM_ZONE */ 01566 tmp->tm_usec = timep->tv_usec; 01567 return result; 01568 }
static int long_increment_overflow | ( | long * | number, | |
int | delta | |||
) | [static] |
Definition at line 1888 of file localtime.c.
Referenced by long_normalize_overflow(), and time2sub().
static int long_normalize_overflow | ( | long * | tensptr, | |
int * | unitsptr, | |||
const int | base | |||
) | [static] |
Definition at line 1908 of file localtime.c.
References long_increment_overflow().
Referenced by time2sub().
01909 { 01910 int tensdelta; 01911 01912 tensdelta = (*unitsptr >= 0) ? 01913 (*unitsptr / base) : 01914 (-1 - (-1 - *unitsptr) / base); 01915 *unitsptr -= tensdelta * base; 01916 return long_increment_overflow(tensptr, tensdelta); 01917 }
static int normalize_overflow | ( | int * | tensptr, | |
int * | unitsptr, | |||
const int | base | |||
) | [static] |
Definition at line 1897 of file localtime.c.
References increment_overflow().
Referenced by time2sub().
01898 { 01899 int tensdelta; 01900 01901 tensdelta = (*unitsptr >= 0) ? 01902 (*unitsptr / base) : 01903 (-1 - (-1 - *unitsptr) / base); 01904 *unitsptr -= tensdelta * base; 01905 return increment_overflow(tensptr, tensdelta); 01906 }
static time_t transtime P | ( | (time_t janfirst, int year, const struct rule *rulep, long offset) | ) | [static] |
static struct ast_tm* timesub P | ( | (const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp) | ) | [static, read] |
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, read] |
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, read] |
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, read] |
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, read] |
static struct ast_tm* gmtsub P | ( | (const struct timeval *timep, long offset, struct ast_tm *tmp) | ) | [static, read] |
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 2216 of file localtime.c.
References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, find_by_locale(), find_by_name(), locale_entry::locale, and locale_entry::name.
Referenced by ast_setlocale().
02217 { 02218 struct locale_entry *cur; 02219 if (prevlocale == LC_GLOBAL_LOCALE) { 02220 return NULL; 02221 } else { 02222 /* Get a handle for this entry, if any */ 02223 if ((cur = find_by_locale(prevlocale))) { 02224 return cur->name; 02225 } else { 02226 /* Create an entry, so it can be restored later */ 02227 int x; 02228 cur = NULL; 02229 AST_LIST_LOCK(&localelist); 02230 for (x = 0; x < 10000; x++) { 02231 char name[5]; 02232 snprintf(name, sizeof(name), "%04d", x); 02233 if (!find_by_name(name)) { 02234 if ((cur = ast_calloc(1, sizeof(*cur) + strlen(name) + 1))) { 02235 cur->locale = prevlocale; 02236 strcpy(cur->name, name); /* SAFE */ 02237 AST_LIST_INSERT_TAIL(&localelist, cur, list); 02238 } 02239 break; 02240 } 02241 } 02242 AST_LIST_UNLOCK(&localelist); 02243 return cur ? cur->name : NULL; 02244 } 02245 } 02246 }
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, read] |
Definition at line 2120 of file localtime.c.
References FALSE, time2(), state::timecnt, TRUE, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, state::types, and TZ_MAX_TYPES.
Referenced by ast_mktime().
02121 { 02122 struct timeval t; 02123 int samei, otheri; 02124 int sameind, otherind; 02125 int i; 02126 int nseen; 02127 int seen[TZ_MAX_TYPES]; 02128 int types[TZ_MAX_TYPES]; 02129 int okay; 02130 02131 if (tmp->tm_isdst > 1) 02132 tmp->tm_isdst = 1; 02133 t = time2(tmp, funcp, offset, &okay, sp); 02134 #ifdef PCTS 02135 /* 02136 ** PCTS code courtesy Grant Sullivan. 02137 */ 02138 if (okay) 02139 return t; 02140 if (tmp->tm_isdst < 0) 02141 tmp->tm_isdst = 0; /* reset to std and try again */ 02142 #endif /* defined PCTS */ 02143 #ifndef PCTS 02144 if (okay || tmp->tm_isdst < 0) 02145 return t; 02146 #endif /* !defined PCTS */ 02147 /* 02148 ** We're supposed to assume that somebody took a time of one type 02149 ** and did some math on it that yielded a "struct ast_tm" that's bad. 02150 ** We try to divine the type they started from and adjust to the 02151 ** type they need. 02152 */ 02153 if (sp == NULL) 02154 return WRONG; 02155 for (i = 0; i < sp->typecnt; ++i) 02156 seen[i] = FALSE; 02157 nseen = 0; 02158 for (i = sp->timecnt - 1; i >= 0; --i) 02159 if (!seen[sp->types[i]]) { 02160 seen[sp->types[i]] = TRUE; 02161 types[nseen++] = sp->types[i]; 02162 } 02163 for (sameind = 0; sameind < nseen; ++sameind) { 02164 samei = types[sameind]; 02165 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) 02166 continue; 02167 for (otherind = 0; otherind < nseen; ++otherind) { 02168 otheri = types[otherind]; 02169 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) 02170 continue; 02171 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - 02172 sp->ttis[samei].tt_gmtoff; 02173 tmp->tm_isdst = !tmp->tm_isdst; 02174 t = time2(tmp, funcp, offset, &okay, sp); 02175 if (okay) 02176 return t; 02177 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - 02178 sp->ttis[samei].tt_gmtoff; 02179 tmp->tm_isdst = !tmp->tm_isdst; 02180 } 02181 } 02182 return WRONG; 02183 }
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, read] |
Definition at line 2107 of file localtime.c.
References FALSE, time2sub(), and TRUE.
Referenced by time1().
02108 { 02109 struct timeval t; 02110 02111 /*! \note 02112 ** First try without normalization of seconds 02113 ** (in case tm_sec contains a value associated with a leap second). 02114 ** If that fails, try with normalization of seconds. 02115 */ 02116 t = time2sub(tmp, funcp, offset, okayp, FALSE, sp); 02117 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp); 02118 }
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, read] |
Definition at line 1933 of file localtime.c.
References DAYSPERLYEAR, EPOCH_YEAR, FALSE, HOURSPERDAY, increment_overflow(), isleap, long_increment_overflow(), long_normalize_overflow(), MINSPERHOUR, MONSPERYEAR, normalize_overflow(), SECSPERMIN, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_year, TM_YEAR_BASE, tmcomp(), TRUE, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, TYPE_BIT, TYPE_INTEGRAL, TYPE_SIGNED, and state::typecnt.
Referenced by time2().
01934 { 01935 int dir; 01936 int i, j; 01937 int saved_seconds; 01938 long li; 01939 time_t lo; 01940 time_t hi; 01941 long y; 01942 struct timeval newt = { 0, 0 }; 01943 struct timeval t = { 0, 0 }; 01944 struct ast_tm yourtm, mytm; 01945 01946 *okayp = FALSE; 01947 yourtm = *tmp; 01948 if (do_norm_secs) { 01949 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, 01950 SECSPERMIN)) 01951 return WRONG; 01952 } 01953 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) 01954 return WRONG; 01955 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) 01956 return WRONG; 01957 y = yourtm.tm_year; 01958 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) 01959 return WRONG; 01960 /* 01961 ** Turn y into an actual year number for now. 01962 ** It is converted back to an offset from TM_YEAR_BASE later. 01963 */ 01964 if (long_increment_overflow(&y, TM_YEAR_BASE)) 01965 return WRONG; 01966 while (yourtm.tm_mday <= 0) { 01967 if (long_increment_overflow(&y, -1)) 01968 return WRONG; 01969 li = y + (1 < yourtm.tm_mon); 01970 yourtm.tm_mday += year_lengths[isleap(li)]; 01971 } 01972 while (yourtm.tm_mday > DAYSPERLYEAR) { 01973 li = y + (1 < yourtm.tm_mon); 01974 yourtm.tm_mday -= year_lengths[isleap(li)]; 01975 if (long_increment_overflow(&y, 1)) 01976 return WRONG; 01977 } 01978 for ( ; ; ) { 01979 i = mon_lengths[isleap(y)][yourtm.tm_mon]; 01980 if (yourtm.tm_mday <= i) 01981 break; 01982 yourtm.tm_mday -= i; 01983 if (++yourtm.tm_mon >= MONSPERYEAR) { 01984 yourtm.tm_mon = 0; 01985 if (long_increment_overflow(&y, 1)) 01986 return WRONG; 01987 } 01988 } 01989 if (long_increment_overflow(&y, -TM_YEAR_BASE)) 01990 return WRONG; 01991 yourtm.tm_year = y; 01992 if (yourtm.tm_year != y) 01993 return WRONG; 01994 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) 01995 saved_seconds = 0; 01996 else if (y + TM_YEAR_BASE < EPOCH_YEAR) { 01997 /* 01998 ** We can't set tm_sec to 0, because that might push the 01999 ** time below the minimum representable time. 02000 ** Set tm_sec to 59 instead. 02001 ** This assumes that the minimum representable time is 02002 ** not in the same minute that a leap second was deleted from, 02003 ** which is a safer assumption than using 58 would be. 02004 */ 02005 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) 02006 return WRONG; 02007 saved_seconds = yourtm.tm_sec; 02008 yourtm.tm_sec = SECSPERMIN - 1; 02009 } else { 02010 saved_seconds = yourtm.tm_sec; 02011 yourtm.tm_sec = 0; 02012 } 02013 /* 02014 ** Do a binary search (this works whatever time_t's type is). 02015 */ 02016 if (!TYPE_SIGNED(time_t)) { 02017 lo = 0; 02018 hi = lo - 1; 02019 } else if (!TYPE_INTEGRAL(time_t)) { 02020 if (sizeof(time_t) > sizeof(float)) 02021 hi = (time_t) DBL_MAX; 02022 else hi = (time_t) FLT_MAX; 02023 lo = -hi; 02024 } else { 02025 lo = 1; 02026 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) 02027 lo *= 2; 02028 hi = -(lo + 1); 02029 } 02030 for ( ; ; ) { 02031 t.tv_sec = lo / 2 + hi / 2; 02032 if (t.tv_sec < lo) 02033 t.tv_sec = lo; 02034 else if (t.tv_sec > hi) 02035 t.tv_sec = hi; 02036 if ((*funcp)(&t, offset, &mytm, sp) == NULL) { 02037 /* 02038 ** Assume that t is too extreme to be represented in 02039 ** a struct ast_tm; arrange things so that it is less 02040 ** extreme on the next pass. 02041 */ 02042 dir = (t.tv_sec > 0) ? 1 : -1; 02043 } else dir = tmcomp(&mytm, &yourtm); 02044 if (dir != 0) { 02045 if (t.tv_sec == lo) { 02046 ++t.tv_sec; 02047 if (t.tv_sec <= lo) 02048 return WRONG; 02049 ++lo; 02050 } else if (t.tv_sec == hi) { 02051 --t.tv_sec; 02052 if (t.tv_sec >= hi) 02053 return WRONG; 02054 --hi; 02055 } 02056 if (lo > hi) 02057 return WRONG; 02058 if (dir > 0) 02059 hi = t.tv_sec; 02060 else lo = t.tv_sec; 02061 continue; 02062 } 02063 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) 02064 break; 02065 /* 02066 ** Right time, wrong type. 02067 ** Hunt for right time, right type. 02068 ** It's okay to guess wrong since the guess 02069 ** gets checked. 02070 */ 02071 /* 02072 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. 02073 */ 02074 for (i = sp->typecnt - 1; i >= 0; --i) { 02075 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) 02076 continue; 02077 for (j = sp->typecnt - 1; j >= 0; --j) { 02078 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) 02079 continue; 02080 newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff - 02081 sp->ttis[i].tt_gmtoff; 02082 if ((*funcp)(&newt, offset, &mytm, sp) == NULL) 02083 continue; 02084 if (tmcomp(&mytm, &yourtm) != 0) 02085 continue; 02086 if (mytm.tm_isdst != yourtm.tm_isdst) 02087 continue; 02088 /* 02089 ** We have a match. 02090 */ 02091 t = newt; 02092 goto label; 02093 } 02094 } 02095 return WRONG; 02096 } 02097 label: 02098 newt.tv_sec = t.tv_sec + saved_seconds; 02099 if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0)) 02100 return WRONG; 02101 t.tv_sec = newt.tv_sec; 02102 if ((*funcp)(&t, offset, tmp, sp)) 02103 *okayp = TRUE; 02104 return t; 02105 }
static struct ast_tm* timesub | ( | const struct timeval * | timep, | |
const long | offset, | |||
const struct state * | sp, | |||
struct ast_tm * | tmp | |||
) | [static, read] |
Definition at line 1741 of file localtime.c.
References DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, EPOCH_WDAY, EPOCH_YEAR, increment_overflow(), isleap, state::leapcnt, leaps_thru_end_of(), lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, SECSPERDAY, SECSPERHOUR, SECSPERMIN, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, ast_tm::tm_wday, ast_tm::tm_yday, ast_tm::tm_year, and TM_YEAR_BASE.
Referenced by gmtsub(), and localsub().
01742 { 01743 const struct lsinfo * lp; 01744 time_t tdays; 01745 int idays; /* unsigned would be so 2003 */ 01746 long rem; 01747 int y; 01748 const int * ip; 01749 long corr; 01750 int hit; 01751 int i; 01752 long seconds; 01753 01754 01755 corr = 0; 01756 hit = 0; 01757 i = (sp == NULL) ? 0 : sp->leapcnt; 01758 while (--i >= 0) { 01759 lp = &sp->lsis[i]; 01760 if (timep->tv_sec >= lp->ls_trans) { 01761 if (timep->tv_sec == lp->ls_trans) { 01762 hit = ((i == 0 && lp->ls_corr > 0) || 01763 lp->ls_corr > sp->lsis[i - 1].ls_corr); 01764 if (hit) 01765 while (i > 0 && 01766 sp->lsis[i].ls_trans == 01767 sp->lsis[i - 1].ls_trans + 1 && 01768 sp->lsis[i].ls_corr == 01769 sp->lsis[i - 1].ls_corr + 1) { 01770 ++hit; 01771 --i; 01772 } 01773 } 01774 corr = lp->ls_corr; 01775 break; 01776 } 01777 } 01778 y = EPOCH_YEAR; 01779 tdays = timep->tv_sec / SECSPERDAY; 01780 rem = timep->tv_sec - tdays * SECSPERDAY; 01781 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { 01782 int newy; 01783 time_t tdelta; 01784 int idelta; 01785 int leapdays; 01786 01787 tdelta = tdays / DAYSPERLYEAR; 01788 idelta = tdelta; 01789 if (tdelta - idelta >= 1 || idelta - tdelta >= 1) 01790 return NULL; 01791 if (idelta == 0) 01792 idelta = (tdays < 0) ? -1 : 1; 01793 newy = y; 01794 if (increment_overflow(&newy, idelta)) 01795 return NULL; 01796 leapdays = leaps_thru_end_of(newy - 1) - 01797 leaps_thru_end_of(y - 1); 01798 tdays -= ((time_t) newy - y) * DAYSPERNYEAR; 01799 tdays -= leapdays; 01800 y = newy; 01801 } 01802 01803 seconds = tdays * SECSPERDAY + 0.5; 01804 tdays = seconds / SECSPERDAY; 01805 rem += seconds - tdays * SECSPERDAY; 01806 01807 /* 01808 ** Given the range, we can now fearlessly cast... 01809 */ 01810 idays = tdays; 01811 rem += offset - corr; 01812 while (rem < 0) { 01813 rem += SECSPERDAY; 01814 --idays; 01815 } 01816 while (rem >= SECSPERDAY) { 01817 rem -= SECSPERDAY; 01818 ++idays; 01819 } 01820 while (idays < 0) { 01821 if (increment_overflow(&y, -1)) 01822 return NULL; 01823 idays += year_lengths[isleap(y)]; 01824 } 01825 while (idays >= year_lengths[isleap(y)]) { 01826 idays -= year_lengths[isleap(y)]; 01827 if (increment_overflow(&y, 1)) 01828 return NULL; 01829 } 01830 tmp->tm_year = y; 01831 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) 01832 return NULL; 01833 tmp->tm_yday = idays; 01834 /* 01835 ** The "extra" mods below avoid overflow problems. 01836 */ 01837 tmp->tm_wday = EPOCH_WDAY + 01838 ((y - EPOCH_YEAR) % DAYSPERWEEK) * 01839 (DAYSPERNYEAR % DAYSPERWEEK) + 01840 leaps_thru_end_of(y - 1) - 01841 leaps_thru_end_of(EPOCH_YEAR - 1) + 01842 idays; 01843 tmp->tm_wday %= DAYSPERWEEK; 01844 if (tmp->tm_wday < 0) 01845 tmp->tm_wday += DAYSPERWEEK; 01846 tmp->tm_hour = (int) (rem / SECSPERHOUR); 01847 rem %= SECSPERHOUR; 01848 tmp->tm_min = (int) (rem / SECSPERMIN); 01849 /* 01850 ** A positive leap second requires a special 01851 ** representation. This uses "... ??:59:60" et seq. 01852 */ 01853 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; 01854 ip = mon_lengths[isleap(y)]; 01855 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon)) 01856 idays -= ip[tmp->tm_mon]; 01857 tmp->tm_mday = (int) (idays + 1); 01858 tmp->tm_isdst = 0; 01859 #ifdef TM_GMTOFF 01860 tmp->TM_GMTOFF = offset; 01861 #endif /* defined TM_GMTOFF */ 01862 tmp->tm_usec = timep->tv_usec; 01863 return tmp; 01864 }
Definition at line 1919 of file localtime.c.
References ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, and ast_tm::tm_year.
Referenced by time2sub().
01920 { 01921 int result; 01922 01923 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && 01924 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && 01925 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && 01926 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && 01927 (result = (atmp->tm_min - btmp->tm_min)) == 0 && 01928 (result = (atmp->tm_sec - btmp->tm_sec)) == 0) 01929 result = atmp->tm_usec - btmp->tm_usec; 01930 return result; 01931 }
static time_t transtime | ( | const time_t | janfirst, | |
const int | year, | |||
const struct rule * | rulep, | |||
const long | offset | |||
) | [static] |
Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect.
Definition at line 1092 of file localtime.c.
References DAY_OF_YEAR, DAYSPERWEEK, INITIALIZE, isleap, JULIAN_DAY, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, SECSPERDAY, and value.
Referenced by tzparse().
01093 { 01094 int leapyear; 01095 time_t value; 01096 int i; 01097 int d, m1, yy0, yy1, yy2, dow; 01098 01099 INITIALIZE(value); 01100 leapyear = isleap(year); 01101 switch (rulep->r_type) { 01102 01103 case JULIAN_DAY: 01104 /* 01105 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap 01106 ** years. 01107 ** In non-leap years, or if the day number is 59 or less, just 01108 ** add SECSPERDAY times the day number-1 to the time of 01109 ** January 1, midnight, to get the day. 01110 */ 01111 value = janfirst + (rulep->r_day - 1) * SECSPERDAY; 01112 if (leapyear && rulep->r_day >= 60) 01113 value += SECSPERDAY; 01114 break; 01115 01116 case DAY_OF_YEAR: 01117 /* 01118 ** n - day of year. 01119 ** Just add SECSPERDAY times the day number to the time of 01120 ** January 1, midnight, to get the day. 01121 */ 01122 value = janfirst + rulep->r_day * SECSPERDAY; 01123 break; 01124 01125 case MONTH_NTH_DAY_OF_WEEK: 01126 /* 01127 ** Mm.n.d - nth "dth day" of month m. 01128 */ 01129 value = janfirst; 01130 for (i = 0; i < rulep->r_mon - 1; ++i) 01131 value += mon_lengths[leapyear][i] * SECSPERDAY; 01132 01133 /* 01134 ** Use Zeller's Congruence to get day-of-week of first day of 01135 ** month. 01136 */ 01137 m1 = (rulep->r_mon + 9) % 12 + 1; 01138 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; 01139 yy1 = yy0 / 100; 01140 yy2 = yy0 % 100; 01141 dow = ((26 * m1 - 2) / 10 + 01142 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; 01143 if (dow < 0) 01144 dow += DAYSPERWEEK; 01145 01146 /* 01147 ** "dow" is the day-of-week of the first day of the month. Get 01148 ** the day-of-month (zero-origin) of the first "dow" day of the 01149 ** month. 01150 */ 01151 d = rulep->r_day - dow; 01152 if (d < 0) 01153 d += DAYSPERWEEK; 01154 for (i = 1; i < rulep->r_week; ++i) { 01155 if (d + DAYSPERWEEK >= 01156 mon_lengths[leapyear][rulep->r_mon - 1]) 01157 break; 01158 d += DAYSPERWEEK; 01159 } 01160 01161 /* 01162 ** "d" is the day-of-month (zero-origin) of the day we want. 01163 */ 01164 value += d * SECSPERDAY; 01165 break; 01166 } 01167 01168 /* 01169 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in 01170 ** question. To get the Epoch-relative time of the specified local 01171 ** time on that day, add the transition time and the current offset 01172 ** from UTC. 01173 */ 01174 return value + rulep->r_time + offset; 01175 }
static int tzload | ( | const char * | name, | |
struct state *const | sp, | |||
const int | doextend | |||
) | [static] |
Definition at line 662 of file localtime.c.
References add_notify(), ast_fully_booted, state::ats, state::charcnt, state::chars, detzcode(), detzcode64(), differ_by_repeat(), FALSE, FILENAME_MAX, state::goahead, state::goback, state::leapcnt, lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, OPEN_MODE, state::timecnt, TRUE, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, state::ttis, TYPE_INTEGRAL, TYPE_SIGNED, state::typecnt, state::types, TZ_MAX_CHARS, TZ_MAX_LEAPS, TZ_MAX_TIMES, TZ_MAX_TYPES, TZDEFAULT, TZDIR, tzparse(), and YEARSPERREPEAT.
Referenced by ast_tzset(), gmtload(), and tzparse().
00663 { 00664 const char * p; 00665 int i; 00666 int fid; 00667 int stored; 00668 int nread; 00669 union { 00670 struct tzhead tzhead; 00671 char buf[2 * sizeof(struct tzhead) + 00672 2 * sizeof *sp + 00673 4 * TZ_MAX_TIMES]; 00674 } u; 00675 00676 if (name == NULL && (name = TZDEFAULT) == NULL) 00677 return -1; 00678 { 00679 int doaccess; 00680 /* 00681 ** Section 4.9.1 of the C standard says that 00682 ** "FILENAME_MAX expands to an integral constant expression 00683 ** that is the size needed for an array of char large enough 00684 ** to hold the longest file name string that the implementation 00685 ** guarantees can be opened." 00686 */ 00687 char fullname[FILENAME_MAX + 1]; 00688 00689 if (name[0] == ':') 00690 ++name; 00691 doaccess = name[0] == '/'; 00692 if (!doaccess) { 00693 if ((p = TZDIR) == NULL) 00694 return -1; 00695 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) 00696 return -1; 00697 (void) strcpy(fullname, p); 00698 (void) strcat(fullname, "/"); 00699 (void) strcat(fullname, name); 00700 /* 00701 ** Set doaccess if '.' (as in "../") shows up in name. 00702 */ 00703 if (strchr(name, '.') != NULL) 00704 doaccess = TRUE; 00705 name = fullname; 00706 } 00707 if (doaccess && access(name, R_OK) != 0) 00708 return -1; 00709 if ((fid = open(name, OPEN_MODE)) == -1) 00710 return -1; 00711 if (ast_fully_booted) { 00712 /* If we don't wait until Asterisk is fully booted, it's possible 00713 * that the watcher thread gets started in the parent process, 00714 * before daemon(3) is called, and the thread won't propagate to 00715 * the child. Given that bootup only takes a few seconds, it's 00716 * reasonable to only start the watcher later. */ 00717 add_notify(sp, name); 00718 } 00719 } 00720 nread = read(fid, u.buf, sizeof u.buf); 00721 if (close(fid) < 0 || nread <= 0) 00722 return -1; 00723 for (stored = 4; stored <= 8; stored *= 2) { 00724 int ttisstdcnt; 00725 int ttisgmtcnt; 00726 00727 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); 00728 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); 00729 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); 00730 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); 00731 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); 00732 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); 00733 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; 00734 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || 00735 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || 00736 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || 00737 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || 00738 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || 00739 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) 00740 return -1; 00741 if (nread - (p - u.buf) < 00742 sp->timecnt * stored + /* ats */ 00743 sp->timecnt + /* types */ 00744 sp->typecnt * 6 + /* ttinfos */ 00745 sp->charcnt + /* chars */ 00746 sp->leapcnt * (stored + 4) + /* lsinfos */ 00747 ttisstdcnt + /* ttisstds */ 00748 ttisgmtcnt) /* ttisgmts */ 00749 return -1; 00750 for (i = 0; i < sp->timecnt; ++i) { 00751 sp->ats[i] = (stored == 4) ? 00752 detzcode(p) : detzcode64(p); 00753 p += stored; 00754 } 00755 for (i = 0; i < sp->timecnt; ++i) { 00756 sp->types[i] = (unsigned char) *p++; 00757 if (sp->types[i] >= sp->typecnt) 00758 return -1; 00759 } 00760 for (i = 0; i < sp->typecnt; ++i) { 00761 struct ttinfo * ttisp; 00762 00763 ttisp = &sp->ttis[i]; 00764 ttisp->tt_gmtoff = detzcode(p); 00765 p += 4; 00766 ttisp->tt_isdst = (unsigned char) *p++; 00767 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) 00768 return -1; 00769 ttisp->tt_abbrind = (unsigned char) *p++; 00770 if (ttisp->tt_abbrind < 0 || 00771 ttisp->tt_abbrind > sp->charcnt) 00772 return -1; 00773 } 00774 for (i = 0; i < sp->charcnt; ++i) 00775 sp->chars[i] = *p++; 00776 sp->chars[i] = '\0'; /* ensure '\0' at end */ 00777 for (i = 0; i < sp->leapcnt; ++i) { 00778 struct lsinfo * lsisp; 00779 00780 lsisp = &sp->lsis[i]; 00781 lsisp->ls_trans = (stored == 4) ? 00782 detzcode(p) : detzcode64(p); 00783 p += stored; 00784 lsisp->ls_corr = detzcode(p); 00785 p += 4; 00786 } 00787 for (i = 0; i < sp->typecnt; ++i) { 00788 struct ttinfo * ttisp; 00789 00790 ttisp = &sp->ttis[i]; 00791 if (ttisstdcnt == 0) 00792 ttisp->tt_ttisstd = FALSE; 00793 else { 00794 ttisp->tt_ttisstd = *p++; 00795 if (ttisp->tt_ttisstd != TRUE && 00796 ttisp->tt_ttisstd != FALSE) 00797 return -1; 00798 } 00799 } 00800 for (i = 0; i < sp->typecnt; ++i) { 00801 struct ttinfo * ttisp; 00802 00803 ttisp = &sp->ttis[i]; 00804 if (ttisgmtcnt == 0) 00805 ttisp->tt_ttisgmt = FALSE; 00806 else { 00807 ttisp->tt_ttisgmt = *p++; 00808 if (ttisp->tt_ttisgmt != TRUE && 00809 ttisp->tt_ttisgmt != FALSE) 00810 return -1; 00811 } 00812 } 00813 /* 00814 ** Out-of-sort ats should mean we're running on a 00815 ** signed time_t system but using a data file with 00816 ** unsigned values (or vice versa). 00817 */ 00818 for (i = 0; i < sp->timecnt - 2; ++i) 00819 if (sp->ats[i] > sp->ats[i + 1]) { 00820 ++i; 00821 if (TYPE_SIGNED(time_t)) { 00822 /* 00823 ** Ignore the end (easy). 00824 */ 00825 sp->timecnt = i; 00826 } else { 00827 /* 00828 ** Ignore the beginning (harder). 00829 */ 00830 int j; 00831 00832 for (j = 0; j + i < sp->timecnt; ++j) { 00833 sp->ats[j] = sp->ats[j + i]; 00834 sp->types[j] = sp->types[j + i]; 00835 } 00836 sp->timecnt = j; 00837 } 00838 break; 00839 } 00840 /* 00841 ** If this is an old file, we're done. 00842 */ 00843 if (u.tzhead.tzh_version[0] == '\0') 00844 break; 00845 nread -= p - u.buf; 00846 for (i = 0; i < nread; ++i) 00847 u.buf[i] = p[i]; 00848 /* 00849 ** If this is a narrow integer time_t system, we're done. 00850 */ 00851 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t)) 00852 break; 00853 } 00854 if (doextend && nread > 2 && 00855 u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && 00856 sp->typecnt + 2 <= TZ_MAX_TYPES) { 00857 struct state ts; 00858 int result; 00859 00860 u.buf[nread - 1] = '\0'; 00861 result = tzparse(&u.buf[1], &ts, FALSE); 00862 if (result == 0 && ts.typecnt == 2 && 00863 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { 00864 for (i = 0; i < 2; ++i) 00865 ts.ttis[i].tt_abbrind += 00866 sp->charcnt; 00867 for (i = 0; i < ts.charcnt; ++i) 00868 sp->chars[sp->charcnt++] = 00869 ts.chars[i]; 00870 i = 0; 00871 while (i < ts.timecnt && 00872 ts.ats[i] <= 00873 sp->ats[sp->timecnt - 1]) 00874 ++i; 00875 while (i < ts.timecnt && 00876 sp->timecnt < TZ_MAX_TIMES) { 00877 sp->ats[sp->timecnt] = 00878 ts.ats[i]; 00879 sp->types[sp->timecnt] = 00880 sp->typecnt + 00881 ts.types[i]; 00882 ++sp->timecnt; 00883 ++i; 00884 } 00885 sp->ttis[sp->typecnt++] = ts.ttis[0]; 00886 sp->ttis[sp->typecnt++] = ts.ttis[1]; 00887 } 00888 } 00889 i = 2 * YEARSPERREPEAT; 00890 sp->goback = sp->goahead = sp->timecnt > i; 00891 sp->goback = sp->goback && sp->types[i] == sp->types[0] && 00892 differ_by_repeat(sp->ats[i], sp->ats[0]); 00893 sp->goahead = sp->goahead && 00894 sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] && 00895 differ_by_repeat(sp->ats[sp->timecnt - 1], 00896 sp->ats[sp->timecnt - 1 - i]); 00897 return 0; 00898 }
static int tzparse | ( | const char * | name, | |
struct state * | sp, | |||
const int | lastditch | |||
) | [static] |
Definition at line 1182 of file localtime.c.
References state::ats, state::charcnt, state::chars, EPOCH_YEAR, FALSE, getoffset(), getqzname(), getrule(), getzname(), INITIALIZE, isleap, state::leapcnt, SECSPERDAY, SECSPERHOUR, state::timecnt, transtime(), TRUE, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, state::ttis, state::typecnt, state::types, TZ_MAX_TIMES, TZDEFRULES, TZDEFRULESTRING, and tzload().
Referenced by ast_tzset(), gmtload(), and tzload().
01183 { 01184 const char * stdname; 01185 const char * dstname; 01186 size_t stdlen; 01187 size_t dstlen; 01188 long stdoffset; 01189 long dstoffset; 01190 time_t * atp; 01191 unsigned char * typep; 01192 char * cp; 01193 int load_result; 01194 01195 INITIALIZE(dstname); 01196 stdname = name; 01197 if (lastditch) { 01198 stdlen = strlen(name); /* length of standard zone name */ 01199 name += stdlen; 01200 if (stdlen >= sizeof sp->chars) 01201 stdlen = (sizeof sp->chars) - 1; 01202 stdoffset = 0; 01203 } else { 01204 if (*name == '<') { 01205 name++; 01206 stdname = name; 01207 name = getqzname(name, '>'); 01208 if (*name != '>') 01209 return -1; 01210 stdlen = name - stdname; 01211 name++; 01212 } else { 01213 name = getzname(name); 01214 stdlen = name - stdname; 01215 } 01216 if (*name == '\0') 01217 return -1; 01218 name = getoffset(name, &stdoffset); 01219 if (name == NULL) 01220 return -1; 01221 } 01222 load_result = tzload(TZDEFRULES, sp, FALSE); 01223 if (load_result != 0) 01224 sp->leapcnt = 0; /* so, we're off a little */ 01225 if (*name != '\0') { 01226 if (*name == '<') { 01227 dstname = ++name; 01228 name = getqzname(name, '>'); 01229 if (*name != '>') 01230 return -1; 01231 dstlen = name - dstname; 01232 name++; 01233 } else { 01234 dstname = name; 01235 name = getzname(name); 01236 dstlen = name - dstname; /* length of DST zone name */ 01237 } 01238 if (*name != '\0' && *name != ',' && *name != ';') { 01239 name = getoffset(name, &dstoffset); 01240 if (name == NULL) 01241 return -1; 01242 } else dstoffset = stdoffset - SECSPERHOUR; 01243 if (*name == '\0' && load_result != 0) 01244 name = TZDEFRULESTRING; 01245 if (*name == ',' || *name == ';') { 01246 struct rule start; 01247 struct rule end; 01248 int year; 01249 time_t janfirst; 01250 time_t starttime; 01251 time_t endtime; 01252 01253 ++name; 01254 if ((name = getrule(name, &start)) == NULL) 01255 return -1; 01256 if (*name++ != ',') 01257 return -1; 01258 if ((name = getrule(name, &end)) == NULL) 01259 return -1; 01260 if (*name != '\0') 01261 return -1; 01262 sp->typecnt = 2; /* standard time and DST */ 01263 /* 01264 ** Two transitions per year, from EPOCH_YEAR forward. 01265 */ 01266 sp->ttis[0].tt_gmtoff = -dstoffset; 01267 sp->ttis[0].tt_isdst = 1; 01268 sp->ttis[0].tt_abbrind = stdlen + 1; 01269 sp->ttis[1].tt_gmtoff = -stdoffset; 01270 sp->ttis[1].tt_isdst = 0; 01271 sp->ttis[1].tt_abbrind = 0; 01272 atp = sp->ats; 01273 typep = sp->types; 01274 janfirst = 0; 01275 sp->timecnt = 0; 01276 for (year = EPOCH_YEAR; 01277 sp->timecnt + 2 <= TZ_MAX_TIMES; 01278 ++year) { 01279 time_t newfirst; 01280 01281 starttime = transtime(janfirst, year, &start, 01282 stdoffset); 01283 endtime = transtime(janfirst, year, &end, 01284 dstoffset); 01285 if (starttime > endtime) { 01286 *atp++ = endtime; 01287 *typep++ = 1; /* DST ends */ 01288 *atp++ = starttime; 01289 *typep++ = 0; /* DST begins */ 01290 } else { 01291 *atp++ = starttime; 01292 *typep++ = 0; /* DST begins */ 01293 *atp++ = endtime; 01294 *typep++ = 1; /* DST ends */ 01295 } 01296 sp->timecnt += 2; 01297 newfirst = janfirst; 01298 newfirst += year_lengths[isleap(year)] * 01299 SECSPERDAY; 01300 if (newfirst <= janfirst) 01301 break; 01302 janfirst = newfirst; 01303 } 01304 } else { 01305 long theirstdoffset; 01306 long theirdstoffset; 01307 long theiroffset; 01308 int isdst; 01309 int i; 01310 int j; 01311 01312 if (*name != '\0') 01313 return -1; 01314 /* 01315 ** Initial values of theirstdoffset and theirdstoffset. 01316 */ 01317 theirstdoffset = 0; 01318 for (i = 0; i < sp->timecnt; ++i) { 01319 j = sp->types[i]; 01320 if (!sp->ttis[j].tt_isdst) { 01321 theirstdoffset = 01322 -sp->ttis[j].tt_gmtoff; 01323 break; 01324 } 01325 } 01326 theirdstoffset = 0; 01327 for (i = 0; i < sp->timecnt; ++i) { 01328 j = sp->types[i]; 01329 if (sp->ttis[j].tt_isdst) { 01330 theirdstoffset = 01331 -sp->ttis[j].tt_gmtoff; 01332 break; 01333 } 01334 } 01335 /* 01336 ** Initially we're assumed to be in standard time. 01337 */ 01338 isdst = FALSE; 01339 theiroffset = theirstdoffset; 01340 /* 01341 ** Now juggle transition times and types 01342 ** tracking offsets as you do. 01343 */ 01344 for (i = 0; i < sp->timecnt; ++i) { 01345 j = sp->types[i]; 01346 sp->types[i] = sp->ttis[j].tt_isdst; 01347 if (sp->ttis[j].tt_ttisgmt) { 01348 /* No adjustment to transition time */ 01349 } else { 01350 /* 01351 ** If summer time is in effect, and the 01352 ** transition time was not specified as 01353 ** standard time, add the summer time 01354 ** offset to the transition time; 01355 ** otherwise, add the standard time 01356 ** offset to the transition time. 01357 */ 01358 /* 01359 ** Transitions from DST to DDST 01360 ** will effectively disappear since 01361 ** POSIX provides for only one DST 01362 ** offset. 01363 */ 01364 if (isdst && !sp->ttis[j].tt_ttisstd) { 01365 sp->ats[i] += dstoffset - 01366 theirdstoffset; 01367 } else { 01368 sp->ats[i] += stdoffset - 01369 theirstdoffset; 01370 } 01371 } 01372 theiroffset = -sp->ttis[j].tt_gmtoff; 01373 if (sp->ttis[j].tt_isdst) 01374 theirdstoffset = theiroffset; 01375 else theirstdoffset = theiroffset; 01376 } 01377 /* 01378 ** Finally, fill in ttis. 01379 ** ttisstd and ttisgmt need not be handled. 01380 */ 01381 sp->ttis[0].tt_gmtoff = -stdoffset; 01382 sp->ttis[0].tt_isdst = FALSE; 01383 sp->ttis[0].tt_abbrind = 0; 01384 sp->ttis[1].tt_gmtoff = -dstoffset; 01385 sp->ttis[1].tt_isdst = TRUE; 01386 sp->ttis[1].tt_abbrind = stdlen + 1; 01387 sp->typecnt = 2; 01388 } 01389 } else { 01390 dstlen = 0; 01391 sp->typecnt = 1; /* only standard time */ 01392 sp->timecnt = 0; 01393 sp->ttis[0].tt_gmtoff = -stdoffset; 01394 sp->ttis[0].tt_isdst = 0; 01395 sp->ttis[0].tt_abbrind = 0; 01396 } 01397 sp->charcnt = stdlen + 1; 01398 if (dstlen != 0) 01399 sp->charcnt += dstlen + 1; 01400 if ((size_t) sp->charcnt > sizeof sp->chars) 01401 return -1; 01402 cp = sp->chars; 01403 (void) strncpy(cp, stdname, stdlen); 01404 cp += stdlen; 01405 *cp++ = '\0'; 01406 if (dstlen != 0) { 01407 (void) strncpy(cp, dstname, dstlen); 01408 *(cp + dstlen) = '\0'; 01409 } 01410 return 0; 01411 }
char elsieid[] = "@(#)localtime.c 8.5" [static] |
Definition at line 84 of file localtime.c.
const char gmt[] = "GMT" [static] |
Definition at line 112 of file localtime.c.
ast_cond_t initialization [static] |
Definition at line 267 of file localtime.c.
ast_mutex_t initialization_lock [static] |
Definition at line 268 of file localtime.c.
int inotify_fd = -1 [static] |
Definition at line 270 of file localtime.c.
Referenced by scan_thread().
pthread_t inotify_thread = AST_PTHREADT_NULL [static] |
Definition at line 266 of file localtime.c.
const int mon_lengths[2][MONSPERYEAR] [static] |
{ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }
Definition at line 900 of file localtime.c.
struct timeval WRONG = { 0, 0 } [static] |
Definition at line 113 of file localtime.c.
const int year_lengths[2] [static] |
{ DAYSPERNYEAR, DAYSPERLYEAR }
Definition at line 905 of file localtime.c.