#include "asterisk.h"#include <sys/stat.h>#include <fcntl.h>#include <float.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"

Go to the source code of this file.
Data Structures | |
| struct | lsinfo |
| leap second information More... | |
| struct | rule |
| struct | state |
| struct | ttinfo |
| time type information More... | |
| struct | zonelist |
Defines | |
| #define | BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) |
| #define | DAY_OF_YEAR 1 |
| #define | JULIAN_DAY 0 |
| #define | MONTH_NTH_DAY_OF_WEEK 2 |
| #define | MY_TZNAME_MAX 255 |
| #define | OPEN_MODE O_RDONLY |
| #define | TZ_ABBR_CHAR_SET "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" |
| #define | TZ_ABBR_ERR_CHAR '_' |
| #define | TZ_ABBR_MAX_LEN 16 |
| #define | TZ_STRLEN_MAX 255 |
| #define | TZDEFRULESTRING ",M4.1.0,M10.5.0" |
Functions | |
| static void | add_notify (struct state *sp, const char *path) |
| void | ast_get_dst_info (const time_t *const timep, int *dst_enabled, time_t *dst_start, time_t *dst_end, int *gmt_off, const char *const zone) |
| struct ast_tm * | ast_localtime (const struct timeval *timep, struct ast_tm *tmp, const char *zone) |
| Timezone-independent version of localtime_r(3). | |
| struct timeval | ast_mktime (struct ast_tm *tmp, const char *zone) |
| Timezone-independent version of mktime(3). | |
| 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. | |
| 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. | |
| 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 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 struct timeval | time1 (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, const struct state *sp) |
| static struct timeval | time2 (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), const long offset, int *okayp, const struct state *sp) |
| static struct timeval | time2sub (struct ast_tm *tmp, struct ast_tm *(*const funcp)(const struct timeval *, long, struct ast_tm *, const struct state *), const long offset, int *okayp, const int do_norm_secs, const struct state *sp) |
| static struct ast_tm * | timesub (const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp) |
| static int | tmcomp (const struct ast_tm *atmp, const struct ast_tm *btmp) |
| static time_t | transtime (const time_t janfirst, const int year, const struct rule *rulep, const long offset) |
| Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the year, a rule, and the offset from UTC at the time that rule takes effect, calculate the Epoch-relative time that rule takes effect. | |
| static int | tzload (const char *name, struct state *const sp, const int doextend) |
| static int | tzparse (const char *name, struct state *sp, const int lastditch) |
Variables | |
| static char | elsieid [] = "@(#)localtime.c 8.5" |
| static const char | gmt [] = "GMT" |
| static ast_cond_t | initialization |
| static ast_mutex_t | initialization_lock |
| static int | inotify_fd = -1 |
| static pthread_t | inotify_thread = AST_PTHREADT_NULL |
| static const int | mon_lengths [2][MONSPERYEAR] |
| static struct timeval | WRONG = { 0, 0 } |
| static const int | year_lengths [2] |
Multi-timezone Localtime code
The original source from this file may be obtained from ftp://elsie.nci.nih.gov/pub/
Definition in file localtime.c.
| #define BIGGEST | ( | a, | |||
| b | ) | (((a) > (b)) ? (a) : (b)) |
Definition at line 126 of file localtime.c.
| #define DAY_OF_YEAR 1 |
Definition at line 170 of file localtime.c.
Referenced by getrule(), and transtime().
| #define JULIAN_DAY 0 |
Definition at line 169 of file localtime.c.
Referenced by getrule(), and transtime().
| #define MONTH_NTH_DAY_OF_WEEK 2 |
Definition at line 171 of file localtime.c.
Referenced by getrule(), and transtime().
| #define MY_TZNAME_MAX 255 |
Definition at line 132 of file localtime.c.
| #define OPEN_MODE O_RDONLY |
Definition at line 94 of file localtime.c.
Referenced by tzload().
| #define TZ_ABBR_CHAR_SET "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" |
Definition at line 78 of file localtime.c.
| #define TZ_ABBR_ERR_CHAR '_' |
Definition at line 83 of file localtime.c.
| #define TZ_ABBR_MAX_LEN 16 |
Definition at line 74 of file localtime.c.
| #define TZ_STRLEN_MAX 255 |
Definition at line 135 of file localtime.c.
| #define TZDEFRULESTRING ",M4.1.0,M10.5.0" |
Definition at line 108 of file localtime.c.
Referenced by tzparse().
| static void add_notify | ( | struct state * | sp, | |
| const char * | path | |||
| ) | [static] |
Definition at line 288 of file localtime.c.
References ast_cond_init(), ast_cond_wait(), ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, initialization, initialization_lock, inotify_daemon(), inotify_fd, inotify_thread, LOG_ERROR, and state::wd.
Referenced by tzload().
00289 { 00290 if (inotify_thread == AST_PTHREADT_NULL) { 00291 ast_cond_init(&initialization, NULL); 00292 ast_mutex_init(&initialization_lock); 00293 ast_mutex_lock(&initialization_lock); 00294 if (!(ast_pthread_create_background(&inotify_thread, NULL, inotify_daemon, NULL))) { 00295 /* Give the thread a chance to initialize */ 00296 ast_cond_wait(&initialization, &initialization_lock); 00297 } else { 00298 ast_log(LOG_ERROR, "Unable to start notification thread\n"); 00299 ast_mutex_unlock(&initialization_lock); 00300 return; 00301 } 00302 ast_mutex_unlock(&initialization_lock); 00303 } 00304 00305 if (inotify_fd > -1) { 00306 char fullpath[FILENAME_MAX + 1] = ""; 00307 if (readlink(path, fullpath, sizeof(fullpath) - 1) != -1) { 00308 /* If file the symlink points to changes */ 00309 sp->wd[1] = inotify_add_watch(inotify_fd, fullpath, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE ); 00310 } else { 00311 sp->wd[1] = -1; 00312 } 00313 /* or if the symlink itself changes (or the real file is here, if path is not a symlink) */ 00314 sp->wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE 00315 #ifdef IN_DONT_FOLLOW /* Only defined in glibc 2.5 and above */ 00316 | IN_DONT_FOLLOW 00317 #endif 00318 ); 00319 } 00320 }
| 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 1320 of file localtime.c.
References ast_tzset(), state::ats, state::goahead, state::goback, state::timecnt, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, and state::types.
Referenced by set_timezone_variables().
01321 { 01322 int i; 01323 int transition1 = -1; 01324 int transition2 = -1; 01325 time_t seconds; 01326 int bounds_exceeded = 0; 01327 time_t t = *timep; 01328 const struct state *sp; 01329 01330 if (NULL == dst_enabled) 01331 return; 01332 *dst_enabled = 0; 01333 01334 if (NULL == dst_start || NULL == dst_end || NULL == gmt_off) 01335 return; 01336 01337 *gmt_off = 0; 01338 01339 sp = ast_tzset(zone); 01340 if (NULL == sp) 01341 return; 01342 01343 /* If the desired time exceeds the bounds of the defined time transitions 01344 * then give give up on determining DST info and simply look for gmt offset 01345 * This requires that I adjust the given time using increments of Gregorian 01346 * repeats to place the time within the defined time transitions in the 01347 * timezone structure. 01348 */ 01349 if ((sp->goback && t < sp->ats[0]) || 01350 (sp->goahead && t > sp->ats[sp->timecnt - 1])) { 01351 time_t tcycles; 01352 int_fast64_t icycles; 01353 01354 if (t < sp->ats[0]) 01355 seconds = sp->ats[0] - t; 01356 else seconds = t - sp->ats[sp->timecnt - 1]; 01357 --seconds; 01358 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; 01359 ++tcycles; 01360 icycles = tcycles; 01361 if (tcycles - icycles >= 1 || icycles - tcycles >= 1) 01362 return; 01363 seconds = icycles; 01364 seconds *= YEARSPERREPEAT; 01365 seconds *= AVGSECSPERYEAR; 01366 if (t < sp->ats[0]) 01367 t += seconds; 01368 else 01369 t -= seconds; 01370 01371 if (t < sp->ats[0] || t > sp->ats[sp->timecnt - 1]) 01372 return; /* "cannot happen" */ 01373 01374 bounds_exceeded = 1; 01375 } 01376 01377 if (sp->timecnt == 0 || t < sp->ats[0]) { 01378 /* I have no transition times or I'm before time */ 01379 *dst_enabled = 0; 01380 /* Find where I can get gmtoff */ 01381 i = 0; 01382 while (sp->ttis[i].tt_isdst) 01383 if (++i >= sp->typecnt) { 01384 i = 0; 01385 break; 01386 } 01387 *gmt_off = sp->ttis[i].tt_gmtoff; 01388 return; 01389 } 01390 01391 for (i = 1; i < sp->timecnt; ++i) { 01392 if (t < sp->ats[i]) { 01393 transition1 = sp->types[i - 1]; 01394 transition2 = sp->types[i]; 01395 break; 01396 } 01397 } 01398 /* if I found transition times that do not bounded the given time and these correspond to 01399 or the bounding zones do not reflect a changes in day light savings, then I do not have dst active */ 01400 if (i >= sp->timecnt || 0 > transition1 || 0 > transition2 || 01401 (sp->ttis[transition1].tt_isdst == sp->ttis[transition2].tt_isdst)) { 01402 *dst_enabled = 0; 01403 *gmt_off = sp->ttis[sp->types[sp->timecnt -1]].tt_gmtoff; 01404 } else { 01405 /* I have valid daylight savings information. */ 01406 if(sp->ttis[transition2].tt_isdst) 01407 *gmt_off = sp->ttis[transition1].tt_gmtoff; 01408 else 01409 *gmt_off = sp->ttis[transition2].tt_gmtoff; 01410 01411 /* If I adjusted the time earlier, indicate that the dst is invalid */ 01412 if (!bounds_exceeded) { 01413 *dst_enabled = 1; 01414 /* Determine which of the bounds is the start of daylight savings and which is the end */ 01415 if(sp->ttis[transition2].tt_isdst) { 01416 *dst_start = sp->ats[i]; 01417 *dst_end = sp->ats[i -1]; 01418 } else { 01419 *dst_start = sp->ats[i -1]; 01420 *dst_end = sp->ats[i]; 01421 } 01422 } 01423 } 01424 return; 01425 }
| struct ast_tm* ast_localtime | ( | const struct timeval * | timep, | |
| struct ast_tm * | p_tm, | |||
| const char * | zone | |||
| ) | [read] |
Timezone-independent version of localtime_r(3).
| timep | Current time, including microseconds | |
| p_tm | Pointer to memory where the broken-out time will be stored | |
| zone | Text string of a standard system zoneinfo file. If NULL, the system localtime will be used. |
| p_tm | is returned for convenience |
Definition at line 1305 of file localtime.c.
References ast_tzset(), and localsub().
Referenced by __ast_verbose_ap(), acf_strftime(), action_corestatus(), append_date(), ast_check_timing(), ast_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_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(), execute_cb(), find_conf_realtime(), format_date(), get_date(), handle_minivm_show_stats(), handle_show_settings(), handle_time_date_req_message(), httpd_helper_thread(), iax2_datetime(), isodate(), leave_voicemail(), main(), make_email_file(), manager_log(), odbc_log(), packdate(), pgsql_log(), phone_call(), phoneprov_callback(), 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_notify_request_with_callerid(), vmu_tm(), write_history(), and write_metadata().
| struct timeval ast_mktime | ( | struct ast_tm *const | tmp, | |
| const char * | zone | |||
| ) | [read] |
Timezone-independent version of mktime(3).
| tmp | Current broken-out time, including microseconds | |
| zone | Text string of a standard system zoneinfo file. If NULL, the system localtime will be used. |
| A | structure containing both seconds and fractional thereof since January 1st, 1970 UTC |
Definition at line 1920 of file localtime.c.
References ast_tzset(), localsub(), and time1().
Referenced by acf_strptime(), conf_run(), find_conf_realtime(), rt_extend_conf(), sms_handleincoming_proto2(), sms_readfile(), and unpackdate().
| 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. |
| An | integer value specifying the number of bytes placed into buf or -1 on error. |
Definition at line 1928 of file localtime.c.
References ast_calloc, ast_free, ast_realloc, format, and ast_tm::tm_usec.
Referenced by __ast_verbose_ap(), acf_strftime(), action_corestatus(), append_date(), ast_log(), build_radius_record(), cdr_get_tv(), cli_prompt(), conf_run(), dump_datetime(), execute_cb(), find_conf_realtime(), format_date(), get_date(), handle_minivm_show_stats(), handle_show_settings(), httpd_helper_thread(), isodate(), leave_voicemail(), make_email_file(), manager_log(), odbc_log(), pgsql_log(), phoneprov_callback(), prep_email_sub_vars(), rt_extend_conf(), sendmail(), sendpage(), sip_show_registry(), static_callback(), timeout_write(), and write_metadata().
01929 { 01930 size_t fmtlen = strlen(tmp) + 1; 01931 char *format = ast_calloc(1, fmtlen), *fptr = format, *newfmt; 01932 int decimals = -1, i, res; 01933 long fraction; 01934 01935 if (!format) 01936 return -1; 01937 for (; *tmp; tmp++) { 01938 if (*tmp == '%') { 01939 switch (tmp[1]) { 01940 case '1': 01941 case '2': 01942 case '3': 01943 case '4': 01944 case '5': 01945 case '6': 01946 if (tmp[2] != 'q') 01947 goto defcase; 01948 decimals = tmp[1] - '0'; 01949 tmp++; 01950 /* Fall through */ 01951 case 'q': /* Milliseconds */ 01952 if (decimals == -1) 01953 decimals = 3; 01954 01955 /* Juggle some memory to fit the item */ 01956 newfmt = ast_realloc(format, fmtlen + decimals); 01957 if (!newfmt) { 01958 ast_free(format); 01959 return -1; 01960 } 01961 fptr = fptr - format + newfmt; 01962 format = newfmt; 01963 fmtlen += decimals; 01964 01965 /* Reduce the fraction of time to the accuracy needed */ 01966 for (i = 6, fraction = tm->tm_usec; i > decimals; i--) 01967 fraction /= 10; 01968 fptr += sprintf(fptr, "%0*ld", decimals, fraction); 01969 01970 /* Reset, in case more than one 'q' specifier exists */ 01971 decimals = -1; 01972 tmp++; 01973 break; 01974 default: 01975 goto defcase; 01976 } 01977 } else 01978 defcase: *fptr++ = *tmp; 01979 } 01980 *fptr = '\0'; 01981 #undef strftime 01982 res = (int)strftime(buf, len, format, (struct tm *)tm); 01983 ast_free(format); 01984 return res; 01985 }
| 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. |
| A | pointer to the first character within s not used to parse the date and time. |
Definition at line 1987 of file localtime.c.
References ast_tm::tm_isdst, and ast_tm::tm_usec.
Referenced by acf_strptime(), conf_run(), find_conf_realtime(), and rt_extend_conf().
01988 { 01989 struct tm tm2 = { 0, }; 01990 char *res = strptime(s, format, &tm2); 01991 memcpy(tm, &tm2, sizeof(*tm)); 01992 tm->tm_usec = 0; 01993 /* strptime(3) doesn't set .tm_isdst correctly, so to force ast_mktime(3) 01994 * to deal with it correctly, we set it to -1. */ 01995 tm->tm_isdst = -1; 01996 return res; 01997 }
| static struct state* ast_tzset | ( | const char * | zone | ) | [static, read] |
Definition at line 1175 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().
01176 { 01177 struct state *sp; 01178 01179 if (ast_strlen_zero(zone)) 01180 zone = "/etc/localtime"; 01181 01182 AST_LIST_LOCK(&zonelist); 01183 AST_LIST_TRAVERSE(&zonelist, sp, list) { 01184 if (!strcmp(sp->name, zone)) { 01185 AST_LIST_UNLOCK(&zonelist); 01186 return sp; 01187 } 01188 } 01189 AST_LIST_UNLOCK(&zonelist); 01190 01191 if (!(sp = ast_calloc(1, sizeof *sp))) 01192 return NULL; 01193 01194 if (tzload(zone, sp, TRUE) != 0) { 01195 if (zone[0] == ':' || tzparse(zone, sp, FALSE) != 0) 01196 (void) gmtload(sp); 01197 } 01198 ast_copy_string(sp->name, zone, sizeof(sp->name)); 01199 AST_LIST_LOCK(&zonelist); 01200 AST_LIST_INSERT_TAIL(&zonelist, sp, list); 01201 AST_LIST_UNLOCK(&zonelist); 01202 return sp; 01203 }
| static long detzcode | ( | const char *const | codep | ) | [static] |
Definition at line 392 of file localtime.c.
Referenced by tzload().
| static time_t detzcode64 | ( | const char *const | codep | ) | [static] |
Definition at line 403 of file localtime.c.
Referenced by tzload().
00404 { 00405 time_t result; 00406 int i; 00407 00408 result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0; 00409 for (i = 0; i < 8; ++i) 00410 result = result * 256 + (codep[i] & 0xff); 00411 return result; 00412 }
| static int differ_by_repeat | ( | const time_t | t1, | |
| const time_t | t0 | |||
| ) | [static] |
Definition at line 414 of file localtime.c.
Referenced by tzload().
| 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 704 of file localtime.c.
Referenced by getrule(), and getsecs().
00705 { 00706 char c; 00707 int num; 00708 00709 if (strp == NULL || !is_digit(c = *strp)) 00710 return NULL; 00711 num = 0; 00712 do { 00713 num = num * 10 + (c - '0'); 00714 if (num > max) 00715 return NULL; /* illegal value */ 00716 c = *++strp; 00717 } while (is_digit(c)); 00718 if (num < min) 00719 return NULL; /* illegal value */ 00720 *nump = num; 00721 return strp; 00722 }
| 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 771 of file localtime.c.
References getsecs().
Referenced by tzparse().
00772 { 00773 int neg = 0; 00774 00775 if (*strp == '-') { 00776 neg = 1; 00777 ++strp; 00778 } else if (*strp == '+') 00779 ++strp; 00780 strp = getsecs(strp, offsetp); 00781 if (strp == NULL) 00782 return NULL; /* illegal time */ 00783 if (neg) 00784 *offsetp = -*offsetp; 00785 return strp; 00786 }
| 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 688 of file localtime.c.
Referenced by tzparse().
| static const char* getrule | ( | const char * | strp, | |
| struct rule * | rulep | |||
| ) | [static] |
Given a pointer into a time zone string, extract a rule in the form date[/time]. See POSIX section 8 for the format of "date" and "time". If a valid rule is not found, return NULL. Otherwise, return a pointer to the first character not part of the rule.
Definition at line 795 of file localtime.c.
References DAY_OF_YEAR, DAYSPERLYEAR, DAYSPERNYEAR, DAYSPERWEEK, getnum(), getsecs(), is_digit, JULIAN_DAY, MONSPERYEAR, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, and SECSPERHOUR.
Referenced by tzparse().
00796 { 00797 if (*strp == 'J') { 00798 /* 00799 ** Julian day. 00800 */ 00801 rulep->r_type = JULIAN_DAY; 00802 ++strp; 00803 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR); 00804 } else if (*strp == 'M') { 00805 /* 00806 ** Month, week, day. 00807 */ 00808 rulep->r_type = MONTH_NTH_DAY_OF_WEEK; 00809 ++strp; 00810 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR); 00811 if (strp == NULL) 00812 return NULL; 00813 if (*strp++ != '.') 00814 return NULL; 00815 strp = getnum(strp, &rulep->r_week, 1, 5); 00816 if (strp == NULL) 00817 return NULL; 00818 if (*strp++ != '.') 00819 return NULL; 00820 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1); 00821 } else if (is_digit(*strp)) { 00822 /* 00823 ** Day of year. 00824 */ 00825 rulep->r_type = DAY_OF_YEAR; 00826 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); 00827 } else return NULL; /* invalid format */ 00828 if (strp == NULL) 00829 return NULL; 00830 if (*strp == '/') { 00831 /* 00832 ** Time specified. 00833 */ 00834 ++strp; 00835 strp = getsecs(strp, &rulep->r_time); 00836 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ 00837 return strp; 00838 }
| 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 732 of file localtime.c.
References DAYSPERWEEK, getnum(), HOURSPERDAY, MINSPERHOUR, num, SECSPERHOUR, and SECSPERMIN.
Referenced by getoffset(), and getrule().
00733 { 00734 int num; 00735 00736 /* 00737 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like 00738 ** "M10.4.6/26", which does not conform to Posix, 00739 ** but which specifies the equivalent of 00740 ** ``02:00 on the first Sunday on or after 23 Oct''. 00741 */ 00742 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); 00743 if (strp == NULL) 00744 return NULL; 00745 *secsp = num * (long) SECSPERHOUR; 00746 if (*strp == ':') { 00747 ++strp; 00748 strp = getnum(strp, &num, 0, MINSPERHOUR - 1); 00749 if (strp == NULL) 00750 return NULL; 00751 *secsp += num * SECSPERMIN; 00752 if (*strp == ':') { 00753 ++strp; 00754 /* `SECSPERMIN' allows for leap seconds. */ 00755 strp = getnum(strp, &num, 0, SECSPERMIN); 00756 if (strp == NULL) 00757 return NULL; 00758 *secsp += num; 00759 } 00760 } 00761 return strp; 00762 }
| 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 669 of file localtime.c.
References is_digit.
Referenced by tzparse().
00670 { 00671 char c; 00672 00673 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' && 00674 c != '+') 00675 ++strp; 00676 return strp; 00677 }
| static int gmtload | ( | struct state * | sp | ) | [static] |
| static struct ast_tm* gmtsub | ( | const struct timeval * | timep, | |
| const long | offset, | |||
| struct ast_tm * | tmp | |||
| ) | [static, read] |
Definition at line 1431 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().
01432 { 01433 struct ast_tm * result; 01434 struct state *sp; 01435 01436 AST_LIST_LOCK(&zonelist); 01437 AST_LIST_TRAVERSE(&zonelist, sp, list) { 01438 if (!strcmp(sp->name, "UTC")) 01439 break; 01440 } 01441 01442 if (!sp) { 01443 if (!(sp = (struct state *) ast_calloc(1, sizeof *sp))) 01444 return NULL; 01445 gmtload(sp); 01446 AST_LIST_INSERT_TAIL(&zonelist, sp, list); 01447 } 01448 AST_LIST_UNLOCK(&zonelist); 01449 01450 result = timesub(timep, offset, sp, tmp); 01451 #ifdef TM_ZONE 01452 /* 01453 ** Could get fancy here and deliver something such as 01454 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, 01455 ** but this is no time for a treasure hunt. 01456 */ 01457 if (offset != 0) 01458 tmp->TM_ZONE = " "; 01459 else 01460 tmp->TM_ZONE = sp->chars; 01461 #endif /* defined TM_ZONE */ 01462 return result; 01463 }
| static int increment_overflow | ( | int * | number, | |
| int | delta | |||
| ) | [static] |
Simplified normalize logic courtesy Paul Eggert.
Definition at line 1614 of file localtime.c.
Referenced by normalize_overflow(), time2sub(), and timesub().
| static void* inotify_daemon | ( | void * | data | ) | [static] |
Definition at line 234 of file localtime.c.
References ast_cond_signal(), 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, buf, errno, initialization, initialization_lock, inotify_fd, inotify_thread, state::list, LOG_ERROR, state::name, and state::wd.
Referenced by add_notify().
00235 { 00236 struct { 00237 struct inotify_event iev; 00238 char name[FILENAME_MAX + 1]; 00239 } buf; 00240 ssize_t res; 00241 struct state *cur; 00242 struct timespec ten_seconds = { 10, 0 }; 00243 00244 inotify_fd = inotify_init(); 00245 00246 ast_mutex_lock(&initialization_lock); 00247 ast_cond_signal(&initialization); 00248 ast_mutex_unlock(&initialization_lock); 00249 00250 if (inotify_fd < 0) { 00251 ast_log(LOG_ERROR, "Cannot initialize file notification service: %s (%d)\n", strerror(errno), errno); 00252 inotify_thread = AST_PTHREADT_NULL; 00253 return NULL; 00254 } 00255 00256 for (;/*ever*/;) { 00257 /* This read should block, most of the time. */ 00258 if ((res = read(inotify_fd, &buf, sizeof(buf))) < sizeof(buf.iev) && res > 0) { 00259 /* This should never happen */ 00260 ast_log(LOG_ERROR, "Inotify read less than a full event (%zd < %zd)?!!\n", res, sizeof(buf.iev)); 00261 break; 00262 } else if (res < 0) { 00263 if (errno == EINTR || errno == EAGAIN) { 00264 /* If read fails, then wait a bit, then continue */ 00265 nanosleep(&ten_seconds, NULL); 00266 continue; 00267 } 00268 /* Sanity check -- this should never happen, either */ 00269 ast_log(LOG_ERROR, "Inotify failed: %s\n", strerror(errno)); 00270 break; 00271 } 00272 AST_LIST_LOCK(&zonelist); 00273 AST_LIST_TRAVERSE_SAFE_BEGIN(&zonelist, cur, list) { 00274 if (cur->wd[0] == buf.iev.wd || cur->wd[1] == buf.iev.wd) { 00275 AST_LIST_REMOVE_CURRENT(list); 00276 ast_free(cur); 00277 break; 00278 } 00279 } 00280 AST_LIST_TRAVERSE_SAFE_END 00281 AST_LIST_UNLOCK(&zonelist); 00282 } 00283 close(inotify_fd); 00284 inotify_thread = AST_PTHREADT_NULL; 00285 return NULL; 00286 }
| 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 1470 of file localtime.c.
Referenced by timesub().
01471 { 01472 return (y >= 0) ? (y / 4 - y / 100 + y / 400) : 01473 -(leaps_thru_end_of(-(y + 1)) + 1); 01474 }
| static struct ast_tm* localsub | ( | const struct timeval * | timep, | |
| const long | offset, | |||
| struct ast_tm * | tmp, | |||
| const struct state * | sp | |||
| ) | [static, read] |
The unused offset argument is for the benefit of mktime variants.
Definition at line 1214 of file localtime.c.
References state::ats, state::chars, gmtsub(), state::goahead, state::goback, state::timecnt, timesub(), ast_tm::tm_gmtoff, ast_tm::tm_isdst, ast_tm::tm_usec, ast_tm::tm_year, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, and state::types.
Referenced by ast_localtime(), and ast_mktime().
01215 { 01216 const struct ttinfo * ttisp; 01217 int i; 01218 struct ast_tm * result; 01219 struct timeval t; 01220 memcpy(&t, timep, sizeof(t)); 01221 01222 if (sp == NULL) 01223 return gmtsub(timep, offset, tmp); 01224 if ((sp->goback && t.tv_sec < sp->ats[0]) || 01225 (sp->goahead && t.tv_sec > sp->ats[sp->timecnt - 1])) { 01226 struct timeval newt = t; 01227 time_t seconds; 01228 time_t tcycles; 01229 int_fast64_t icycles; 01230 01231 if (t.tv_sec < sp->ats[0]) 01232 seconds = sp->ats[0] - t.tv_sec; 01233 else seconds = t.tv_sec - sp->ats[sp->timecnt - 1]; 01234 --seconds; 01235 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR; 01236 ++tcycles; 01237 icycles = tcycles; 01238 if (tcycles - icycles >= 1 || icycles - tcycles >= 1) 01239 return NULL; 01240 seconds = icycles; 01241 seconds *= YEARSPERREPEAT; 01242 seconds *= AVGSECSPERYEAR; 01243 if (t.tv_sec < sp->ats[0]) 01244 newt.tv_sec += seconds; 01245 else newt.tv_sec -= seconds; 01246 if (newt.tv_sec < sp->ats[0] || 01247 newt.tv_sec > sp->ats[sp->timecnt - 1]) 01248 return NULL; /* "cannot happen" */ 01249 result = localsub(&newt, offset, tmp, sp); 01250 if (result == tmp) { 01251 time_t newy; 01252 01253 newy = tmp->tm_year; 01254 if (t.tv_sec < sp->ats[0]) 01255 newy -= icycles * YEARSPERREPEAT; 01256 else 01257 newy += icycles * YEARSPERREPEAT; 01258 tmp->tm_year = newy; 01259 if (tmp->tm_year != newy) 01260 return NULL; 01261 } 01262 return result; 01263 } 01264 if (sp->timecnt == 0 || t.tv_sec < sp->ats[0]) { 01265 i = 0; 01266 while (sp->ttis[i].tt_isdst) { 01267 if (++i >= sp->typecnt) { 01268 i = 0; 01269 break; 01270 } 01271 } 01272 } else { 01273 int lo = 1; 01274 int hi = sp->timecnt; 01275 01276 while (lo < hi) { 01277 int mid = (lo + hi) >> 1; 01278 01279 if (t.tv_sec < sp->ats[mid]) 01280 hi = mid; 01281 else 01282 lo = mid + 1; 01283 } 01284 i = (int) sp->types[lo - 1]; 01285 } 01286 ttisp = &sp->ttis[i]; 01287 /* 01288 ** To get (wrong) behavior that's compatible with System V Release 2.0 01289 ** you'd replace the statement below with 01290 ** t += ttisp->tt_gmtoff; 01291 ** timesub(&t, 0L, sp, tmp); 01292 */ 01293 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); 01294 tmp->tm_isdst = ttisp->tt_isdst; 01295 #ifndef SOLARIS /* Solaris doesn't have this element */ 01296 tmp->tm_gmtoff = ttisp->tt_gmtoff; 01297 #endif 01298 #ifdef TM_ZONE 01299 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; 01300 #endif /* defined TM_ZONE */ 01301 tmp->tm_usec = timep->tv_usec; 01302 return result; 01303 }
| static int long_increment_overflow | ( | long * | number, | |
| int | delta | |||
| ) | [static] |
Definition at line 1623 of file localtime.c.
Referenced by long_normalize_overflow(), and time2sub().
| static int long_normalize_overflow | ( | long * | tensptr, | |
| int * | unitsptr, | |||
| const int | base | |||
| ) | [static] |
Definition at line 1643 of file localtime.c.
References long_increment_overflow().
Referenced by time2sub().
01644 { 01645 int tensdelta; 01646 01647 tensdelta = (*unitsptr >= 0) ? 01648 (*unitsptr / base) : 01649 (-1 - (-1 - *unitsptr) / base); 01650 *unitsptr -= tensdelta * base; 01651 return long_increment_overflow(tensptr, tensdelta); 01652 }
| static int normalize_overflow | ( | int * | tensptr, | |
| int * | unitsptr, | |||
| const int | base | |||
| ) | [static] |
Definition at line 1632 of file localtime.c.
References increment_overflow().
Referenced by time2sub().
01633 { 01634 int tensdelta; 01635 01636 tensdelta = (*unitsptr >= 0) ? 01637 (*unitsptr / base) : 01638 (-1 - (-1 - *unitsptr) / base); 01639 *unitsptr -= tensdelta * base; 01640 return increment_overflow(tensptr, tensdelta); 01641 }
| static time_t transtime P | ( | (time_t janfirst, int year, const struct rule *rulep, long offset) | ) | [static] |
| static struct ast_tm* timesub P | ( | (const struct timeval *timep, long offset, const struct state *sp, struct ast_tm *tmp) | ) | [static, read] |
| static struct timeval time2sub P | ( | (struct ast_tm *tmp, struct ast_tm *(*funcp)(const struct timeval *, long, struct ast_tm *, const struct state *sp), long offset, int *okayp, int do_norm_secs, const struct state *sp) | ) | [static, read] |
| static struct timeval time2 P | ( | (struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, int *okayp, const struct state *sp) | ) | [static, read] |
| static struct timeval time1 P | ( | (struct ast_tm *tmp, struct ast_tm *(*funcp) P((const struct timeval *, long, struct ast_tm *, const struct state *sp)), long offset, const struct state *sp) | ) | [static, read] |
| static int normalize_overflow P | ( | (int *tensptr, int *unitsptr, const int base) | ) | [static] |
| static int long_normalize_overflow P | ( | (long *tensptr, int *unitsptr, const int base) | ) | [static] |
| static int long_increment_overflow P | ( | (long *number, int delta) | ) | [static] |
| static int leaps_thru_end_of P | ( | (int y) | ) | [static] |
| static int increment_overflow P | ( | (int *number, int delta) | ) | [static] |
| static struct ast_tm* localsub P | ( | (const struct timeval *timep, long offset, struct ast_tm *tmp, const struct state *sp) | ) | [static, read] |
| static struct ast_tm* gmtsub P | ( | (const struct timeval *timep, long offset, struct ast_tm *tmp) | ) | [static, read] |
| static int gmtload P | ( | (struct state *sp) | ) | [static] |
| static const char* getrule P | ( | (const char *strp, struct rule *rulep) | ) | [static] |
| static const char* getoffset P | ( | (const char *strp, long *offsetp) | ) | [static] |
| static const char* getsecs P | ( | (const char *strp, long *secsp) | ) | [static] |
| static const char* getnum P | ( | (const char *strp, int *nump, int min, int max) | ) | [static] |
| static const char* getqzname P | ( | (const char *strp, const int delim) | ) | [static] |
| static const char* getzname P | ( | (const char *strp) | ) | [static] |
| static int differ_by_repeat P | ( | (time_t t1, time_t t0) | ) | [static] |
| static time_t detzcode64 P | ( | (const char *codep) | ) | [static] |
| static struct timeval time1 | ( | struct ast_tm * | tmp, | |
| struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *) | funcp, | |||
| const long | offset, | |||
| const struct state * | sp | |||
| ) | [static, read] |
Definition at line 1855 of file localtime.c.
References FALSE, time2(), state::timecnt, TRUE, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, and state::types.
Referenced by ast_mktime().
01856 { 01857 struct timeval t; 01858 int samei, otheri; 01859 int sameind, otherind; 01860 int i; 01861 int nseen; 01862 int seen[TZ_MAX_TYPES]; 01863 int types[TZ_MAX_TYPES]; 01864 int okay; 01865 01866 if (tmp->tm_isdst > 1) 01867 tmp->tm_isdst = 1; 01868 t = time2(tmp, funcp, offset, &okay, sp); 01869 #ifdef PCTS 01870 /* 01871 ** PCTS code courtesy Grant Sullivan. 01872 */ 01873 if (okay) 01874 return t; 01875 if (tmp->tm_isdst < 0) 01876 tmp->tm_isdst = 0; /* reset to std and try again */ 01877 #endif /* defined PCTS */ 01878 #ifndef PCTS 01879 if (okay || tmp->tm_isdst < 0) 01880 return t; 01881 #endif /* !defined PCTS */ 01882 /* 01883 ** We're supposed to assume that somebody took a time of one type 01884 ** and did some math on it that yielded a "struct ast_tm" that's bad. 01885 ** We try to divine the type they started from and adjust to the 01886 ** type they need. 01887 */ 01888 if (sp == NULL) 01889 return WRONG; 01890 for (i = 0; i < sp->typecnt; ++i) 01891 seen[i] = FALSE; 01892 nseen = 0; 01893 for (i = sp->timecnt - 1; i >= 0; --i) 01894 if (!seen[sp->types[i]]) { 01895 seen[sp->types[i]] = TRUE; 01896 types[nseen++] = sp->types[i]; 01897 } 01898 for (sameind = 0; sameind < nseen; ++sameind) { 01899 samei = types[sameind]; 01900 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst) 01901 continue; 01902 for (otherind = 0; otherind < nseen; ++otherind) { 01903 otheri = types[otherind]; 01904 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst) 01905 continue; 01906 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff - 01907 sp->ttis[samei].tt_gmtoff; 01908 tmp->tm_isdst = !tmp->tm_isdst; 01909 t = time2(tmp, funcp, offset, &okay, sp); 01910 if (okay) 01911 return t; 01912 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff - 01913 sp->ttis[samei].tt_gmtoff; 01914 tmp->tm_isdst = !tmp->tm_isdst; 01915 } 01916 } 01917 return WRONG; 01918 }
| static struct timeval time2 | ( | struct ast_tm * | tmp, | |
| struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *sp) | funcp, | |||
| const long | offset, | |||
| int * | okayp, | |||
| const struct state * | sp | |||
| ) | [static, read] |
Definition at line 1842 of file localtime.c.
References FALSE, time2sub(), and TRUE.
Referenced by time1().
01843 { 01844 struct timeval t; 01845 01846 /*! \note 01847 ** First try without normalization of seconds 01848 ** (in case tm_sec contains a value associated with a leap second). 01849 ** If that fails, try with normalization of seconds. 01850 */ 01851 t = time2sub(tmp, funcp, offset, okayp, FALSE, sp); 01852 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, sp); 01853 }
| static struct timeval time2sub | ( | struct ast_tm * | tmp, | |
| struct ast_tm *(*)(const struct timeval *, long, struct ast_tm *, const struct state *) | funcp, | |||
| const long | offset, | |||
| int * | okayp, | |||
| const int | do_norm_secs, | |||
| const struct state * | sp | |||
| ) | [static, read] |
Definition at line 1668 of file localtime.c.
References DAYSPERLYEAR, dir, EPOCH_YEAR, FALSE, HOURSPERDAY, increment_overflow(), isleap, long_increment_overflow(), long_normalize_overflow(), MINSPERHOUR, mon_lengths, MONSPERYEAR, normalize_overflow(), SECSPERMIN, ast_tm::tm_hour, ast_tm::tm_isdst, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_year, TM_YEAR_BASE, tmcomp(), TRUE, ttinfo::tt_gmtoff, ttinfo::tt_isdst, state::ttis, state::typecnt, and year_lengths.
Referenced by time2().
01669 { 01670 int dir; 01671 int i, j; 01672 int saved_seconds; 01673 long li; 01674 time_t lo; 01675 time_t hi; 01676 long y; 01677 struct timeval newt = { 0, 0 }; 01678 struct timeval t = { 0, 0 }; 01679 struct ast_tm yourtm, mytm; 01680 01681 *okayp = FALSE; 01682 yourtm = *tmp; 01683 if (do_norm_secs) { 01684 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, 01685 SECSPERMIN)) 01686 return WRONG; 01687 } 01688 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR)) 01689 return WRONG; 01690 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) 01691 return WRONG; 01692 y = yourtm.tm_year; 01693 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) 01694 return WRONG; 01695 /* 01696 ** Turn y into an actual year number for now. 01697 ** It is converted back to an offset from TM_YEAR_BASE later. 01698 */ 01699 if (long_increment_overflow(&y, TM_YEAR_BASE)) 01700 return WRONG; 01701 while (yourtm.tm_mday <= 0) { 01702 if (long_increment_overflow(&y, -1)) 01703 return WRONG; 01704 li = y + (1 < yourtm.tm_mon); 01705 yourtm.tm_mday += year_lengths[isleap(li)]; 01706 } 01707 while (yourtm.tm_mday > DAYSPERLYEAR) { 01708 li = y + (1 < yourtm.tm_mon); 01709 yourtm.tm_mday -= year_lengths[isleap(li)]; 01710 if (long_increment_overflow(&y, 1)) 01711 return WRONG; 01712 } 01713 for ( ; ; ) { 01714 i = mon_lengths[isleap(y)][yourtm.tm_mon]; 01715 if (yourtm.tm_mday <= i) 01716 break; 01717 yourtm.tm_mday -= i; 01718 if (++yourtm.tm_mon >= MONSPERYEAR) { 01719 yourtm.tm_mon = 0; 01720 if (long_increment_overflow(&y, 1)) 01721 return WRONG; 01722 } 01723 } 01724 if (long_increment_overflow(&y, -TM_YEAR_BASE)) 01725 return WRONG; 01726 yourtm.tm_year = y; 01727 if (yourtm.tm_year != y) 01728 return WRONG; 01729 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN) 01730 saved_seconds = 0; 01731 else if (y + TM_YEAR_BASE < EPOCH_YEAR) { 01732 /* 01733 ** We can't set tm_sec to 0, because that might push the 01734 ** time below the minimum representable time. 01735 ** Set tm_sec to 59 instead. 01736 ** This assumes that the minimum representable time is 01737 ** not in the same minute that a leap second was deleted from, 01738 ** which is a safer assumption than using 58 would be. 01739 */ 01740 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN)) 01741 return WRONG; 01742 saved_seconds = yourtm.tm_sec; 01743 yourtm.tm_sec = SECSPERMIN - 1; 01744 } else { 01745 saved_seconds = yourtm.tm_sec; 01746 yourtm.tm_sec = 0; 01747 } 01748 /* 01749 ** Do a binary search (this works whatever time_t's type is). 01750 */ 01751 if (!TYPE_SIGNED(time_t)) { 01752 lo = 0; 01753 hi = lo - 1; 01754 } else if (!TYPE_INTEGRAL(time_t)) { 01755 if (sizeof(time_t) > sizeof(float)) 01756 hi = (time_t) DBL_MAX; 01757 else hi = (time_t) FLT_MAX; 01758 lo = -hi; 01759 } else { 01760 lo = 1; 01761 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) 01762 lo *= 2; 01763 hi = -(lo + 1); 01764 } 01765 for ( ; ; ) { 01766 t.tv_sec = lo / 2 + hi / 2; 01767 if (t.tv_sec < lo) 01768 t.tv_sec = lo; 01769 else if (t.tv_sec > hi) 01770 t.tv_sec = hi; 01771 if ((*funcp)(&t, offset, &mytm, sp) == NULL) { 01772 /* 01773 ** Assume that t is too extreme to be represented in 01774 ** a struct ast_tm; arrange things so that it is less 01775 ** extreme on the next pass. 01776 */ 01777 dir = (t.tv_sec > 0) ? 1 : -1; 01778 } else dir = tmcomp(&mytm, &yourtm); 01779 if (dir != 0) { 01780 if (t.tv_sec == lo) { 01781 ++t.tv_sec; 01782 if (t.tv_sec <= lo) 01783 return WRONG; 01784 ++lo; 01785 } else if (t.tv_sec == hi) { 01786 --t.tv_sec; 01787 if (t.tv_sec >= hi) 01788 return WRONG; 01789 --hi; 01790 } 01791 if (lo > hi) 01792 return WRONG; 01793 if (dir > 0) 01794 hi = t.tv_sec; 01795 else lo = t.tv_sec; 01796 continue; 01797 } 01798 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst) 01799 break; 01800 /* 01801 ** Right time, wrong type. 01802 ** Hunt for right time, right type. 01803 ** It's okay to guess wrong since the guess 01804 ** gets checked. 01805 */ 01806 /* 01807 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's. 01808 */ 01809 for (i = sp->typecnt - 1; i >= 0; --i) { 01810 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst) 01811 continue; 01812 for (j = sp->typecnt - 1; j >= 0; --j) { 01813 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst) 01814 continue; 01815 newt.tv_sec = t.tv_sec + sp->ttis[j].tt_gmtoff - 01816 sp->ttis[i].tt_gmtoff; 01817 if ((*funcp)(&newt, offset, &mytm, sp) == NULL) 01818 continue; 01819 if (tmcomp(&mytm, &yourtm) != 0) 01820 continue; 01821 if (mytm.tm_isdst != yourtm.tm_isdst) 01822 continue; 01823 /* 01824 ** We have a match. 01825 */ 01826 t = newt; 01827 goto label; 01828 } 01829 } 01830 return WRONG; 01831 } 01832 label: 01833 newt.tv_sec = t.tv_sec + saved_seconds; 01834 if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0)) 01835 return WRONG; 01836 t.tv_sec = newt.tv_sec; 01837 if ((*funcp)(&t, offset, tmp, sp)) 01838 *okayp = TRUE; 01839 return t; 01840 }
| static struct ast_tm* timesub | ( | const struct timeval * | timep, | |
| const long | offset, | |||
| const struct state * | sp, | |||
| struct ast_tm * | tmp | |||
| ) | [static, read] |
Definition at line 1476 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().
01477 { 01478 const struct lsinfo * lp; 01479 time_t tdays; 01480 int idays; /* unsigned would be so 2003 */ 01481 long rem; 01482 int y; 01483 const int * ip; 01484 long corr; 01485 int hit; 01486 int i; 01487 long seconds; 01488 01489 01490 corr = 0; 01491 hit = 0; 01492 i = (sp == NULL) ? 0 : sp->leapcnt; 01493 while (--i >= 0) { 01494 lp = &sp->lsis[i]; 01495 if (timep->tv_sec >= lp->ls_trans) { 01496 if (timep->tv_sec == lp->ls_trans) { 01497 hit = ((i == 0 && lp->ls_corr > 0) || 01498 lp->ls_corr > sp->lsis[i - 1].ls_corr); 01499 if (hit) 01500 while (i > 0 && 01501 sp->lsis[i].ls_trans == 01502 sp->lsis[i - 1].ls_trans + 1 && 01503 sp->lsis[i].ls_corr == 01504 sp->lsis[i - 1].ls_corr + 1) { 01505 ++hit; 01506 --i; 01507 } 01508 } 01509 corr = lp->ls_corr; 01510 break; 01511 } 01512 } 01513 y = EPOCH_YEAR; 01514 tdays = timep->tv_sec / SECSPERDAY; 01515 rem = timep->tv_sec - tdays * SECSPERDAY; 01516 while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { 01517 int newy; 01518 time_t tdelta; 01519 int idelta; 01520 int leapdays; 01521 01522 tdelta = tdays / DAYSPERLYEAR; 01523 idelta = tdelta; 01524 if (tdelta - idelta >= 1 || idelta - tdelta >= 1) 01525 return NULL; 01526 if (idelta == 0) 01527 idelta = (tdays < 0) ? -1 : 1; 01528 newy = y; 01529 if (increment_overflow(&newy, idelta)) 01530 return NULL; 01531 leapdays = leaps_thru_end_of(newy - 1) - 01532 leaps_thru_end_of(y - 1); 01533 tdays -= ((time_t) newy - y) * DAYSPERNYEAR; 01534 tdays -= leapdays; 01535 y = newy; 01536 } 01537 01538 seconds = tdays * SECSPERDAY + 0.5; 01539 tdays = seconds / SECSPERDAY; 01540 rem += seconds - tdays * SECSPERDAY; 01541 01542 /* 01543 ** Given the range, we can now fearlessly cast... 01544 */ 01545 idays = tdays; 01546 rem += offset - corr; 01547 while (rem < 0) { 01548 rem += SECSPERDAY; 01549 --idays; 01550 } 01551 while (rem >= SECSPERDAY) { 01552 rem -= SECSPERDAY; 01553 ++idays; 01554 } 01555 while (idays < 0) { 01556 if (increment_overflow(&y, -1)) 01557 return NULL; 01558 idays += year_lengths[isleap(y)]; 01559 } 01560 while (idays >= year_lengths[isleap(y)]) { 01561 idays -= year_lengths[isleap(y)]; 01562 if (increment_overflow(&y, 1)) 01563 return NULL; 01564 } 01565 tmp->tm_year = y; 01566 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) 01567 return NULL; 01568 tmp->tm_yday = idays; 01569 /* 01570 ** The "extra" mods below avoid overflow problems. 01571 */ 01572 tmp->tm_wday = EPOCH_WDAY + 01573 ((y - EPOCH_YEAR) % DAYSPERWEEK) * 01574 (DAYSPERNYEAR % DAYSPERWEEK) + 01575 leaps_thru_end_of(y - 1) - 01576 leaps_thru_end_of(EPOCH_YEAR - 1) + 01577 idays; 01578 tmp->tm_wday %= DAYSPERWEEK; 01579 if (tmp->tm_wday < 0) 01580 tmp->tm_wday += DAYSPERWEEK; 01581 tmp->tm_hour = (int) (rem / SECSPERHOUR); 01582 rem %= SECSPERHOUR; 01583 tmp->tm_min = (int) (rem / SECSPERMIN); 01584 /* 01585 ** A positive leap second requires a special 01586 ** representation. This uses "... ??:59:60" et seq. 01587 */ 01588 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit; 01589 ip = mon_lengths[isleap(y)]; 01590 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon)) 01591 idays -= ip[tmp->tm_mon]; 01592 tmp->tm_mday = (int) (idays + 1); 01593 tmp->tm_isdst = 0; 01594 #ifdef TM_GMTOFF 01595 tmp->TM_GMTOFF = offset; 01596 #endif /* defined TM_GMTOFF */ 01597 tmp->tm_usec = timep->tv_usec; 01598 return tmp; 01599 }
Definition at line 1654 of file localtime.c.
References ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, and ast_tm::tm_year.
Referenced by time2sub().
01655 { 01656 int result; 01657 01658 if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && 01659 (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && 01660 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && 01661 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && 01662 (result = (atmp->tm_min - btmp->tm_min)) == 0 && 01663 (result = (atmp->tm_sec - btmp->tm_sec)) == 0) 01664 result = atmp->tm_usec - btmp->tm_usec; 01665 return result; 01666 }
| 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 846 of file localtime.c.
References DAY_OF_YEAR, DAYSPERWEEK, isleap, JULIAN_DAY, m1, mon_lengths, MONTH_NTH_DAY_OF_WEEK, rule::r_day, rule::r_mon, rule::r_time, rule::r_type, rule::r_week, and SECSPERDAY.
Referenced by tzparse().
00847 { 00848 int leapyear; 00849 time_t value; 00850 int i; 00851 int d, m1, yy0, yy1, yy2, dow; 00852 00853 INITIALIZE(value); 00854 leapyear = isleap(year); 00855 switch (rulep->r_type) { 00856 00857 case JULIAN_DAY: 00858 /* 00859 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap 00860 ** years. 00861 ** In non-leap years, or if the day number is 59 or less, just 00862 ** add SECSPERDAY times the day number-1 to the time of 00863 ** January 1, midnight, to get the day. 00864 */ 00865 value = janfirst + (rulep->r_day - 1) * SECSPERDAY; 00866 if (leapyear && rulep->r_day >= 60) 00867 value += SECSPERDAY; 00868 break; 00869 00870 case DAY_OF_YEAR: 00871 /* 00872 ** n - day of year. 00873 ** Just add SECSPERDAY times the day number to the time of 00874 ** January 1, midnight, to get the day. 00875 */ 00876 value = janfirst + rulep->r_day * SECSPERDAY; 00877 break; 00878 00879 case MONTH_NTH_DAY_OF_WEEK: 00880 /* 00881 ** Mm.n.d - nth "dth day" of month m. 00882 */ 00883 value = janfirst; 00884 for (i = 0; i < rulep->r_mon - 1; ++i) 00885 value += mon_lengths[leapyear][i] * SECSPERDAY; 00886 00887 /* 00888 ** Use Zeller's Congruence to get day-of-week of first day of 00889 ** month. 00890 */ 00891 m1 = (rulep->r_mon + 9) % 12 + 1; 00892 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; 00893 yy1 = yy0 / 100; 00894 yy2 = yy0 % 100; 00895 dow = ((26 * m1 - 2) / 10 + 00896 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; 00897 if (dow < 0) 00898 dow += DAYSPERWEEK; 00899 00900 /* 00901 ** "dow" is the day-of-week of the first day of the month. Get 00902 ** the day-of-month (zero-origin) of the first "dow" day of the 00903 ** month. 00904 */ 00905 d = rulep->r_day - dow; 00906 if (d < 0) 00907 d += DAYSPERWEEK; 00908 for (i = 1; i < rulep->r_week; ++i) { 00909 if (d + DAYSPERWEEK >= 00910 mon_lengths[leapyear][rulep->r_mon - 1]) 00911 break; 00912 d += DAYSPERWEEK; 00913 } 00914 00915 /* 00916 ** "d" is the day-of-month (zero-origin) of the day we want. 00917 */ 00918 value += d * SECSPERDAY; 00919 break; 00920 } 00921 00922 /* 00923 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in 00924 ** question. To get the Epoch-relative time of the specified local 00925 ** time on that day, add the transition time and the current offset 00926 ** from UTC. 00927 */ 00928 return value + rulep->r_time + offset; 00929 }
| static int tzload | ( | const char * | name, | |
| struct state *const | sp, | |||
| const int | doextend | |||
| ) | [static] |
Definition at line 423 of file localtime.c.
References add_notify(), state::ats, buf, state::charcnt, state::chars, detzcode(), detzcode64(), differ_by_repeat(), FALSE, state::goahead, state::goback, state::leapcnt, lsinfo::ls_corr, lsinfo::ls_trans, state::lsis, OPEN_MODE, state::timecnt, TRUE, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, state::ttis, state::typecnt, state::types, and tzparse().
Referenced by ast_tzset(), gmtload(), and tzparse().
00424 { 00425 const char * p; 00426 int i; 00427 int fid; 00428 int stored; 00429 int nread; 00430 union { 00431 struct tzhead tzhead; 00432 char buf[2 * sizeof(struct tzhead) + 00433 2 * sizeof *sp + 00434 4 * TZ_MAX_TIMES]; 00435 } u; 00436 00437 if (name == NULL && (name = TZDEFAULT) == NULL) 00438 return -1; 00439 { 00440 int doaccess; 00441 /* 00442 ** Section 4.9.1 of the C standard says that 00443 ** "FILENAME_MAX expands to an integral constant expression 00444 ** that is the size needed for an array of char large enough 00445 ** to hold the longest file name string that the implementation 00446 ** guarantees can be opened." 00447 */ 00448 char fullname[FILENAME_MAX + 1]; 00449 00450 if (name[0] == ':') 00451 ++name; 00452 doaccess = name[0] == '/'; 00453 if (!doaccess) { 00454 if ((p = TZDIR) == NULL) 00455 return -1; 00456 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) 00457 return -1; 00458 (void) strcpy(fullname, p); 00459 (void) strcat(fullname, "/"); 00460 (void) strcat(fullname, name); 00461 /* 00462 ** Set doaccess if '.' (as in "../") shows up in name. 00463 */ 00464 if (strchr(name, '.') != NULL) 00465 doaccess = TRUE; 00466 name = fullname; 00467 } 00468 if (doaccess && access(name, R_OK) != 0) 00469 return -1; 00470 if ((fid = open(name, OPEN_MODE)) == -1) 00471 return -1; 00472 add_notify(sp, name); 00473 } 00474 nread = read(fid, u.buf, sizeof u.buf); 00475 if (close(fid) < 0 || nread <= 0) 00476 return -1; 00477 for (stored = 4; stored <= 8; stored *= 2) { 00478 int ttisstdcnt; 00479 int ttisgmtcnt; 00480 00481 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); 00482 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); 00483 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); 00484 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); 00485 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); 00486 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); 00487 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; 00488 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || 00489 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || 00490 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || 00491 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || 00492 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || 00493 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) 00494 return -1; 00495 if (nread - (p - u.buf) < 00496 sp->timecnt * stored + /* ats */ 00497 sp->timecnt + /* types */ 00498 sp->typecnt * 6 + /* ttinfos */ 00499 sp->charcnt + /* chars */ 00500 sp->leapcnt * (stored + 4) + /* lsinfos */ 00501 ttisstdcnt + /* ttisstds */ 00502 ttisgmtcnt) /* ttisgmts */ 00503 return -1; 00504 for (i = 0; i < sp->timecnt; ++i) { 00505 sp->ats[i] = (stored == 4) ? 00506 detzcode(p) : detzcode64(p); 00507 p += stored; 00508 } 00509 for (i = 0; i < sp->timecnt; ++i) { 00510 sp->types[i] = (unsigned char) *p++; 00511 if (sp->types[i] >= sp->typecnt) 00512 return -1; 00513 } 00514 for (i = 0; i < sp->typecnt; ++i) { 00515 struct ttinfo * ttisp; 00516 00517 ttisp = &sp->ttis[i]; 00518 ttisp->tt_gmtoff = detzcode(p); 00519 p += 4; 00520 ttisp->tt_isdst = (unsigned char) *p++; 00521 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) 00522 return -1; 00523 ttisp->tt_abbrind = (unsigned char) *p++; 00524 if (ttisp->tt_abbrind < 0 || 00525 ttisp->tt_abbrind > sp->charcnt) 00526 return -1; 00527 } 00528 for (i = 0; i < sp->charcnt; ++i) 00529 sp->chars[i] = *p++; 00530 sp->chars[i] = '\0'; /* ensure '\0' at end */ 00531 for (i = 0; i < sp->leapcnt; ++i) { 00532 struct lsinfo * lsisp; 00533 00534 lsisp = &sp->lsis[i]; 00535 lsisp->ls_trans = (stored == 4) ? 00536 detzcode(p) : detzcode64(p); 00537 p += stored; 00538 lsisp->ls_corr = detzcode(p); 00539 p += 4; 00540 } 00541 for (i = 0; i < sp->typecnt; ++i) { 00542 struct ttinfo * ttisp; 00543 00544 ttisp = &sp->ttis[i]; 00545 if (ttisstdcnt == 0) 00546 ttisp->tt_ttisstd = FALSE; 00547 else { 00548 ttisp->tt_ttisstd = *p++; 00549 if (ttisp->tt_ttisstd != TRUE && 00550 ttisp->tt_ttisstd != FALSE) 00551 return -1; 00552 } 00553 } 00554 for (i = 0; i < sp->typecnt; ++i) { 00555 struct ttinfo * ttisp; 00556 00557 ttisp = &sp->ttis[i]; 00558 if (ttisgmtcnt == 0) 00559 ttisp->tt_ttisgmt = FALSE; 00560 else { 00561 ttisp->tt_ttisgmt = *p++; 00562 if (ttisp->tt_ttisgmt != TRUE && 00563 ttisp->tt_ttisgmt != FALSE) 00564 return -1; 00565 } 00566 } 00567 /* 00568 ** Out-of-sort ats should mean we're running on a 00569 ** signed time_t system but using a data file with 00570 ** unsigned values (or vice versa). 00571 */ 00572 for (i = 0; i < sp->timecnt - 2; ++i) 00573 if (sp->ats[i] > sp->ats[i + 1]) { 00574 ++i; 00575 if (TYPE_SIGNED(time_t)) { 00576 /* 00577 ** Ignore the end (easy). 00578 */ 00579 sp->timecnt = i; 00580 } else { 00581 /* 00582 ** Ignore the beginning (harder). 00583 */ 00584 int j; 00585 00586 for (j = 0; j + i < sp->timecnt; ++j) { 00587 sp->ats[j] = sp->ats[j + i]; 00588 sp->types[j] = sp->types[j + i]; 00589 } 00590 sp->timecnt = j; 00591 } 00592 break; 00593 } 00594 /* 00595 ** If this is an old file, we're done. 00596 */ 00597 if (u.tzhead.tzh_version[0] == '\0') 00598 break; 00599 nread -= p - u.buf; 00600 for (i = 0; i < nread; ++i) 00601 u.buf[i] = p[i]; 00602 /* 00603 ** If this is a narrow integer time_t system, we're done. 00604 */ 00605 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t)) 00606 break; 00607 } 00608 if (doextend && nread > 2 && 00609 u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && 00610 sp->typecnt + 2 <= TZ_MAX_TYPES) { 00611 struct state ts; 00612 int result; 00613 00614 u.buf[nread - 1] = '\0'; 00615 result = tzparse(&u.buf[1], &ts, FALSE); 00616 if (result == 0 && ts.typecnt == 2 && 00617 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { 00618 for (i = 0; i < 2; ++i) 00619 ts.ttis[i].tt_abbrind += 00620 sp->charcnt; 00621 for (i = 0; i < ts.charcnt; ++i) 00622 sp->chars[sp->charcnt++] = 00623 ts.chars[i]; 00624 i = 0; 00625 while (i < ts.timecnt && 00626 ts.ats[i] <= 00627 sp->ats[sp->timecnt - 1]) 00628 ++i; 00629 while (i < ts.timecnt && 00630 sp->timecnt < TZ_MAX_TIMES) { 00631 sp->ats[sp->timecnt] = 00632 ts.ats[i]; 00633 sp->types[sp->timecnt] = 00634 sp->typecnt + 00635 ts.types[i]; 00636 ++sp->timecnt; 00637 ++i; 00638 } 00639 sp->ttis[sp->typecnt++] = ts.ttis[0]; 00640 sp->ttis[sp->typecnt++] = ts.ttis[1]; 00641 } 00642 } 00643 i = 2 * YEARSPERREPEAT; 00644 sp->goback = sp->goahead = sp->timecnt > i; 00645 sp->goback = sp->goback && sp->types[i] == sp->types[0] && 00646 differ_by_repeat(sp->ats[i], sp->ats[0]); 00647 sp->goahead = sp->goahead && 00648 sp->types[sp->timecnt - 1] == sp->types[sp->timecnt - 1 - i] && 00649 differ_by_repeat(sp->ats[sp->timecnt - 1], 00650 sp->ats[sp->timecnt - 1 - i]); 00651 return 0; 00652 }
| static int tzparse | ( | const char * | name, | |
| struct state * | sp, | |||
| const int | lastditch | |||
| ) | [static] |
Definition at line 936 of file localtime.c.
References state::ats, state::charcnt, state::chars, EPOCH_YEAR, FALSE, getoffset(), getqzname(), getrule(), getzname(), isleap, state::leapcnt, SECSPERDAY, SECSPERHOUR, starttime, state::timecnt, transtime(), TRUE, ttinfo::tt_abbrind, ttinfo::tt_gmtoff, ttinfo::tt_isdst, ttinfo::tt_ttisgmt, ttinfo::tt_ttisstd, state::ttis, state::typecnt, state::types, TZDEFRULESTRING, tzload(), and year_lengths.
Referenced by ast_tzset(), gmtload(), and tzload().
00937 { 00938 const char * stdname; 00939 const char * dstname; 00940 size_t stdlen; 00941 size_t dstlen; 00942 long stdoffset; 00943 long dstoffset; 00944 time_t * atp; 00945 unsigned char * typep; 00946 char * cp; 00947 int load_result; 00948 00949 INITIALIZE(dstname); 00950 stdname = name; 00951 if (lastditch) { 00952 stdlen = strlen(name); /* length of standard zone name */ 00953 name += stdlen; 00954 if (stdlen >= sizeof sp->chars) 00955 stdlen = (sizeof sp->chars) - 1; 00956 stdoffset = 0; 00957 } else { 00958 if (*name == '<') { 00959 name++; 00960 stdname = name; 00961 name = getqzname(name, '>'); 00962 if (*name != '>') 00963 return -1; 00964 stdlen = name - stdname; 00965 name++; 00966 } else { 00967 name = getzname(name); 00968 stdlen = name - stdname; 00969 } 00970 if (*name == '\0') 00971 return -1; 00972 name = getoffset(name, &stdoffset); 00973 if (name == NULL) 00974 return -1; 00975 } 00976 load_result = tzload(TZDEFRULES, sp, FALSE); 00977 if (load_result != 0) 00978 sp->leapcnt = 0; /* so, we're off a little */ 00979 if (*name != '\0') { 00980 if (*name == '<') { 00981 dstname = ++name; 00982 name = getqzname(name, '>'); 00983 if (*name != '>') 00984 return -1; 00985 dstlen = name - dstname; 00986 name++; 00987 } else { 00988 dstname = name; 00989 name = getzname(name); 00990 dstlen = name - dstname; /* length of DST zone name */ 00991 } 00992 if (*name != '\0' && *name != ',' && *name != ';') { 00993 name = getoffset(name, &dstoffset); 00994 if (name == NULL) 00995 return -1; 00996 } else dstoffset = stdoffset - SECSPERHOUR; 00997 if (*name == '\0' && load_result != 0) 00998 name = TZDEFRULESTRING; 00999 if (*name == ',' || *name == ';') { 01000 struct rule start; 01001 struct rule end; 01002 int year; 01003 time_t janfirst; 01004 time_t starttime; 01005 time_t endtime; 01006 01007 ++name; 01008 if ((name = getrule(name, &start)) == NULL) 01009 return -1; 01010 if (*name++ != ',') 01011 return -1; 01012 if ((name = getrule(name, &end)) == NULL) 01013 return -1; 01014 if (*name != '\0') 01015 return -1; 01016 sp->typecnt = 2; /* standard time and DST */ 01017 /* 01018 ** Two transitions per year, from EPOCH_YEAR forward. 01019 */ 01020 sp->ttis[0].tt_gmtoff = -dstoffset; 01021 sp->ttis[0].tt_isdst = 1; 01022 sp->ttis[0].tt_abbrind = stdlen + 1; 01023 sp->ttis[1].tt_gmtoff = -stdoffset; 01024 sp->ttis[1].tt_isdst = 0; 01025 sp->ttis[1].tt_abbrind = 0; 01026 atp = sp->ats; 01027 typep = sp->types; 01028 janfirst = 0; 01029 sp->timecnt = 0; 01030 for (year = EPOCH_YEAR; 01031 sp->timecnt + 2 <= TZ_MAX_TIMES; 01032 ++year) { 01033 time_t newfirst; 01034 01035 starttime = transtime(janfirst, year, &start, 01036 stdoffset); 01037 endtime = transtime(janfirst, year, &end, 01038 dstoffset); 01039 if (starttime > endtime) { 01040 *atp++ = endtime; 01041 *typep++ = 1; /* DST ends */ 01042 *atp++ = starttime; 01043 *typep++ = 0; /* DST begins */ 01044 } else { 01045 *atp++ = starttime; 01046 *typep++ = 0; /* DST begins */ 01047 *atp++ = endtime; 01048 *typep++ = 1; /* DST ends */ 01049 } 01050 sp->timecnt += 2; 01051 newfirst = janfirst; 01052 newfirst += year_lengths[isleap(year)] * 01053 SECSPERDAY; 01054 if (newfirst <= janfirst) 01055 break; 01056 janfirst = newfirst; 01057 } 01058 } else { 01059 long theirstdoffset; 01060 long theirdstoffset; 01061 long theiroffset; 01062 int isdst; 01063 int i; 01064 int j; 01065 01066 if (*name != '\0') 01067 return -1; 01068 /* 01069 ** Initial values of theirstdoffset and theirdstoffset. 01070 */ 01071 theirstdoffset = 0; 01072 for (i = 0; i < sp->timecnt; ++i) { 01073 j = sp->types[i]; 01074 if (!sp->ttis[j].tt_isdst) { 01075 theirstdoffset = 01076 -sp->ttis[j].tt_gmtoff; 01077 break; 01078 } 01079 } 01080 theirdstoffset = 0; 01081 for (i = 0; i < sp->timecnt; ++i) { 01082 j = sp->types[i]; 01083 if (sp->ttis[j].tt_isdst) { 01084 theirdstoffset = 01085 -sp->ttis[j].tt_gmtoff; 01086 break; 01087 } 01088 } 01089 /* 01090 ** Initially we're assumed to be in standard time. 01091 */ 01092 isdst = FALSE; 01093 theiroffset = theirstdoffset; 01094 /* 01095 ** Now juggle transition times and types 01096 ** tracking offsets as you do. 01097 */ 01098 for (i = 0; i < sp->timecnt; ++i) { 01099 j = sp->types[i]; 01100 sp->types[i] = sp->ttis[j].tt_isdst; 01101 if (sp->ttis[j].tt_ttisgmt) { 01102 /* No adjustment to transition time */ 01103 } else { 01104 /* 01105 ** If summer time is in effect, and the 01106 ** transition time was not specified as 01107 ** standard time, add the summer time 01108 ** offset to the transition time; 01109 ** otherwise, add the standard time 01110 ** offset to the transition time. 01111 */ 01112 /* 01113 ** Transitions from DST to DDST 01114 ** will effectively disappear since 01115 ** POSIX provides for only one DST 01116 ** offset. 01117 */ 01118 if (isdst && !sp->ttis[j].tt_ttisstd) { 01119 sp->ats[i] += dstoffset - 01120 theirdstoffset; 01121 } else { 01122 sp->ats[i] += stdoffset - 01123 theirstdoffset; 01124 } 01125 } 01126 theiroffset = -sp->ttis[j].tt_gmtoff; 01127 if (sp->ttis[j].tt_isdst) 01128 theirdstoffset = theiroffset; 01129 else theirstdoffset = theiroffset; 01130 } 01131 /* 01132 ** Finally, fill in ttis. 01133 ** ttisstd and ttisgmt need not be handled. 01134 */ 01135 sp->ttis[0].tt_gmtoff = -stdoffset; 01136 sp->ttis[0].tt_isdst = FALSE; 01137 sp->ttis[0].tt_abbrind = 0; 01138 sp->ttis[1].tt_gmtoff = -dstoffset; 01139 sp->ttis[1].tt_isdst = TRUE; 01140 sp->ttis[1].tt_abbrind = stdlen + 1; 01141 sp->typecnt = 2; 01142 } 01143 } else { 01144 dstlen = 0; 01145 sp->typecnt = 1; /* only standard time */ 01146 sp->timecnt = 0; 01147 sp->ttis[0].tt_gmtoff = -stdoffset; 01148 sp->ttis[0].tt_isdst = 0; 01149 sp->ttis[0].tt_abbrind = 0; 01150 } 01151 sp->charcnt = stdlen + 1; 01152 if (dstlen != 0) 01153 sp->charcnt += dstlen + 1; 01154 if ((size_t) sp->charcnt > sizeof sp->chars) 01155 return -1; 01156 cp = sp->chars; 01157 (void) strncpy(cp, stdname, stdlen); 01158 cp += stdlen; 01159 *cp++ = '\0'; 01160 if (dstlen != 0) { 01161 (void) strncpy(cp, dstname, dstlen); 01162 *(cp + dstlen) = '\0'; 01163 } 01164 return 0; 01165 }
char elsieid[] = "@(#)localtime.c 8.5" [static] |
Definition at line 69 of file localtime.c.
const char gmt[] = "GMT" [static] |
Definition at line 97 of file localtime.c.
ast_cond_t initialization [static] |
Definition at line 229 of file localtime.c.
Referenced by add_notify(), and inotify_daemon().
ast_mutex_t initialization_lock [static] |
Definition at line 230 of file localtime.c.
Referenced by add_notify(), and inotify_daemon().
int inotify_fd = -1 [static] |
Definition at line 232 of file localtime.c.
Referenced by add_notify(), and inotify_daemon().
pthread_t inotify_thread = AST_PTHREADT_NULL [static] |
Definition at line 228 of file localtime.c.
Referenced by add_notify(), and inotify_daemon().
const int mon_lengths[2][MONSPERYEAR] [static] |
{
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
}
Definition at line 654 of file localtime.c.
Referenced by time2sub(), timesub(), and transtime().
struct timeval WRONG = { 0, 0 } [static] |
Definition at line 98 of file localtime.c.
const int year_lengths[2] [static] |
{
DAYSPERNYEAR, DAYSPERLYEAR
}
Definition at line 659 of file localtime.c.
Referenced by time2sub(), timesub(), and tzparse().
1.6.2