#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_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) |
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) |
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] |
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 143 of file localtime.c.
#define DAY_OF_YEAR 1 |
#define JULIAN_DAY 0 |
#define MONTH_NTH_DAY_OF_WEEK 2 |
#define MY_TZNAME_MAX 255 |
Definition at line 149 of file localtime.c.
#define OPEN_MODE O_RDONLY |
#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" |
Definition at line 125 of file localtime.c.
Referenced by tzparse().
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, int_fast64_t, 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).
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 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).
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 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.
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 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.
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 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] |
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.
References int_fast64_t.
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] |
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] |
Definition at line 1456 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().
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 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] |
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 }
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] |
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 }
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] |
int inotify_fd = -1 [static] |
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:
{ DAYSPERNYEAR, DAYSPERLYEAR }
Definition at line 893 of file localtime.c.
Referenced by time2sub(), and timesub().