#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 147 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 153 of file localtime.c.
#define OPEN_MODE O_RDONLY |
#define TZ_ABBR_CHAR_SET "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" |
Definition at line 92 of file localtime.c.
#define TZ_ABBR_ERR_CHAR '_' |
Definition at line 97 of file localtime.c.
#define TZ_ABBR_MAX_LEN 16 |
Definition at line 88 of file localtime.c.
#define TZ_STRLEN_MAX 255 |
Definition at line 156 of file localtime.c.
#define TZDEFRULESTRING ",M4.1.0,M10.5.0" |
Definition at line 129 of file localtime.c.
Referenced by tzparse().
static void add_notify | ( | struct state * | sp, | |
const char * | path | |||
) | [static] |
Definition at line 327 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().
00328 { 00329 if (inotify_thread == AST_PTHREADT_NULL) { 00330 ast_cond_init(&initialization, NULL); 00331 ast_mutex_init(&initialization_lock); 00332 ast_mutex_lock(&initialization_lock); 00333 if (!(ast_pthread_create_background(&inotify_thread, NULL, inotify_daemon, NULL))) { 00334 /* Give the thread a chance to initialize */ 00335 ast_cond_wait(&initialization, &initialization_lock); 00336 } else { 00337 fprintf(stderr, "Unable to start notification thread\n"); 00338 ast_mutex_unlock(&initialization_lock); 00339 return; 00340 } 00341 ast_mutex_unlock(&initialization_lock); 00342 } 00343 00344 if (inotify_fd > -1) { 00345 char fullpath[FILENAME_MAX + 1] = ""; 00346 if (readlink(path, fullpath, sizeof(fullpath) - 1) != -1) { 00347 /* If file the symlink points to changes */ 00348 sp->wd[1] = inotify_add_watch(inotify_fd, fullpath, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE ); 00349 } else { 00350 sp->wd[1] = -1; 00351 } 00352 /* or if the symlink itself changes (or the real file is here, if path is not a symlink) */ 00353 sp->wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE 00354 #ifdef IN_DONT_FOLLOW /* Only defined in glibc 2.5 and above */ 00355 | IN_DONT_FOLLOW 00356 #endif 00357 ); 00358 } 00359 }
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 1566 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().
01567 { 01568 int i; 01569 int transition1 = -1; 01570 int transition2 = -1; 01571 time_t seconds; 01572 int bounds_exceeded = 0; 01573 time_t t = *timep; 01574 const struct state *sp; 01575 01576 if (NULL == dst_enabled) 01577 return; 01578 *dst_enabled = 0; 01579 01580 if (NULL == dst_start || NULL == dst_end || NULL == gmt_off) 01581 return; 01582 01583 *gmt_off = 0; 01584 01585 sp = ast_tzset(zone); 01586 if (NULL == sp) 01587 return; 01588 01589 /* If the desired time exceeds the bounds of the defined time transitions 01590 * then give give up on determining DST info and simply look for gmt offset 01591 * This requires that I adjust the given time using increments of Gregorian 01592 * repeats to place the time within the defined time transitions in the 01593 * timezone structure. 01594 */ 01595 if ((sp->goback && t < sp->ats[0]) || 01596 (sp->goahead && t > sp->ats[sp->timecnt - 1])) { 01597 time_t tcycles; 01598 int_fast64_t icycles; 01599 01600 if (t < sp->ats[0]) 01601 seconds = sp->ats[0] - t; 01602 else seconds = t - sp->ats[sp->timecnt - 1]; 01603 --seconds; 01604 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; 01605 ++tcycles; 01606 icycles = tcycles; 01607 if (tcycles - icycles >= 1 || icycles - tcycles >= 1) 01608 return; 01609 seconds = icycles; 01610 seconds *= YEARSPERREPEAT; 01611 seconds *= AVGSECSPERYEAR; 01612 if (t < sp->ats[0]) 01613 t += seconds; 01614 else 01615 t -= seconds; 01616 01617 if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1]) 01618 return; /* "cannot happen" */ 01619 01620 bounds_exceeded = 1; 01621 } 01622 01623 if (sp->timecnt == 0 || t < sp->ats[0]) { 01624 /* I have no transition times or I'm before time */ 01625 *dst_enabled = 0; 01626 /* Find where I can get gmtoff */ 01627 i = 0; 01628 while (sp->ttis[i].tt_isdst) 01629 if (++i >= sp->typecnt) { 01630 i = 0; 01631 break; 01632 } 01633 *gmt_off = sp->ttis[i].tt_gmtoff; 01634 return; 01635 } 01636 01637 for (i = 1; i < sp->timecnt; ++i) { 01638 if (t < sp->ats[i]) { 01639 transition1 = sp->types[i - 1]; 01640 transition2 = sp->types[i]; 01641 break; 01642 } 01643 } 01644 /* if I found transition times that do not bounded the given time and these correspond to 01645 or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */ 01646 if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 || 01647 (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) { 01648 *dst_enabled = 0; 01649 *gmt_off = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff; 01650 } else { 01651 /* I have valid daylight savings information. */ 01652 if(sp->ttis[transition2].tt_isdst) 01653 *gmt_off = sp->ttis[transition1].tt_gmtoff; 01654 else 01655 *gmt_off = sp->ttis[transition2].tt_gmtoff; 01656 01657 /* If I adjusted the time earlier, indicate that the dst is invalid */ 01658 if (!bounds_exceeded) { 01659 *dst_enabled = 1; 01660 /* Determine which of the bounds is the start of daylight savings and which is the end */ 01661 if(sp->ttis[transition2].tt_isdst) { 01662 *dst_start = sp->ats[i]; 01663 *dst_end = sp->ats[i -1]; 01664 } else { 01665 *dst_start = sp->ats[i -1]; 01666 *dst_end = sp->ats[i]; 01667 } 01668 } 01669 } 01670 return; 01671 }
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 1551 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().
01552 { 01553 const struct state *sp = ast_tzset(zone); 01554 memset(tmp, 0, sizeof(*tmp)); 01555 return sp ? localsub(timep, 0L, tmp, sp) : NULL; 01556 }
void ast_localtime_wakeup_monitor | ( | struct ast_test * | info | ) |
Definition at line 606 of file localtime.c.
References ast_cond_wait, AST_LIST_LOCK, AST_LIST_UNLOCK, AST_PTHREADT_NULL, initialization, inotify_thread, and lock.
00607 { 00608 if (inotify_thread != AST_PTHREADT_NULL) { 00609 AST_LIST_LOCK(&zonelist); 00610 #ifdef TEST_FRAMEWORK 00611 test = info; 00612 #endif 00613 pthread_kill(inotify_thread, SIGURG); 00614 ast_cond_wait(&initialization, &(&zonelist)->lock); 00615 #ifdef TEST_FRAMEWORK 00616 test = NULL; 00617 #endif 00618 AST_LIST_UNLOCK(&zonelist); 00619 } 00620 }
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 2166 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().
02167 { 02168 const struct state *sp; 02169 if (!(sp = ast_tzset(zone))) 02170 return WRONG; 02171 return time1(tmp, localsub, 0L, sp); 02172 }
const char* ast_setlocale | ( | const char * | locale | ) |
Set the thread-local representation of the current locale.
Definition at line 2229 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().
02230 { 02231 struct locale_entry *cur; 02232 locale_t prevlocale = LC_GLOBAL_LOCALE; 02233 02234 if (locale == NULL) { 02235 return store_by_locale(uselocale(LC_GLOBAL_LOCALE)); 02236 } 02237 02238 AST_LIST_LOCK(&localelist); 02239 if ((cur = find_by_name(locale))) { 02240 prevlocale = uselocale(cur->locale); 02241 } 02242 02243 if (!cur) { 02244 if ((cur = ast_calloc(1, sizeof(*cur) + strlen(locale) + 1))) { 02245 cur->locale = newlocale(LC_ALL_MASK, locale, NULL); 02246 strcpy(cur->name, locale); /* SAFE */ 02247 AST_LIST_INSERT_TAIL(&localelist, cur, list); 02248 prevlocale = uselocale(cur->locale); 02249 } 02250 } 02251 AST_LIST_UNLOCK(&localelist); 02252 return store_by_locale(prevlocale); 02253 }
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 2332 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().
02333 { 02334 return ast_strftime_locale(buf, len, tmp, tm, NULL); 02335 }
int ast_strftime_locale | ( | char * | buf, | |
size_t | len, | |||
const char * | tmp, | |||
const struct ast_tm * | tm, | |||
const char * | locale | |||
) |
Definition at line 2261 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().
02262 { 02263 size_t fmtlen = strlen(tmp) + 1; 02264 char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt; 02265 int decimals = -1, i, res; 02266 long fraction; 02267 const char *prevlocale; 02268 02269 if (!format) { 02270 return -1; 02271 } 02272 for (; *tmp; tmp++) { 02273 if (*tmp == '%') { 02274 switch (tmp[1]) { 02275 case '1': 02276 case '2': 02277 case '3': 02278 case '4': 02279 case '5': 02280 case '6': 02281 if (tmp[2] != 'q') { 02282 goto defcase; 02283 } 02284 decimals = tmp[1] - '0'; 02285 tmp++; 02286 /* Fall through */ 02287 case 'q': /* Milliseconds */ 02288 if (decimals == -1) { 02289 decimals = 3; 02290 } 02291 02292 /* Juggle some memory to fit the item */ 02293 newfmt = ast_realloc(format, fmtlen + decimals); 02294 if (!newfmt) { 02295 ast_free(format); 02296 return -1; 02297 } 02298 fptr = fptr - format + newfmt; 02299 format = newfmt; 02300 fmtlen += decimals; 02301 02302 /* Reduce the fraction of time to the accuracy needed */ 02303 for (i = 6, fraction = tm->tm_usec; i > decimals; i--) { 02304 fraction /= 10; 02305 } 02306 fptr += sprintf(fptr, "%0*ld", decimals, fraction); 02307 02308 /* Reset, in case more than one 'q' specifier exists */ 02309 decimals = -1; 02310 tmp++; 02311 break; 02312 default: 02313 goto defcase; 02314 } 02315 } else { 02316 defcase: *fptr++ = *tmp; 02317 } 02318 } 02319 *fptr = '\0'; 02320 #undef strftime 02321 if (locale) { 02322 prevlocale = ast_setlocale(locale); 02323 } 02324 res = (int)strftime(buf, len, format, (struct tm *)tm); 02325 if (locale) { 02326 ast_setlocale(prevlocale); 02327 } 02328 ast_free(format); 02329 return res; 02330 }
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 2358 of file localtime.c.
References ast_strptime_locale().
Referenced by acf_strptime(), conf_run(), mstime_to_time_t(), rt_extend_conf(), and testtime_write().
02359 { 02360 return ast_strptime_locale(s, format, tm, NULL); 02361 }
char* ast_strptime_locale | ( | const char * | s, | |
const char * | format, | |||
struct ast_tm * | tm, | |||
const char * | locale | |||
) |
Definition at line 2337 of file localtime.c.
References ast_setlocale(), ast_tm::tm_isdst, and ast_tm::tm_usec.
Referenced by ast_strptime().
02338 { 02339 struct tm tm2 = { 0, }; 02340 char *res; 02341 const char *prevlocale; 02342 02343 prevlocale = ast_setlocale(locale); 02344 res = strptime(s, format, &tm2); 02345 ast_setlocale(prevlocale); 02346 /* ast_time and tm are not the same size - tm is a subset of 02347 * ast_time. Hence, the size of tm needs to be used for the 02348 * memcpy 02349 */ 02350 memcpy(tm, &tm2, sizeof(tm2)); 02351 tm->tm_usec = 0; 02352 /* strptime(3) doesn't set .tm_isdst correctly, so to force ast_mktime(3) 02353 * to deal with it correctly, we set it to -1. */ 02354 tm->tm_isdst = -1; 02355 return res; 02356 }
static struct state* ast_tzset | ( | const char * | zone | ) | [static] |
Definition at line 1413 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().
01414 { 01415 struct state *sp; 01416 01417 if (ast_strlen_zero(zone)) { 01418 #ifdef SOLARIS 01419 zone = getenv("TZ"); 01420 if (ast_strlen_zero(zone)) { 01421 zone = "GMT"; 01422 } 01423 #else 01424 zone = "/etc/localtime"; 01425 #endif 01426 } 01427 01428 AST_LIST_LOCK(&zonelist); 01429 AST_LIST_TRAVERSE(&zonelist, sp, list) { 01430 if (!strcmp(sp->name, zone)) { 01431 AST_LIST_UNLOCK(&zonelist); 01432 return sp; 01433 } 01434 } 01435 AST_LIST_UNLOCK(&zonelist); 01436 01437 if (!(sp = ast_calloc(1, sizeof *sp))) 01438 return NULL; 01439 01440 if (tzload(zone, sp, TRUE) != 0) { 01441 if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0) 01442 (void) gmtload(sp); 01443 } 01444 ast_copy_string(sp->name, zone, sizeof(sp->name)); 01445 AST_LIST_LOCK(&zonelist); 01446 AST_LIST_INSERT_TAIL(&zonelist, sp, list); 01447 AST_LIST_UNLOCK(&zonelist); 01448 return sp; 01449 }
static long detzcode | ( | const char *const | codep | ) | [static] |
Definition at line 630 of file localtime.c.
Referenced by tzload().
00631 { 00632 long result; 00633 int i; 00634 00635 result = (codep[0] & 0x80) ? ~0L : 0; 00636 for (i = 0; i < 4; ++i) 00637 result = (result << 8) | (codep[i] & 0xff); 00638 return result; 00639 }
static time_t detzcode64 | ( | const char *const | codep | ) | [static] |
Definition at line 641 of file localtime.c.
References int_fast64_t.
Referenced by tzload().
00642 { 00643 time_t result; 00644 int i; 00645 00646 result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0; 00647 for (i = 0; i < 8; ++i) 00648 result = result * 256 + (codep[i] & 0xff); 00649 return result; 00650 }
static int differ_by_repeat | ( | const time_t | t1, | |
const time_t | t0 | |||
) | [static] |
Definition at line 652 of file localtime.c.
References SECSPERREPEAT, SECSPERREPEAT_BITS, TYPE_BIT, TYPE_INTEGRAL, and TYPE_SIGNED.
00653 { 00654 const long long at1 = t1, at0 = t0; 00655 if (TYPE_INTEGRAL(time_t) && 00656 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) 00657 return 0; 00658 return at1 - at0 == SECSPERREPEAT; 00659 }
static struct locale_entry* find_by_locale | ( | locale_t | locale | ) | [static] |
Definition at line 2175 of file localtime.c.
References AST_LIST_TRAVERSE, locale_entry::list, and locale_entry::locale.
Referenced by store_by_locale().
02176 { 02177 struct locale_entry *cur; 02178 AST_LIST_TRAVERSE(&localelist, cur, list) { 02179 if (locale == cur->locale) { 02180 return cur; 02181 } 02182 } 02183 return NULL; 02184 }
static struct locale_entry* find_by_name | ( | const char * | name | ) | [static] |
Definition at line 2186 of file localtime.c.
References AST_LIST_TRAVERSE, locale_entry::list, and locale_entry::name.
02187 { 02188 struct locale_entry *cur; 02189 AST_LIST_TRAVERSE(&localelist, cur, list) { 02190 if (strcmp(name, cur->name) == 0) { 02191 return cur; 02192 } 02193 } 02194 return NULL; 02195 }
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 942 of file localtime.c.
References is_digit.
Referenced by getrule(), and getsecs().
00943 { 00944 char c; 00945 int num; 00946 00947 if (strp == NULL || !is_digit(c = *strp)) 00948 return NULL; 00949 num = 0; 00950 do { 00951 num = num * 10 + (c - '0'); 00952 if (num > max) 00953 return NULL; /* illegal value */ 00954 c = *++strp; 00955 } while (is_digit(c)); 00956 if (num < min) 00957 return NULL; /* illegal value */ 00958 *nump = num; 00959 return strp; 00960 }
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 1009 of file localtime.c.
References getsecs().
Referenced by tzparse().
01010 { 01011 int neg = 0; 01012 01013 if (*strp == '-') { 01014 neg = 1; 01015 ++strp; 01016 } else if (*strp == '+') 01017 ++strp; 01018 strp = getsecs(strp, offsetp); 01019 if (strp == NULL) 01020 return NULL; /* illegal time */ 01021 if (neg) 01022 *offsetp = -*offsetp; 01023 return strp; 01024 }
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 926 of file localtime.c.
Referenced by tzparse().
00927 { 00928 int c; 00929 00930 while ((c = *strp) != '\0' && c != delim) 00931 ++strp; 00932 return strp; 00933 }
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 1033 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().
01034 { 01035 if (*strp == 'J') { 01036 /* 01037 ** Julian day. 01038 */ 01039 rulep->r_type = JULIAN_DAY; 01040 ++strp; 01041 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); 01042 } else if (*strp == 'M') { 01043 /* 01044 ** Month, week, day. 01045 */ 01046 rulep->r_type = MONTH_NTH_DAY_OF_WEEK; 01047 ++strp; 01048 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); 01049 if (strp == NULL) 01050 return NULL; 01051 if (*strp++ != '.') 01052 return NULL; 01053 strp = getnum(strp, &rulep->r_week, 1, 5); 01054 if (strp == NULL) 01055 return NULL; 01056 if (*strp++ != '.') 01057 return NULL; 01058 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); 01059 } else if (is_digit(*strp)) { 01060 /* 01061 ** Day of year. 01062 */ 01063 rulep->r_type = DAY_OF_YEAR; 01064 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); 01065 } else return NULL; /* invalid format */ 01066 if (strp == NULL) 01067 return NULL; 01068 if (*strp == '/') { 01069 /* 01070 ** Time specified. 01071 */ 01072 ++strp; 01073 strp = getsecs(strp, &rulep->r_time); 01074 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ 01075 return strp; 01076 }
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 970 of file localtime.c.
References DAYSPERWEEK, getnum(), HOURSPERDAY, MINSPERHOUR, SECSPERHOUR, and SECSPERMIN.
Referenced by getoffset(), and getrule().
00971 { 00972 int num; 00973 00974 /* 00975 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like 00976 ** "M10.4.6/26", which does not conform to Posix, 00977 ** but which specifies the equivalent of 00978 ** ``02:00 on the first Sunday on or after 23 Oct''. 00979 */ 00980 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); 00981 if (strp == NULL) 00982 return NULL; 00983 *secsp = num * (long) SECSPERHOUR; 00984 if (*strp == ':') { 00985 ++strp; 00986 strp = getnum(strp, &num, 0, MINSPERHOUR - 1); 00987 if (strp == NULL) 00988 return NULL; 00989 *secsp += num * SECSPERMIN; 00990 if (*strp == ':') { 00991 ++strp; 00992 /* `SECSPERMIN' allows for leap seconds. */ 00993 strp = getnum(strp, &num, 0, SECSPERMIN); 00994 if (strp == NULL) 00995 return NULL; 00996 *secsp += num; 00997 } 00998 } 00999 return strp; 01000 }
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 907 of file localtime.c.
References is_digit.
Referenced by tzparse().
00908 { 00909 char c; 00910 00911 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && 00912 c != '+') 00913 ++strp; 00914 return strp; 00915 }
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 1677 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().
01678 { 01679 struct ast_tm * result; 01680 struct state *sp; 01681 01682 AST_LIST_LOCK(&zonelist); 01683 AST_LIST_TRAVERSE(&zonelist, sp, list) { 01684 if (!strcmp(sp->name, "UTC")) 01685 break; 01686 } 01687 01688 if (!sp) { 01689 if (!(sp = (struct state *) ast_calloc(1, sizeof *sp))) 01690 return NULL; 01691 gmtload(sp); 01692 AST_LIST_INSERT_TAIL(&zonelist, sp, list); 01693 } 01694 AST_LIST_UNLOCK(&zonelist); 01695 01696 result = timesub(timep, offset, sp, tmp); 01697 #ifdef TM_ZONE 01698 /* 01699 ** Could get fancy here and deliver something such as 01700 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, 01701 ** but this is no time for a treasure hunt. 01702 */ 01703 if (offset != 0) 01704 tmp->TM_ZONE = " "; 01705 else 01706 tmp->TM_ZONE = sp->chars; 01707 #endif /* defined TM_ZONE */ 01708 return result; 01709 }
static int increment_overflow | ( | int * | number, | |
int | delta | |||
) | [static] |
Simplified normalize logic courtesy Paul Eggert.
Definition at line 1860 of file localtime.c.
Referenced by normalize_overflow(), and timesub().
01861 { 01862 int number0; 01863 01864 number0 = *number; 01865 *number += delta; 01866 return (*number < number0) != (delta < 0); 01867 }
static void* inotify_daemon | ( | void * | data | ) | [static] |
Definition at line 271 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().
00272 { 00273 struct { 00274 struct inotify_event iev; 00275 char name[FILENAME_MAX + 1]; 00276 } buf; 00277 ssize_t res; 00278 struct state *cur; 00279 00280 inotify_fd = inotify_init(); 00281 00282 ast_mutex_lock(&initialization_lock); 00283 ast_cond_broadcast(&initialization); 00284 ast_mutex_unlock(&initialization_lock); 00285 00286 if (inotify_fd < 0) { 00287 ast_log(LOG_ERROR, "Cannot initialize file notification service: %s (%d)\n", strerror(errno), errno); 00288 inotify_thread = AST_PTHREADT_NULL; 00289 return NULL; 00290 } 00291 00292 for (;/*ever*/;) { 00293 /* This read should block, most of the time. */ 00294 if ((res = read(inotify_fd, &buf, sizeof(buf))) < sizeof(buf.iev) && res > 0) { 00295 /* This should never happen */ 00296 ast_log(LOG_ERROR, "Inotify read less than a full event (%zd < %zd)?!!\n", res, sizeof(buf.iev)); 00297 break; 00298 } else if (res < 0) { 00299 if (errno == EINTR || errno == EAGAIN) { 00300 /* If read fails, try again */ 00301 AST_LIST_LOCK(&zonelist); 00302 ast_cond_broadcast(&initialization); 00303 AST_LIST_UNLOCK(&zonelist); 00304 continue; 00305 } 00306 /* Sanity check -- this should never happen, either */ 00307 ast_log(LOG_ERROR, "Inotify failed: %s\n", strerror(errno)); 00308 break; 00309 } 00310 AST_LIST_LOCK(&zonelist); 00311 AST_LIST_TRAVERSE_SAFE_BEGIN(&zonelist, cur, list) { 00312 if (cur->wd[0] == buf.iev.wd || cur->wd[1] == buf.iev.wd) { 00313 AST_LIST_REMOVE_CURRENT(list); 00314 ast_free(cur); 00315 break; 00316 } 00317 } 00318 AST_LIST_TRAVERSE_SAFE_END 00319 ast_cond_broadcast(&initialization); 00320 AST_LIST_UNLOCK(&zonelist); 00321 } 00322 close(inotify_fd); 00323 inotify_thread = AST_PTHREADT_NULL; 00324 return NULL; 00325 }
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 1716 of file localtime.c.
Referenced by timesub().
01717 { 01718 return (y >= 0) ? (y / 4 - y / 100 + y / 400) : 01719 -(leaps_thru_end_of(-(y + 1)) + 1); 01720 }
static struct ast_tm* localsub | ( | const struct timeval * | timep, | |
const long | offset, | |||
struct ast_tm * | tmp, | |||
const struct state * | sp | |||
) | [static] |
Definition at line 1460 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().
01461 { 01462 const struct ttinfo * ttisp; 01463 int i; 01464 struct ast_tm * result; 01465 struct timeval t; 01466 memcpy(&t, timep, sizeof(t)); 01467 01468 if (sp == NULL) 01469 return gmtsub(timep, offset, tmp); 01470 if ((sp->goback && t.tv_sec < sp->ats[0]) || 01471 (sp->goahead && t.tv_sec > sp->ats[sp->timecnt - 1])) { 01472 struct timeval newt = t; 01473 time_t seconds; 01474 time_t tcycles; 01475 int_fast64_t icycles; 01476 01477 if (t.tv_sec < sp->ats[0]) 01478 seconds = sp->ats[0] - t.tv_sec; 01479 else seconds = t.tv_sec - sp->ats[sp->timecnt - 1]; 01480 --seconds; 01481 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; 01482 ++tcycles; 01483 icycles = tcycles; 01484 if (tcycles - icycles >= 1 || icycles - tcycles >= 1) 01485 return NULL; 01486 seconds = icycles; 01487 seconds *= YEARSPERREPEAT; 01488 seconds *= AVGSECSPERYEAR; 01489 if (t.tv_sec < sp->ats[0]) 01490 newt.tv_sec += seconds; 01491 else newt.tv_sec -= seconds; 01492 if (newt.tv_sec < sp->ats[0] || 01493 newt.tv_sec > sp->ats[sp->timecnt - 1]) 01494 return NULL; /* "cannot happen" */ 01495 result = localsub(&newt, offset, tmp, sp); 01496 if (result == tmp) { 01497 time_t newy; 01498 01499 newy = tmp->tm_year; 01500 if (t.tv_sec < sp->ats[0]) 01501 newy -= icycles * YEARSPERREPEAT; 01502 else 01503 newy += icycles * YEARSPERREPEAT; 01504 tmp->tm_year = newy; 01505 if (tmp->tm_year != newy) 01506 return NULL; 01507 } 01508 return result; 01509 } 01510 if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) { 01511 i = 0; 01512 while (sp->ttis[i].tt_isdst) { 01513 if (++i >= sp->typecnt) { 01514 i = 0; 01515 break; 01516 } 01517 } 01518 } else { 01519 int lo = 1; 01520 int hi = sp->timecnt; 01521 01522 while (lo < hi) { 01523 int mid = (lo + hi) >> 1; 01524 01525 if (t.tv_sec < sp->ats[mid]) 01526 hi = mid; 01527 else 01528 lo = mid + 1; 01529 } 01530 i = (int) sp->types[lo - 1]; 01531 } 01532 ttisp = &sp->ttis[i]; 01533 /* 01534 ** To get (wrong) behavior that's compatible with System V Release 2.0 01535 ** you'd replace the statement below with 01536 ** t += ttisp->tt_gmtoff; 01537 ** timesub(&t, 0L, sp, tmp); 01538 */ 01539 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); 01540 tmp->tm_isdst = ttisp->tt_isdst; 01541 #ifndef SOLARIS /* Solaris doesn't have this element */ 01542 tmp->tm_gmtoff = ttisp->tt_gmtoff; 01543 #endif 01544 #ifdef TM_ZONE 01545 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; 01546 #endif /* defined TM_ZONE */ 01547 tmp->tm_usec = timep->tv_usec; 01548 return result; 01549 }
static int long_increment_overflow | ( | long * | number, | |
int | delta | |||
) | [static] |
Definition at line 1869 of file localtime.c.
Referenced by long_normalize_overflow(), and time2sub().
01870 { 01871 long number0; 01872 01873 number0 = *number; 01874 *number += delta; 01875 return (*number < number0) != (delta < 0); 01876 }
static int long_normalize_overflow | ( | long * | tensptr, | |
int * | unitsptr, | |||
const int | base | |||
) | [static] |
Definition at line 1889 of file localtime.c.
References long_increment_overflow().
Referenced by time2sub().
01890 { 01891 int tensdelta; 01892 01893 tensdelta = (*unitsptr >= 0) ? 01894 (*unitsptr / base) : 01895 (-1 - (-1 - *unitsptr) / base); 01896 *unitsptr -= tensdelta * base; 01897 return long_increment_overflow(tensptr, tensdelta); 01898 }
static int normalize_overflow | ( | int * | tensptr, | |
int * | unitsptr, | |||
const int | base | |||
) | [static] |
Definition at line 1878 of file localtime.c.
References increment_overflow().
Referenced by time2sub().
01879 { 01880 int tensdelta; 01881 01882 tensdelta = (*unitsptr >= 0) ? 01883 (*unitsptr / base) : 01884 (-1 - (-1 - *unitsptr) / base); 01885 *unitsptr -= tensdelta * base; 01886 return increment_overflow(tensptr, tensdelta); 01887 }
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 2197 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().
02198 { 02199 struct locale_entry *cur; 02200 if (prevlocale == LC_GLOBAL_LOCALE) { 02201 return NULL; 02202 } else { 02203 /* Get a handle for this entry, if any */ 02204 if ((cur = find_by_locale(prevlocale))) { 02205 return cur->name; 02206 } else { 02207 /* Create an entry, so it can be restored later */ 02208 int x; 02209 cur = NULL; 02210 AST_LIST_LOCK(&localelist); 02211 for (x = 0; x < 10000; x++) { 02212 char name[5]; 02213 snprintf(name, sizeof(name), "%04d", x); 02214 if (!find_by_name(name)) { 02215 if ((cur = ast_calloc(1, sizeof(*cur) + strlen(name) + 1))) { 02216 cur->locale = prevlocale; 02217 strcpy(cur->name, name); /* SAFE */ 02218 AST_LIST_INSERT_TAIL(&localelist, cur, list); 02219 } 02220 break; 02221 } 02222 } 02223 AST_LIST_UNLOCK(&localelist); 02224 return cur ? cur->name : NULL; 02225 } 02226 } 02227 }
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 2101 of file localtime.c.
References FALSE, time2(), state::timecnt, TRUE, state::typecnt, state::types, and TZ_MAX_TYPES.
Referenced by ast_mktime().
02102 { 02103 struct timeval t; 02104 int samei, otheri; 02105 int sameind, otherind; 02106 int i; 02107 int nseen; 02108 int seen[TZ_MAX_TYPES]; 02109 int types[TZ_MAX_TYPES]; 02110 int okay; 02111 02112 if (tmp->tm_isdst > 1) 02113 tmp->tm_isdst = 1; 02114 t = time2(tmp, funcp, offset, &okay, sp); 02115 #ifdef PCTS 02116 /* 02117 ** PCTS code courtesy Grant Sullivan. 02118 */ 02119 if (okay) 02120 return t; 02121 if (tmp->tm_isdst < 0) 02122 tmp->tm_isdst = 0; /* reset to std and try again */ 02123 #endif /* defined PCTS */ 02124 #ifndef PCTS 02125 if (okay || tmp->tm_isdst < 0) 02126 return t; 02127 #endif /* !defined PCTS */ 02128 /* 02129 ** We're supposed to assume that somebody took a time of one type 02130 ** and did some math on it that yielded a "struct ast_tm" that's bad. 02131 ** We try to divine the type they started from and adjust to the 02132 ** type they need. 02133 */ 02134 if (sp == NULL) 02135 return WRONG; 02136 for (i = 0; i < sp->typecnt; ++i) 02137 seen[i] = FALSE; 02138 nseen = 0; 02139 for (i = sp->timecnt - 1; i >= 0; --i) 02140 if (!seen[sp->types[i]]) { 02141 seen[sp->types[i]] = TRUE; 02142 types[nseen++] = sp->types[i]; 02143 } 02144 for (sameind = 0; sameind < nseen; ++sameind) { 02145 samei = types[sameind]; 02146 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) 02147 continue; 02148 for (otherind = 0; otherind < nseen; ++otherind) { 02149 otheri = types[otherind]; 02150 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) 02151 continue; 02152 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - 02153 sp->ttis[samei].tt_gmtoff; 02154 tmp->tm_isdst = !tmp->tm_isdst; 02155 t = time2(tmp, funcp, offset, &okay, sp); 02156 if (okay) 02157 return t; 02158 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - 02159 sp->ttis[samei].tt_gmtoff; 02160 tmp->tm_isdst = !tmp->tm_isdst; 02161 } 02162 } 02163 return WRONG; 02164 }
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 2088 of file localtime.c.
References FALSE, time2sub(), and TRUE.
Referenced by time1().
02089 { 02090 struct timeval t; 02091 02092 /*! \note 02093 ** First try without normalization of seconds 02094 ** (in case tm_sec contains a value associated with a leap second). 02095 ** If that fails, try with normalization of seconds. 02096 */ 02097 t = time2sub(tmp, funcp, offset, okayp, FALSE, sp); 02098 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp); 02099 }
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 1914 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().
01915 { 01916 int dir; 01917 int i, j; 01918 int saved_seconds; 01919 long li; 01920 time_t lo; 01921 time_t hi; 01922 long y; 01923 struct timeval newt = { 0, 0 }; 01924 struct timeval t = { 0, 0 }; 01925 struct ast_tm yourtm, mytm; 01926 01927 *okayp = FALSE; 01928 yourtm = *tmp; 01929 if (do_norm_secs) { 01930 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, 01931 SECSPERMIN)) 01932 return WRONG; 01933 } 01934 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) 01935 return WRONG; 01936 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) 01937 return WRONG; 01938 y = yourtm.tm_year; 01939 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) 01940 return WRONG; 01941 /* 01942 ** Turn y into an actual year number for now. 01943 ** It is converted back to an offset from TM_YEAR_BASE later. 01944 */ 01945 if (long_increment_overflow(&y, TM_YEAR_BASE)) 01946 return WRONG; 01947 while (yourtm.tm_mday <= 0) { 01948 if (long_increment_overflow(&y, -1)) 01949 return WRONG; 01950 li = y + (1 < yourtm.tm_mon); 01951 yourtm.tm_mday += year_lengths[isleap(li)]; 01952 } 01953 while (yourtm.tm_mday > DAYSPERLYEAR) { 01954 li = y + (1 < yourtm.tm_mon); 01955 yourtm.tm_mday -= year_lengths[isleap(li)]; 01956 if (long_increment_overflow(&y, 1)) 01957 return WRONG; 01958 } 01959 for ( ; ; ) { 01960 i = mon_lengths[isleap(y)][yourtm.tm_mon]; 01961 if (yourtm.tm_mday <= i) 01962 break; 01963 yourtm.tm_mday -= i; 01964 if (++yourtm.tm_mon >= MONSPERYEAR) { 01965 yourtm.tm_mon = 0; 01966 if (long_increment_overflow(&y, 1)) 01967 return WRONG; 01968 } 01969 } 01970 if (long_increment_overflow(&y, -TM_YEAR_BASE)) 01971 return WRONG; 01972 yourtm.tm_year = y; 01973 if (yourtm.tm_year != y) 01974 return WRONG; 01975 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) 01976 saved_seconds = 0; 01977 else if (y + TM_YEAR_BASE < EPOCH_YEAR) { 01978 /* 01979 ** We can't set tm_sec to 0, because that might push the 01980 ** time below the minimum representable time. 01981 ** Set tm_sec to 59 instead. 01982 ** This assumes that the minimum representable time is 01983 ** not in the same minute that a leap second was deleted from, 01984 ** which is a safer assumption than using 58 would be. 01985 */ 01986 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) 01987 return WRONG; 01988 saved_seconds = yourtm.tm_sec; 01989 yourtm.tm_sec = SECSPERMIN - 1; 01990 } else { 01991 saved_seconds = yourtm.tm_sec; 01992 yourtm.tm_sec = 0; 01993 } 01994 /* 01995 ** Do a binary search (this works whatever time_t's type is). 01996 */ 01997 if (!TYPE_SIGNED(time_t)) { 01998 lo = 0; 01999 hi = lo - 1; 02000 } else if (!TYPE_INTEGRAL(time_t)) { 02001 if (sizeof(time_t) > sizeof(float)) 02002 hi = (time_t) DBL_MAX; 02003 else hi = (time_t) FLT_MAX; 02004 lo = -hi; 02005 } else { 02006 lo = 1; 02007 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) 02008 lo *= 2; 02009 hi = -(lo + 1); 02010 } 02011 for ( ; ; ) { 02012 t.tv_sec = lo / 2 + hi / 2; 02013 if (t.tv_sec < lo) 02014 t.tv_sec = lo; 02015 else if (t.tv_sec > hi) 02016 t.tv_sec = hi; 02017 if ((*funcp)(&t, offset, &mytm, sp) == NULL) { 02018 /* 02019 ** Assume that t is too extreme to be represented in 02020 ** a struct ast_tm; arrange things so that it is less 02021 ** extreme on the next pass. 02022 */ 02023 dir = (t.tv_sec > 0) ? 1 : -1; 02024 } else dir = tmcomp(&mytm, &yourtm); 02025 if (dir != 0) { 02026 if (t.tv_sec == lo) { 02027 ++t.tv_sec; 02028 if (t.tv_sec <= lo) 02029 return WRONG; 02030 ++lo; 02031 } else if (t.tv_sec == hi) { 02032 --t.tv_sec; 02033 if (t.tv_sec >= hi) 02034 return WRONG; 02035 --hi; 02036 } 02037 if (lo > hi) 02038 return WRONG; 02039 if (dir > 0) 02040 hi = t.tv_sec; 02041 else lo = t.tv_sec; 02042 continue; 02043 } 02044 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) 02045 break; 02046 /* 02047 ** Right time, wrong type. 02048 ** Hunt for right time, right type. 02049 ** It's okay to guess wrong since the guess 02050 ** gets checked. 02051 */ 02052 /* 02053 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. 02054 */ 02055 for (i = sp->typecnt - 1; i >= 0; --i) { 02056 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) 02057 continue; 02058 for (j = sp->typecnt - 1; j >= 0; --j) { 02059 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) 02060 continue; 02061 newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff - 02062 sp->ttis[i].tt_gmtoff; 02063 if ((*funcp)(&newt, offset, &mytm, sp) == NULL) 02064 continue; 02065 if (tmcomp(&mytm, &yourtm) != 0) 02066 continue; 02067 if (mytm.tm_isdst != yourtm.tm_isdst) 02068 continue; 02069 /* 02070 ** We have a match. 02071 */ 02072 t = newt; 02073 goto label; 02074 } 02075 } 02076 return WRONG; 02077 } 02078 label: 02079 newt.tv_sec = t.tv_sec + saved_seconds; 02080 if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0)) 02081 return WRONG; 02082 t.tv_sec = newt.tv_sec; 02083 if ((*funcp)(&t, offset, tmp, sp)) 02084 *okayp = TRUE; 02085 return t; 02086 }
static struct ast_tm* timesub | ( | const struct timeval * | timep, | |
const long | offset, | |||
const struct state * | sp, | |||
struct ast_tm * | tmp | |||
) | [static] |
Definition at line 1722 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().
01723 { 01724 const struct lsinfo * lp; 01725 time_t tdays; 01726 int idays; /* unsigned would be so 2003 */ 01727 long rem; 01728 int y; 01729 const int * ip; 01730 long corr; 01731 int hit; 01732 int i; 01733 long seconds; 01734 01735 01736 corr = 0; 01737 hit = 0; 01738 i = (sp == NULL) ? 0 : sp->leapcnt; 01739 while (--i >= 0) { 01740 lp = &sp->lsis[i]; 01741 if (timep->tv_sec >= lp->ls_trans) { 01742 if (timep->tv_sec == lp->ls_trans) { 01743 hit = ((i == 0 && lp->ls_corr > 0) || 01744 lp->ls_corr > sp->lsis[i - 1].ls_corr); 01745 if (hit) 01746 while (i > 0 && 01747 sp->lsis[i].ls_trans == 01748 sp->lsis[i - 1].ls_trans + 1 && 01749 sp->lsis[i].ls_corr == 01750 sp->lsis[i - 1].ls_corr + 1) { 01751 ++hit; 01752 --i; 01753 } 01754 } 01755 corr = lp->ls_corr; 01756 break; 01757 } 01758 } 01759 y = EPOCH_YEAR; 01760 tdays = timep->tv_sec / SECSPERDAY; 01761 rem = timep->tv_sec - tdays * SECSPERDAY; 01762 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { 01763 int newy; 01764 time_t tdelta; 01765 int idelta; 01766 int leapdays; 01767 01768 tdelta = tdays / DAYSPERLYEAR; 01769 idelta = tdelta; 01770 if (tdelta - idelta >= 1 || idelta - tdelta >= 1) 01771 return NULL; 01772 if (idelta == 0) 01773 idelta = (tdays < 0) ? -1 : 1; 01774 newy = y; 01775 if (increment_overflow(&newy, idelta)) 01776 return NULL; 01777 leapdays = leaps_thru_end_of(newy - 1) - 01778 leaps_thru_end_of(y - 1); 01779 tdays -= ((time_t) newy - y) * DAYSPERNYEAR; 01780 tdays -= leapdays; 01781 y = newy; 01782 } 01783 01784 seconds = tdays * SECSPERDAY + 0.5; 01785 tdays = seconds / SECSPERDAY; 01786 rem += seconds - tdays * SECSPERDAY; 01787 01788 /* 01789 ** Given the range, we can now fearlessly cast... 01790 */ 01791 idays = tdays; 01792 rem += offset - corr; 01793 while (rem < 0) { 01794 rem += SECSPERDAY; 01795 --idays; 01796 } 01797 while (rem >= SECSPERDAY) { 01798 rem -= SECSPERDAY; 01799 ++idays; 01800 } 01801 while (idays < 0) { 01802 if (increment_overflow(&y, -1)) 01803 return NULL; 01804 idays += year_lengths[isleap(y)]; 01805 } 01806 while (idays >= year_lengths[isleap(y)]) { 01807 idays -= year_lengths[isleap(y)]; 01808 if (increment_overflow(&y, 1)) 01809 return NULL; 01810 } 01811 tmp->tm_year = y; 01812 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) 01813 return NULL; 01814 tmp->tm_yday = idays; 01815 /* 01816 ** The "extra" mods below avoid overflow problems. 01817 */ 01818 tmp->tm_wday = EPOCH_WDAY + 01819 ((y - EPOCH_YEAR) % DAYSPERWEEK) * 01820 (DAYSPERNYEAR % DAYSPERWEEK) + 01821 leaps_thru_end_of(y - 1) - 01822 leaps_thru_end_of(EPOCH_YEAR - 1) + 01823 idays; 01824 tmp->tm_wday %= DAYSPERWEEK; 01825 if (tmp->tm_wday < 0) 01826 tmp->tm_wday += DAYSPERWEEK; 01827 tmp->tm_hour = (int) (rem / SECSPERHOUR); 01828 rem %= SECSPERHOUR; 01829 tmp->tm_min = (int) (rem / SECSPERMIN); 01830 /* 01831 ** A positive leap second requires a special 01832 ** representation. This uses "... ??:59:60" et seq. 01833 */ 01834 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; 01835 ip = mon_lengths[isleap(y)]; 01836 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon)) 01837 idays -= ip[tmp->tm_mon]; 01838 tmp->tm_mday = (int) (idays + 1); 01839 tmp->tm_isdst = 0; 01840 #ifdef TM_GMTOFF 01841 tmp->TM_GMTOFF = offset; 01842 #endif /* defined TM_GMTOFF */ 01843 tmp->tm_usec = timep->tv_usec; 01844 return tmp; 01845 }
Definition at line 1900 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.
01901 { 01902 int result; 01903 01904 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && 01905 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && 01906 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && 01907 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && 01908 (result = (atmp->tm_min - btmp->tm_min)) == 0 && 01909 (result = (atmp->tm_sec - btmp->tm_sec)) == 0) 01910 result = atmp->tm_usec - btmp->tm_usec; 01911 return result; 01912 }
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 1084 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().
01085 { 01086 int leapyear; 01087 time_t value; 01088 int i; 01089 int d, m1, yy0, yy1, yy2, dow; 01090 01091 INITIALIZE(value); 01092 leapyear = isleap(year); 01093 switch (rulep->r_type) { 01094 01095 case JULIAN_DAY: 01096 /* 01097 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap 01098 ** years. 01099 ** In non-leap years, or if the day number is 59 or less, just 01100 ** add SECSPERDAY times the day number-1 to the time of 01101 ** January 1, midnight, to get the day. 01102 */ 01103 value = janfirst + (rulep->r_day - 1) * SECSPERDAY; 01104 if (leapyear && rulep->r_day >= 60) 01105 value += SECSPERDAY; 01106 break; 01107 01108 case DAY_OF_YEAR: 01109 /* 01110 ** n - day of year. 01111 ** Just add SECSPERDAY times the day number to the time of 01112 ** January 1, midnight, to get the day. 01113 */ 01114 value = janfirst + rulep->r_day * SECSPERDAY; 01115 break; 01116 01117 case MONTH_NTH_DAY_OF_WEEK: 01118 /* 01119 ** Mm.n.d - nth "dth day" of month m. 01120 */ 01121 value = janfirst; 01122 for (i = 0; i < rulep->r_mon - 1; ++i) 01123 value += mon_lengths[leapyear][i] * SECSPERDAY; 01124 01125 /* 01126 ** Use Zeller's Congruence to get day-of-week of first day of 01127 ** month. 01128 */ 01129 m1 = (rulep->r_mon + 9) % 12 + 1; 01130 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; 01131 yy1 = yy0 / 100; 01132 yy2 = yy0 % 100; 01133 dow = ((26 * m1 - 2) / 10 + 01134 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; 01135 if (dow < 0) 01136 dow += DAYSPERWEEK; 01137 01138 /* 01139 ** "dow" is the day-of-week of the first day of the month. Get 01140 ** the day-of-month (zero-origin) of the first "dow" day of the 01141 ** month. 01142 */ 01143 d = rulep->r_day - dow; 01144 if (d < 0) 01145 d += DAYSPERWEEK; 01146 for (i = 1; i < rulep->r_week; ++i) { 01147 if (d + DAYSPERWEEK >= 01148 mon_lengths[leapyear][rulep->r_mon - 1]) 01149 break; 01150 d += DAYSPERWEEK; 01151 } 01152 01153 /* 01154 ** "d" is the day-of-month (zero-origin) of the day we want. 01155 */ 01156 value += d * SECSPERDAY; 01157 break; 01158 } 01159 01160 /* 01161 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in 01162 ** question. To get the Epoch-relative time of the specified local 01163 ** time on that day, add the transition time and the current offset 01164 ** from UTC. 01165 */ 01166 return value + rulep->r_time + offset; 01167 }
static int tzload | ( | const char * | name, | |
struct state *const | sp, | |||
const int | doextend | |||
) | [static] |
Definition at line 661 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().
00662 { 00663 const char * p; 00664 int i; 00665 int fid; 00666 int stored; 00667 int nread; 00668 union { 00669 struct tzhead tzhead; 00670 char buf[2 * sizeof(struct tzhead) + 00671 2 * sizeof *sp + 00672 4 * TZ_MAX_TIMES]; 00673 } u; 00674 00675 if (name == NULL && (name = TZDEFAULT) == NULL) 00676 return -1; 00677 { 00678 int doaccess; 00679 /* 00680 ** Section 4.9.1 of the C standard says that 00681 ** "FILENAME_MAX expands to an integral constant expression 00682 ** that is the size needed for an array of char large enough 00683 ** to hold the longest file name string that the implementation 00684 ** guarantees can be opened." 00685 */ 00686 char fullname[FILENAME_MAX + 1]; 00687 00688 if (name[0] == ':') 00689 ++name; 00690 doaccess = name[0] == '/'; 00691 if (!doaccess) { 00692 if ((p = TZDIR) == NULL) 00693 return -1; 00694 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) 00695 return -1; 00696 (void) strcpy(fullname, p); 00697 (void) strcat(fullname, "/"); 00698 (void) strcat(fullname, name); 00699 /* 00700 ** Set doaccess if '.' (as in "../") shows up in name. 00701 */ 00702 if (strchr(name, '.') != NULL) 00703 doaccess = TRUE; 00704 name = fullname; 00705 } 00706 if (doaccess && access(name, R_OK) != 0) 00707 return -1; 00708 if ((fid = open(name, OPEN_MODE)) == -1) 00709 return -1; 00710 add_notify(sp, name); 00711 } 00712 nread = read(fid, u.buf, sizeof u.buf); 00713 if (close(fid) < 0 || nread <= 0) 00714 return -1; 00715 for (stored = 4; stored <= 8; stored *= 2) { 00716 int ttisstdcnt; 00717 int ttisgmtcnt; 00718 00719 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); 00720 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); 00721 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); 00722 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); 00723 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); 00724 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); 00725 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; 00726 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || 00727 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || 00728 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || 00729 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || 00730 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || 00731 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) 00732 return -1; 00733 if (nread - (p - u.buf) < 00734 sp->timecnt * stored + /* ats */ 00735 sp->timecnt + /* types */ 00736 sp->typecnt * 6 + /* ttinfos */ 00737 sp->charcnt + /* chars */ 00738 sp->leapcnt * (stored + 4) + /* lsinfos */ 00739 ttisstdcnt + /* ttisstds */ 00740 ttisgmtcnt) /* ttisgmts */ 00741 return -1; 00742 for (i = 0; i < sp->timecnt; ++i) { 00743 sp->ats[i] = (stored == 4) ? 00744 detzcode(p) : detzcode64(p); 00745 p += stored; 00746 } 00747 for (i = 0; i < sp->timecnt; ++i) { 00748 sp->types[i] = (unsigned char) *p++; 00749 if (sp->types[i] >= sp->typecnt) 00750 return -1; 00751 } 00752 for (i = 0; i < sp->typecnt; ++i) { 00753 struct ttinfo * ttisp; 00754 00755 ttisp = &sp->ttis[i]; 00756 ttisp->tt_gmtoff = detzcode(p); 00757 p += 4; 00758 ttisp->tt_isdst = (unsigned char) *p++; 00759 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) 00760 return -1; 00761 ttisp->tt_abbrind = (unsigned char) *p++; 00762 if (ttisp->tt_abbrind < 0 || 00763 ttisp->tt_abbrind > sp->charcnt) 00764 return -1; 00765 } 00766 for (i = 0; i < sp->charcnt; ++i) 00767 sp->chars[i] = *p++; 00768 sp->chars[i] = '\0'; /* ensure '\0' at end */ 00769 for (i = 0; i < sp->leapcnt; ++i) { 00770 struct lsinfo * lsisp; 00771 00772 lsisp = &sp->lsis[i]; 00773 lsisp->ls_trans = (stored == 4) ? 00774 detzcode(p) : detzcode64(p); 00775 p += stored; 00776 lsisp->ls_corr = detzcode(p); 00777 p += 4; 00778 } 00779 for (i = 0; i < sp->typecnt; ++i) { 00780 struct ttinfo * ttisp; 00781 00782 ttisp = &sp->ttis[i]; 00783 if (ttisstdcnt == 0) 00784 ttisp->tt_ttisstd = FALSE; 00785 else { 00786 ttisp->tt_ttisstd = *p++; 00787 if (ttisp->tt_ttisstd != TRUE && 00788 ttisp->tt_ttisstd != FALSE) 00789 return -1; 00790 } 00791 } 00792 for (i = 0; i < sp->typecnt; ++i) { 00793 struct ttinfo * ttisp; 00794 00795 ttisp = &sp->ttis[i]; 00796 if (ttisgmtcnt == 0) 00797 ttisp->tt_ttisgmt = FALSE; 00798 else { 00799 ttisp->tt_ttisgmt = *p++; 00800 if (ttisp->tt_ttisgmt != TRUE && 00801 ttisp->tt_ttisgmt != FALSE) 00802 return -1; 00803 } 00804 } 00805 /* 00806 ** Out-of-sort ats should mean we're running on a 00807 ** signed time_t system but using a data file with 00808 ** unsigned values (or vice versa). 00809 */ 00810 for (i = 0; i < sp->timecnt - 2; ++i) 00811 if (sp->ats[i] > sp->ats[i + 1]) { 00812 ++i; 00813 if (TYPE_SIGNED(time_t)) { 00814 /* 00815 ** Ignore the end (easy). 00816 */ 00817 sp->timecnt = i; 00818 } else { 00819 /* 00820 ** Ignore the beginning (harder). 00821 */ 00822 int j; 00823 00824 for (j = 0; j + i < sp->timecnt; ++j) { 00825 sp->ats[j] = sp->ats[j + i]; 00826 sp->types[j] = sp->types[j + i]; 00827 } 00828 sp->timecnt = j; 00829 } 00830 break; 00831 } 00832 /* 00833 ** If this is an old file, we're done. 00834 */ 00835 if (u.tzhead.tzh_version[0] == '\0') 00836 break; 00837 nread -= p - u.buf; 00838 for (i = 0; i < nread; ++i) 00839 u.buf[i] = p[i]; 00840 /* 00841 ** If this is a narrow integer time_t system, we're done. 00842 */ 00843 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t)) 00844 break; 00845 } 00846 if (doextend && nread > 2 && 00847 u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && 00848 sp->typecnt + 2 <= TZ_MAX_TYPES) { 00849 struct state ts; 00850 int result; 00851 00852 u.buf[nread - 1] = '\0'; 00853 result = tzparse(&u.buf[1], &ts, FALSE); 00854 if (result == 0 && ts.typecnt == 2 && 00855 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { 00856 for (i = 0; i < 2; ++i) 00857 ts.ttis[i].tt_abbrind += 00858 sp->charcnt; 00859 for (i = 0; i < ts.charcnt; ++i) 00860 sp->chars[sp->charcnt++] = 00861 ts.chars[i]; 00862 i = 0; 00863 while (i < ts.timecnt && 00864 ts.ats[i] <= 00865 sp->ats[sp->timecnt - 1]) 00866 ++i; 00867 while (i < ts.timecnt && 00868 sp->timecnt < TZ_MAX_TIMES) { 00869 sp->ats[sp->timecnt] = 00870 ts.ats[i]; 00871 sp->types[sp->timecnt] = 00872 sp->typecnt + 00873 ts.types[i]; 00874 ++sp->timecnt; 00875 ++i; 00876 } 00877 sp->ttis[sp->typecnt++] = ts.ttis[0]; 00878 sp->ttis[sp->typecnt++] = ts.ttis[1]; 00879 } 00880 } 00881 i = 2 * YEARSPERREPEAT; 00882 sp->goback = sp->goahead = sp->timecnt > i; 00883 sp->goback = sp->goback && sp->types[i] == sp->types[0] && 00884 differ_by_repeat(sp->ats[i], sp->ats[0]); 00885 sp->goahead = sp->goahead && 00886 sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] && 00887 differ_by_repeat(sp->ats[sp->timecnt - 1], 00888 sp->ats[sp->timecnt - 1 - i]); 00889 return 0; 00890 }
static int tzparse | ( | const char * | name, | |
struct state * | sp, | |||
const int | lastditch | |||
) | [static] |
Definition at line 1174 of file localtime.c.
References state::ats, state::chars, EPOCH_YEAR, FALSE, getoffset(), getqzname(), getrule(), getzname(), INITIALIZE, isleap, state::leapcnt, SECSPERDAY, SECSPERHOUR, 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().
01175 { 01176 const char * stdname; 01177 const char * dstname; 01178 size_t stdlen; 01179 size_t dstlen; 01180 long stdoffset; 01181 long dstoffset; 01182 time_t * atp; 01183 unsigned char * typep; 01184 char * cp; 01185 int load_result; 01186 01187 INITIALIZE(dstname); 01188 stdname = name; 01189 if (lastditch) { 01190 stdlen = strlen(name); /* length of standard zone name */ 01191 name += stdlen; 01192 if (stdlen >= sizeof sp->chars) 01193 stdlen = (sizeof sp->chars) - 1; 01194 stdoffset = 0; 01195 } else { 01196 if (*name == '<') { 01197 name++; 01198 stdname = name; 01199 name = getqzname(name, '>'); 01200 if (*name != '>') 01201 return -1; 01202 stdlen = name - stdname; 01203 name++; 01204 } else { 01205 name = getzname(name); 01206 stdlen = name - stdname; 01207 } 01208 if (*name == '\0') 01209 return -1; 01210 name = getoffset(name, &stdoffset); 01211 if (name == NULL) 01212 return -1; 01213 } 01214 load_result = tzload(TZDEFRULES, sp, FALSE); 01215 if (load_result != 0) 01216 sp->leapcnt = 0; /* so, we're off a little */ 01217 if (*name != '\0') { 01218 if (*name == '<') { 01219 dstname = ++name; 01220 name = getqzname(name, '>'); 01221 if (*name != '>') 01222 return -1; 01223 dstlen = name - dstname; 01224 name++; 01225 } else { 01226 dstname = name; 01227 name = getzname(name); 01228 dstlen = name - dstname; /* length of DST zone name */ 01229 } 01230 if (*name != '\0' && *name != ',' && *name != ';') { 01231 name = getoffset(name, &dstoffset); 01232 if (name == NULL) 01233 return -1; 01234 } else dstoffset = stdoffset - SECSPERHOUR; 01235 if (*name == '\0' && load_result != 0) 01236 name = TZDEFRULESTRING; 01237 if (*name == ',' || *name == ';') { 01238 struct rule start; 01239 struct rule end; 01240 int year; 01241 time_t janfirst; 01242 time_t starttime; 01243 time_t endtime; 01244 01245 ++name; 01246 if ((name = getrule(name, &start)) == NULL) 01247 return -1; 01248 if (*name++ != ',') 01249 return -1; 01250 if ((name = getrule(name, &end)) == NULL) 01251 return -1; 01252 if (*name != '\0') 01253 return -1; 01254 sp->typecnt = 2; /* standard time and DST */ 01255 /* 01256 ** Two transitions per year, from EPOCH_YEAR forward. 01257 */ 01258 sp->ttis[0].tt_gmtoff = -dstoffset; 01259 sp->ttis[0].tt_isdst = 1; 01260 sp->ttis[0].tt_abbrind = stdlen + 1; 01261 sp->ttis[1].tt_gmtoff = -stdoffset; 01262 sp->ttis[1].tt_isdst = 0; 01263 sp->ttis[1].tt_abbrind = 0; 01264 atp = sp->ats; 01265 typep = sp->types; 01266 janfirst = 0; 01267 sp->timecnt = 0; 01268 for (year = EPOCH_YEAR; 01269 sp->timecnt + 2 <= TZ_MAX_TIMES; 01270 ++year) { 01271 time_t newfirst; 01272 01273 starttime = transtime(janfirst, year, &start, 01274 stdoffset); 01275 endtime = transtime(janfirst, year, &end, 01276 dstoffset); 01277 if (starttime > endtime) { 01278 *atp++ = endtime; 01279 *typep++ = 1; /* DST ends */ 01280 *atp++ = starttime; 01281 *typep++ = 0; /* DST begins */ 01282 } else { 01283 *atp++ = starttime; 01284 *typep++ = 0; /* DST begins */ 01285 *atp++ = endtime; 01286 *typep++ = 1; /* DST ends */ 01287 } 01288 sp->timecnt += 2; 01289 newfirst = janfirst; 01290 newfirst += year_lengths[isleap(year)] * 01291 SECSPERDAY; 01292 if (newfirst <= janfirst) 01293 break; 01294 janfirst = newfirst; 01295 } 01296 } else { 01297 long theirstdoffset; 01298 long theirdstoffset; 01299 long theiroffset; 01300 int isdst; 01301 int i; 01302 int j; 01303 01304 if (*name != '\0') 01305 return -1; 01306 /* 01307 ** Initial values of theirstdoffset and theirdstoffset. 01308 */ 01309 theirstdoffset = 0; 01310 for (i = 0; i < sp->timecnt; ++i) { 01311 j = sp->types[i]; 01312 if (!sp->ttis[j].tt_isdst) { 01313 theirstdoffset = 01314 -sp->ttis[j].tt_gmtoff; 01315 break; 01316 } 01317 } 01318 theirdstoffset = 0; 01319 for (i = 0; i < sp->timecnt; ++i) { 01320 j = sp->types[i]; 01321 if (sp->ttis[j].tt_isdst) { 01322 theirdstoffset = 01323 -sp->ttis[j].tt_gmtoff; 01324 break; 01325 } 01326 } 01327 /* 01328 ** Initially we're assumed to be in standard time. 01329 */ 01330 isdst = FALSE; 01331 theiroffset = theirstdoffset; 01332 /* 01333 ** Now juggle transition times and types 01334 ** tracking offsets as you do. 01335 */ 01336 for (i = 0; i < sp->timecnt; ++i) { 01337 j = sp->types[i]; 01338 sp->types[i] = sp->ttis[j].tt_isdst; 01339 if (sp->ttis[j].tt_ttisgmt) { 01340 /* No adjustment to transition time */ 01341 } else { 01342 /* 01343 ** If summer time is in effect, and the 01344 ** transition time was not specified as 01345 ** standard time, add the summer time 01346 ** offset to the transition time; 01347 ** otherwise, add the standard time 01348 ** offset to the transition time. 01349 */ 01350 /* 01351 ** Transitions from DST to DDST 01352 ** will effectively disappear since 01353 ** POSIX provides for only one DST 01354 ** offset. 01355 */ 01356 if (isdst && !sp->ttis[j].tt_ttisstd) { 01357 sp->ats[i] += dstoffset - 01358 theirdstoffset; 01359 } else { 01360 sp->ats[i] += stdoffset - 01361 theirstdoffset; 01362 } 01363 } 01364 theiroffset = -sp->ttis[j].tt_gmtoff; 01365 if (sp->ttis[j].tt_isdst) 01366 theirdstoffset = theiroffset; 01367 else theirstdoffset = theiroffset; 01368 } 01369 /* 01370 ** Finally, fill in ttis. 01371 ** ttisstd and ttisgmt need not be handled. 01372 */ 01373 sp->ttis[0].tt_gmtoff = -stdoffset; 01374 sp->ttis[0].tt_isdst = FALSE; 01375 sp->ttis[0].tt_abbrind = 0; 01376 sp->ttis[1].tt_gmtoff = -dstoffset; 01377 sp->ttis[1].tt_isdst = TRUE; 01378 sp->ttis[1].tt_abbrind = stdlen + 1; 01379 sp->typecnt = 2; 01380 } 01381 } else { 01382 dstlen = 0; 01383 sp->typecnt = 1; /* only standard time */ 01384 sp->timecnt = 0; 01385 sp->ttis[0].tt_gmtoff = -stdoffset; 01386 sp->ttis[0].tt_isdst = 0; 01387 sp->ttis[0].tt_abbrind = 0; 01388 } 01389 sp->charcnt = stdlen + 1; 01390 if (dstlen != 0) 01391 sp->charcnt += dstlen + 1; 01392 if ((size_t) sp->charcnt > sizeof sp->chars) 01393 return -1; 01394 cp = sp->chars; 01395 (void) strncpy(cp, stdname, stdlen); 01396 cp += stdlen; 01397 *cp++ = '\0'; 01398 if (dstlen != 0) { 01399 (void) strncpy(cp, dstname, dstlen); 01400 *(cp + dstlen) = '\0'; 01401 } 01402 return 0; 01403 }
char elsieid[] = "@(#)localtime.c 8.5" [static] |
Definition at line 83 of file localtime.c.
const char gmt[] = "GMT" [static] |
Definition at line 111 of file localtime.c.
ast_cond_t initialization [static] |
Definition at line 266 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 265 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 892 of file localtime.c.
Referenced by time2sub(), and timesub().
struct timeval WRONG = { 0, 0 } [static] |
Definition at line 112 of file localtime.c.
const int year_lengths[2] [static] |
Initial value:
{ DAYSPERNYEAR, DAYSPERLYEAR }
Definition at line 897 of file localtime.c.
Referenced by time2sub(), and timesub().