59 #include <sys/inotify.h> 60 #elif defined(HAVE_KQUEUE) 61 #include <sys/types.h> 63 #include <sys/event.h> 82 static char __attribute__((unused))
elsieid[] =
"@(#)localtime.c 8.5";
86 #ifndef TZ_ABBR_MAX_LEN 87 #define TZ_ABBR_MAX_LEN 16 90 #ifndef TZ_ABBR_CHAR_SET 91 #define TZ_ABBR_CHAR_SET \ 92 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" 95 #ifndef TZ_ABBR_ERR_CHAR 96 #define TZ_ABBR_ERR_CHAR '_' 104 #define OPEN_MODE (O_RDONLY | O_BINARY) 107 #define OPEN_MODE O_RDONLY 110 static const char gmt[] =
"GMT";
111 static const struct timeval
WRONG = { 0, 0 };
113 #ifdef TEST_FRAMEWORK 127 #ifndef TZDEFRULESTRING 128 #define TZDEFRULESTRING ",M4.1.0,M10.5.0" 146 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) 149 #define MY_TZNAME_MAX TZNAME_MAX 152 #define MY_TZNAME_MAX 255 154 #ifndef TZ_STRLEN_MAX 155 #define TZ_STRLEN_MAX 255 175 #elif defined(HAVE_KQUEUE) 177 # ifdef HAVE_O_SYMLINK 189 #define SP_STACK_FLAG INT_MIN 191 # define SP_STACK_INIT(sp) do { \ 192 (sp).wd[0] = SP_STACK_FLAG; \ 194 # define SP_STACK_CHECK(sp) ((sp)->wd[0] == SP_STACK_FLAG) 195 # define SP_HEAP_INIT(sp) do { \ 199 # define SP_HEAP_FREE(sp) do {} while (0) 201 #elif defined(HAVE_KQUEUE) 202 # define SP_STACK_INIT(sp) do { \ 203 (sp).fd = SP_STACK_FLAG; \ 205 # define SP_STACK_CHECK(sp) ((sp)->fd == SP_STACK_FLAG) 206 #ifdef HAVE_O_SYMLINK 207 # define SP_HEAP_INIT(sp) do { \ 211 # define SP_HEAP_FREE(sp) do { \ 213 kqueue_daemon_freestate(sp); \ 214 if ((sp)->fd > -1) { close((sp)->fd); (sp)->fd = -1; } \ 215 if ((sp)->fds > -1) { close((sp)->fds); (sp)->fds = -1; } \ 220 # define SP_HEAP_INIT(sp) do { \ 224 # define SP_HEAP_FREE(sp) do { \ 226 kqueue_daemon_freestate(sp); \ 227 if ((sp)->fd > -1) { close((sp)->fd); (sp)->fd = -1; } \ 228 if ((sp)->dir != NULL) { closedir((sp)->dir); (sp)->dir = NULL; } \ 235 # define SP_STACK_INIT(sp) do {} while (0) 236 # define SP_STACK_CHECK(sp) (0) 237 # define SP_HEAP_INIT(sp) do {} while (0) 238 # define SP_HEAP_FREE(sp) do {} while (0) 257 #define DAY_OF_YEAR 1 258 #define MONTH_NTH_DAY_OF_WEEK 2 264 static long detzcode P((
const char * codep));
267 static const char *
getzname P((
const char * strp));
268 static const char *
getqzname P((
const char * strp,
const int delim));
269 static const char *
getnum P((
const char * strp,
int * nump,
int min,
271 static const char *
getsecs P((
const char * strp,
long * secsp));
272 static const char *
getoffset P((
const char * strp,
long * offsetp));
273 static const char *
getrule P((
const char * strp,
struct rule * rulep));
275 static struct ast_tm *
gmtsub P((
const struct timeval * timep,
long offset,
277 static struct ast_tm *
localsub P((
const struct timeval * timep,
long offset,
283 int * unitsptr,
const int base));
287 struct ast_tm * (*funcp)
P((
const struct timeval *,
289 long offset,
const struct state *sp));
291 struct ast_tm * (*funcp)
P((
const struct timeval *,
293 long offset,
int * okayp,
const struct state *sp));
295 struct ast_tm * (*funcp) (
const struct timeval *,
297 long offset,
int * okayp,
int do_norm_secs,
const struct state *sp));
298 static struct ast_tm *
timesub P((
const struct timeval * timep,
long offset,
301 const struct ast_tm * btmp));
302 static time_t
transtime P((time_t janfirst,
int year,
303 const struct rule * rulep,
long offset));
304 static int tzload P((
const char * name,
struct state * sp,
313 #if defined(HAVE_NEWLOCALE) && defined(HAVE_USELOCALE) 317 #ifndef TZ_STRLEN_MAX 318 #define TZ_STRLEN_MAX 255 337 if (sp->
name[0] ==
'/') {
338 snprintf(name,
sizeof(name),
"%s", sp->
name);
340 snprintf(name,
sizeof(name),
"/etc/%s", sp->
name);
342 snprintf(name,
sizeof(name),
"%s/%s",
TZDIR, sp->
name);
356 struct inotify_event *iev;
357 size_t real_sizeof_iev =
sizeof(*iev) +
FILENAME_MAX + 1;
361 inotify_fd = inotify_init();
367 if (inotify_fd < 0) {
378 if ((res = read(inotify_fd, iev, real_sizeof_iev)) <
sizeof(*iev) && res > 0) {
380 ast_log(
LOG_ERROR,
"Inotify read less than a full event (%zd < %zu)?!!\n", res,
sizeof(*iev));
382 }
else if (res < 0) {
396 if (cur->
wd[0] == iev->wd || cur->
wd[1] == iev->wd) {
428 fprintf(stderr,
"Unable to start notification thread\n");
435 if (inotify_fd > -1) {
437 if (readlink(path, fullpath,
sizeof(fullpath) - 1) != -1) {
439 sp->
wd[1] = inotify_add_watch(inotify_fd, fullpath, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE );
444 sp->
wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE
445 #ifdef IN_DONT_FOLLOW
451 #elif defined(HAVE_KQUEUE) 452 static int queue_fd = -1;
467 # define EVVN_NOTES_BITS \ 468 (NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_REVOKE|NOTE_ATTRIB \ 469 |NOTE_RENAME|NOTE_LINK|NOTE_TRUNCATE) 471 # define EVVN_NOTES_BITS \ 472 (NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_REVOKE|NOTE_ATTRIB \ 473 |NOTE_RENAME|NOTE_LINK) 476 static void *kqueue_daemon(
void *data)
482 if (queue_fd < 0 && (queue_fd = kqueue()) < 0) {
485 fprintf(stderr,
"Unable to initialize kqueue(): %s\n", strerror(
errno));
500 if (kevent(queue_fd,
NULL, 0, &kev, 1,
NULL) < 0) {
507 sp = (
struct state *) kev.udata;
533 static void kqueue_daemon_freestate(
struct state *sp)
536 struct timespec no_wait = { 0, 1 };
552 EV_SET(&kev, sp->fd, EVFILT_VNODE, EV_DELETE, 0, 0,
NULL);
553 kevent(queue_fd, &kev, 1,
NULL, 0, &no_wait);
556 #ifdef HAVE_O_SYMLINK 559 EV_SET(&kev, sp->fds, EVFILT_VNODE, EV_DELETE, 0, 0,
NULL);
560 kevent(queue_fd, &kev, 1,
NULL, 0, &no_wait);
565 EV_SET(&kev, dirfd(sp->dir), EVFILT_VNODE, EV_DELETE, 0, 0,
NULL);
566 kevent(queue_fd, &kev, 1,
NULL, 0, &no_wait);
574 struct timespec no_wait = { 0, 1 };
596 if (psx_sp !=
NULL ||
603 sizeof(psx_sp->
name));
624 #ifdef HAVE_O_SYMLINK 625 if (readlink(path, watchdir,
sizeof(watchdir) - 1) != -1 && (sp->fds = open(path, O_RDONLY | O_SYMLINK
626 # ifdef HAVE_O_EVTONLY
630 EV_SET(&kev, sp->fds, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, EVVN_NOTES_BITS, 0, sp);
632 if (kevent(queue_fd, &kev, 1,
NULL, 0, &no_wait) < 0 &&
errno != 0) {
637 fprintf(stderr,
"Unable to watch '%s': %s\n", path, strerror(
errno));
643 if (readlink(path, watchdir,
sizeof(watchdir) - 1) != -1) {
649 if ((slash = strrchr(watchdir,
'/'))) {
652 if (!(sp->dir = opendir(watchdir))) {
653 fprintf(stderr,
"Unable to watch directory with symlink '%s': %s\n", path, strerror(
errno));
666 EV_SET(&kev, dirfd(sp->dir), EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
667 EVVN_NOTES_BITS, 0, sp);
669 if (kevent(queue_fd, &kev, 1,
NULL, 0, &no_wait) < 0 &&
errno != 0) {
670 fprintf(stderr,
"Unable to watch '%s': %s\n", watchdir, strerror(
errno));
679 if ((sp->fd = open(path, O_RDONLY
680 # ifdef HAVE_O_EVTONLY
684 fprintf(stderr,
"Unable to watch '%s' for changes: %s\n", path, strerror(
errno));
688 EV_SET(&kev, sp->fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, EVVN_NOTES_BITS, 0, sp);
690 if (kevent(queue_fd, &kev, 1,
NULL, 0, &no_wait) < 0 &&
errno != 0) {
695 fprintf(stderr,
"Unable to watch '%s': %s\n", path, strerror(
errno));
702 static void *notify_daemon(
void *data)
706 struct timespec sixty_seconds = { 60, 0 };
717 nanosleep(&sixty_seconds,
NULL);
720 char *name = cur->
name;
724 if (name[0] !=
'/') {
725 (void) strcpy(fullname,
TZDIR "/");
726 (void) strcat(fullname, name);
731 if (st.st_mtime > cur->mtime[0] || lst.st_mtime > cur->mtime[1]) {
732 #ifdef TEST_FRAMEWORK 734 ast_test_status_update(test,
"Removing cached TZ entry '%s' because underlying file changed. (%ld != %ld) or (%ld != %ld)\n", name, st.st_mtime, cur->mtime[0], lst.st_mtime, cur->mtime[1]);
738 ast_log(
LOG_NOTICE,
"Removing cached TZ entry '%s' because underlying file changed.\n", name);
769 sp->mtime[0] = st.st_mtime;
771 sp->mtime[1] = st.st_mtime;
798 struct timespec wait_time = { .tv_sec = wait_now.tv_sec + 2, .tv_nsec = wait_now.tv_usec * 1000 };
802 #ifdef TEST_FRAMEWORK 805 pthread_kill(inotify_thread, SIGURG);
807 #ifdef TEST_FRAMEWORK 827 result = (codep[0] & 0x80) ? ~0L : 0;
828 for (i = 0; i < 4; ++i)
829 result = (result << 8) | (codep[i] & 0xff);
839 for (i = 0; i < 8; ++i)
840 result = result * 256 + (codep[i] & 0xff);
846 const long long at1 =
t1, at0 = t0;
853 static int tzload(
const char *name,
struct state *
const sp,
const int doextend)
862 char buf[2 *
sizeof(
struct tzhead) +
882 doaccess = name[0] ==
'/';
886 if ((strlen(p) + strlen(name) + 1) >=
sizeof fullname)
888 (void) strcpy(fullname, p);
889 (void) strcat(fullname,
"/");
890 (void) strcat(fullname, name);
894 if (strchr(name,
'.') !=
NULL)
898 if (doaccess && access(name, R_OK) != 0)
911 nread = read(fid, u.buf,
sizeof u.buf);
913 if (close(fid) < 0 || nread <
sizeof u.tzhead)
915 for (stored = 4; stored <= 8; stored *= 2) {
919 ttisstdcnt = (int)
detzcode(u.tzhead.tzh_ttisstdcnt);
920 ttisgmtcnt = (int)
detzcode(u.tzhead.tzh_ttisgmtcnt);
925 p = u.tzhead.tzh_charcnt +
sizeof u.tzhead.tzh_charcnt;
930 (ttisstdcnt != sp->
typecnt && ttisstdcnt != 0) ||
931 (ttisgmtcnt != sp->
typecnt && ttisgmtcnt != 0))
933 if (nread - (p - u.buf) <
942 for (i = 0; i < sp->
timecnt; ++i) {
943 sp->
ats[i] = (stored == 4) ?
947 for (i = 0; i < sp->
timecnt; ++i) {
948 sp->
types[i] = (
unsigned char) *p++;
952 for (i = 0; i < sp->
typecnt; ++i) {
955 ttisp = &sp->
ttis[i];
958 ttisp->
tt_isdst = (
unsigned char) *p++;
966 for (i = 0; i < sp->
charcnt; ++i)
969 for (i = 0; i < sp->
leapcnt; ++i) {
972 lsisp = &sp->
lsis[i];
979 for (i = 0; i < sp->
typecnt; ++i) {
982 ttisp = &sp->
ttis[i];
992 for (i = 0; i < sp->
typecnt; ++i) {
995 ttisp = &sp->
ttis[i];
1010 for (i = 0; i < sp->
timecnt - 2; ++i)
1011 if (sp->
ats[i] > sp->
ats[i + 1]) {
1024 for (j = 0; j + i < sp->
timecnt; ++j) {
1025 sp->
ats[j] = sp->
ats[j + i];
1035 if (u.tzhead.tzh_version[0] ==
'\0')
1038 for (i = 0; i < nread; ++i)
1042 if (nread <
sizeof(u.tzhead)) {
1048 if (stored >= (
int)
sizeof(time_t) &&
TYPE_INTEGRAL(time_t))
1051 if (doextend && nread > 2 &&
1052 u.buf[0] ==
'\n' && u.buf[nread - 1] ==
'\n' &&
1063 u.buf[nread - 1] =
'\0';
1065 if (result == 0 && ts.
typecnt == 2 &&
1067 for (i = 0; i < 2; ++i)
1070 for (i = 0; i < ts.
charcnt; ++i)
1104 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
1105 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
1122 while ((c = *strp) !=
'\0' && !
is_digit(c) && c !=
',' && c !=
'-' &&
1137 static const char *
getqzname(
const char *strp,
const int delim)
1141 while ((c = *strp) !=
'\0' && c != delim)
1153 static const char *
getnum(
const char *strp,
int *nump,
const int min,
const int max)
1162 num = num * 10 + (c -
'0');
1181 static const char *
getsecs(
const char *strp,
long *
const secsp)
1204 strp =
getnum(strp, &num, 0, SECSPERMIN);
1220 static const char *
getoffset(
const char *strp,
long *offsetp)
1227 }
else if (*strp ==
'+')
1229 strp =
getsecs(strp, offsetp);
1233 *offsetp = -*offsetp;
1253 }
else if (*strp ==
'M') {
1275 strp =
getnum(strp, &rulep->
r_day, 0, DAYSPERLYEAR - 1);
1295 static time_t
transtime(
const time_t janfirst,
const int year,
const struct rule *rulep,
const long offset)
1300 int d, m1, yy0, yy1, yy2, dow;
1315 if (leapyear && rulep->
r_day >= 60)
1333 for (i = 0; i < rulep->
r_mon - 1; ++i)
1334 value += mon_lengths[leapyear][i] *
SECSPERDAY;
1340 m1 = (rulep->
r_mon + 9) % 12 + 1;
1341 yy0 = (rulep->
r_mon <= 2) ? (year - 1) : year;
1344 dow = ((26 * m1 - 2) / 10 +
1345 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1354 d = rulep->
r_day - dow;
1357 for (i = 1; i < rulep->
r_week; ++i) {
1359 mon_lengths[leapyear][rulep->
r_mon - 1])
1377 return value + rulep->
r_time + offset;
1385 static int tzparse(
const char *name,
struct state *sp,
const int lastditch)
1387 const char * stdname;
1388 const char * dstname;
1394 unsigned char * typep;
1401 stdlen = strlen(name);
1403 if (stdlen >=
sizeof sp->
chars)
1404 stdlen = (
sizeof sp->
chars) - 1;
1413 stdlen = name - stdname;
1417 stdlen = name - stdname;
1426 if (load_result != 0)
1428 if (*name !=
'\0') {
1434 dstlen = name - dstname;
1439 dstlen = name - dstname;
1441 if (*name !=
'\0' && *name !=
',' && *name !=
';') {
1446 if (*name ==
'\0' && load_result != 0)
1448 if (*name ==
',' || *name ==
';') {
1484 starttime =
transtime(janfirst, year, &start,
1486 endtime =
transtime(janfirst, year, &end,
1488 if (starttime > endtime) {
1500 newfirst = janfirst;
1501 newfirst += year_lengths[
isleap(year)] *
1503 if (newfirst <= janfirst)
1505 janfirst = newfirst;
1508 long theirstdoffset;
1519 for (i = 0; i < sp->
timecnt; ++i) {
1527 theiroffset = theirstdoffset;
1532 for (i = 0; i < sp->
timecnt; ++i) {
1539 sp->
ats[i] += stdoffset - theirstdoffset;
1543 theirstdoffset = theiroffset;
1572 (void) strncpy(cp, stdname, stdlen);
1576 (void) strncpy(cp, dstname, dstlen);
1577 *(cp + dstlen) =
'\0';
1607 zone = getenv(
"TZ");
1612 zone =
"/etc/localtime";
1618 if (!strcmp(sp->
name, zone)) {
1650 const struct ttinfo * ttisp;
1654 memcpy(&t, timep,
sizeof(t));
1657 return gmtsub(timep, offset, tmp);
1658 if ((sp->
goback && t.tv_sec < sp->
ats[0]) ||
1660 struct timeval newt = t;
1665 if (t.tv_sec < sp->
ats[0])
1666 seconds = sp->
ats[0] - t.tv_sec;
1667 else seconds = t.tv_sec - sp->
ats[sp->
timecnt - 1];
1672 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1677 if (t.tv_sec < sp->
ats[0])
1678 newt.tv_sec += seconds;
1679 else newt.tv_sec -= seconds;
1680 if (newt.tv_sec < sp->
ats[0] ||
1683 result =
localsub(&newt, offset, tmp, sp);
1684 if (result == tmp) {
1688 if (t.tv_sec < sp->
ats[0])
1698 if (sp->
timecnt == 0 || t.tv_sec < sp->
ats[0]) {
1711 int mid = (lo + hi) >> 1;
1713 if (t.tv_sec < sp->
ats[mid])
1718 i = (int) sp->
types[lo - 1];
1720 ttisp = &sp->
ttis[i];
1735 tmp->
tm_usec = timep->tv_usec;
1742 memset(tmp, 0,
sizeof(*tmp));
1754 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)
1757 int transition1 = -1;
1758 int transition2 = -1;
1760 int bounds_exceeded = 0;
1762 const struct state *sp;
1764 if (
NULL == dst_enabled)
1768 if (
NULL == dst_start ||
NULL == dst_end ||
NULL == gmt_off)
1783 if ((sp->
goback && t < sp->ats[0]) ||
1789 seconds = sp->
ats[0] - t;
1795 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1805 if (t < sp->ats[0] || t > sp->
ats[sp->
timecnt - 1])
1808 bounds_exceeded = 1;
1811 if (sp->
timecnt == 0 || t < sp->ats[0]) {
1826 for (i = 1; i < sp->
timecnt; ++i) {
1827 if (t < sp->ats[i]) {
1828 transition1 = sp->
types[i - 1];
1829 transition2 = sp->
types[i];
1835 if (i >= sp->
timecnt || 0 > transition1 || 0 > transition2 ||
1847 if (!bounds_exceeded) {
1851 *dst_start = sp->
ats[i];
1852 *dst_end = sp->
ats[i -1];
1854 *dst_start = sp->
ats[i -1];
1855 *dst_end = sp->
ats[i];
1873 if (!strcmp(sp->
name,
"UTC"))
1887 result =
timesub(timep, offset, sp, tmp);
1897 tmp->TM_ZONE = sp->
chars;
1909 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1915 const struct lsinfo * lp;
1932 if (timep->tv_sec >= lp->
ls_trans) {
1933 if (timep->tv_sec == lp->
ls_trans) {
1934 hit = ((i == 0 && lp->
ls_corr > 0) ||
1953 while (tdays < 0 || tdays >= year_lengths[
isleap(y)]) {
1961 if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
1964 idelta = (tdays < 0) ? -1 : 1;
1975 seconds = tdays * SECSPERDAY + 0.5;
1983 rem += offset - corr;
1988 while (rem >= SECSPERDAY) {
1995 idays += year_lengths[
isleap(y)];
1997 while (idays >= year_lengths[
isleap(y)]) {
1998 idays -= year_lengths[
isleap(y)];
2026 ip = mon_lengths[
isleap(y)];
2028 idays -= ip[tmp->
tm_mon];
2029 tmp->
tm_mday = (int) (idays + 1);
2032 tmp->TM_GMTOFF = offset;
2034 tmp->
tm_usec = timep->tv_usec;
2057 return (*number < number0) != (delta < 0);
2066 return (*number < number0) != (delta < 0);
2073 tensdelta = (*unitsptr >= 0) ?
2074 (*unitsptr / base) :
2075 (-1 - (-1 - *unitsptr) / base);
2076 *unitsptr -= tensdelta * base;
2084 tensdelta = (*unitsptr >= 0) ?
2085 (*unitsptr / base) :
2086 (-1 - (-1 - *unitsptr) / base);
2087 *unitsptr -= tensdelta * base;
2105 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)
2114 struct timeval newt = { 0, 0 };
2115 struct timeval t = { 0, 0 };
2116 struct ast_tm yourtm, mytm;
2141 li = y + (1 < yourtm.
tm_mon);
2144 while (yourtm.
tm_mday > DAYSPERLYEAR) {
2145 li = y + (1 < yourtm.
tm_mon);
2179 saved_seconds = yourtm.
tm_sec;
2182 saved_seconds = yourtm.
tm_sec;
2192 if (
sizeof(time_t) >
sizeof(
float))
2193 hi = (time_t) DBL_MAX;
2194 else hi = (time_t) FLT_MAX;
2198 for (i = 0; i < (int)
TYPE_BIT(time_t) - 1; ++i)
2203 t.tv_sec = lo / 2 + hi / 2;
2206 else if (t.tv_sec > hi)
2208 if ((*funcp)(&t, offset, &mytm, sp) ==
NULL) {
2214 dir = (t.tv_sec > 0) ? 1 : -1;
2215 }
else dir =
tmcomp(&mytm, &yourtm);
2217 if (t.tv_sec == lo) {
2222 }
else if (t.tv_sec == hi) {
2246 for (i = sp->
typecnt - 1; i >= 0; --i) {
2249 for (j = sp->
typecnt - 1; j >= 0; --j) {
2254 if ((*funcp)(&newt, offset, &mytm, sp) ==
NULL)
2256 if (
tmcomp(&mytm, &yourtm) != 0)
2258 if (mytm.tm_isdst != yourtm.
tm_isdst)
2270 newt.tv_sec = t.tv_sec + saved_seconds;
2271 if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0))
2273 t.tv_sec = newt.tv_sec;
2274 if ((*funcp)(&t, offset, tmp, sp))
2279 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)
2289 return *okayp ? t :
time2sub(tmp, funcp, offset, okayp,
TRUE, sp);
2296 int sameind, otherind;
2303 if (tmp->tm_isdst > 1)
2305 t =
time2(tmp, funcp, offset, &okay, sp);
2312 if (tmp->tm_isdst < 0)
2316 if (okay || tmp->tm_isdst < 0)
2327 for (i = 0; i < sp->
typecnt; ++i)
2330 for (i = sp->
timecnt - 1; i >= 0; --i)
2331 if (!seen[sp->
types[i]]) {
2333 types[nseen++] = sp->
types[i];
2335 for (sameind = 0; sameind < nseen; ++sameind) {
2336 samei = types[sameind];
2339 for (otherind = 0; otherind < nseen; ++otherind) {
2340 otheri = types[otherind];
2345 tmp->tm_isdst = !tmp->tm_isdst;
2346 t =
time2(tmp, funcp, offset, &okay, sp);
2351 tmp->tm_isdst = !tmp->tm_isdst;
2359 const struct state *sp;
2365 #if defined(HAVE_NEWLOCALE) && defined(HAVE_USELOCALE) 2370 if (locale == cur->
locale) {
2381 if (strcmp(name, cur->
name) == 0) {
2391 if (prevlocale == LC_GLOBAL_LOCALE) {
2402 for (x = 0; x < 10000; x++) {
2404 snprintf(name,
sizeof(name),
"%04d", x);
2406 if ((cur =
ast_calloc(1,
sizeof(*cur) + strlen(name) + 1))) {
2407 cur->
locale = prevlocale;
2408 strcpy(cur->
name, name);
2423 locale_t prevlocale = LC_GLOBAL_LOCALE;
2425 if (locale ==
NULL) {
2431 prevlocale = uselocale(cur->
locale);
2435 if ((cur =
ast_calloc(1,
sizeof(*cur) + strlen(locale) + 1))) {
2436 cur->
locale = newlocale(LC_ALL_MASK, locale,
NULL);
2437 strcpy(cur->
name, locale);
2439 prevlocale = uselocale(cur->
locale);
2454 size_t fmtlen = strlen(tmp) + 1;
2456 int decimals = -1, i, res;
2458 const char *prevlocale;
2464 for (; *
tmp; tmp++) {
2473 if (tmp[2] !=
'q') {
2476 decimals = tmp[1] -
'0';
2480 if (decimals == -1) {
2490 fptr = fptr - format + newfmt;
2495 for (i = 6, fraction = tm->
tm_usec; i > decimals; i--) {
2498 fptr += sprintf(fptr,
"%0*ld", decimals, fraction);
2508 defcase: *fptr++ = *
tmp;
2516 res = (int)strftime(buf, len, format, (
struct tm *)tm);
2531 struct tm tm2 = { 0, };
2533 const char *prevlocale;
2536 res = strptime(s, format, &tm2);
2542 memcpy(tm, &tm2,
sizeof(tm2));
static time_t detzcode64(const char *const codep)
static struct ast_tm * timesub(const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
#define TYPE_SIGNED(type)
static struct ast_tm * localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
#define AST_LIST_LOCK(head)
Locks a list.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
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.
#define ast_realloc(p, len)
A wrapper for realloc()
String manipulation functions.
#define SP_STACK_CHECK(sp)
const char * ast_setlocale(const char *locale)
Set the thread-local representation of the current locale.
static ast_cond_t initialization
char name[TZ_STRLEN_MAX+1]
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define SECSPERREPEAT_BITS
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 i...
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 strfti...
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 ...
static const int mon_lengths[2][MONSPERYEAR]
#define ast_cond_wait(cond, mutex)
#define ast_cond_init(cond, attr)
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define ast_mutex_lock(a)
static const struct timeval WRONG
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *tmp, const char *zone)
Timezone-independent version of localtime_r(3).
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
#define SP_STACK_INIT(sp)
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define ast_cond_signal(cond)
static void sstate_free(struct state *p)
#define TYPE_INTEGRAL(type)
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, sizeof gmt),(2 *(MY_TZNAME_MAX+1)))]
static struct locale_entry * find_by_name(const char *name)
static struct state * sstate_alloc(void)
void ast_localtime_wakeup_monitor(struct ast_test *info)
pthread_cond_t ast_cond_t
#define ast_strlen_zero(foo)
static int tzload(const char *name, struct state *const sp, const int doextend)
static int gmtload(struct state *sp)
#define ast_pthread_create_background(a, b, c, d)
Custom localtime functions for multiple timezones.
struct timeval ast_mktime(struct ast_tm *tmp, const char *zone)
Timezone-independent version of mktime(3).
struct lsinfo lsis[TZ_MAX_LEAPS]
#define ast_test_status_update(a, b, c...)
static int normalize_overflow(int *tensptr, int *unitsptr, const int base)
#define AST_PTHREADT_NULL
char * ast_strptime_locale(const char *s, const char *format, struct ast_tm *tm, const char *locale)
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
A set of macros to manage forward-linked lists.
static struct locale_entry * find_by_locale(locale_t locale)
static int long_normalize_overflow(long *tensptr, int *unitsptr, const int base)
#define ast_cond_broadcast(cond)
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
static long detzcode(const char *const codep)
static ast_mutex_t initialization_lock
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
static void * inotify_daemon(void *data)
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
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 ...
static int increment_overflow(int *number, int delta)
Simplified normalize logic courtesy Paul Eggert.
static void common_startup(void)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static long detzcode P((const char *codep))
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
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.
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)
#define ast_calloc(num, len)
A wrapper for calloc()
Prototypes for public functions only of internal interest,.
#define MONTH_NTH_DAY_OF_WEEK
static int differ_by_repeat(const time_t t1, const time_t t0)
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...
static int tmcomp(const struct ast_tm *atmp, const struct ast_tm *btmp)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static const int year_lengths[2]
#define AST_LIST_TRYLOCK(head)
Locks a list, without blocking if the list is locked.
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...
static struct ast_tm * gmtsub(const struct timeval *timep, const long offset, struct ast_tm *tmp)
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
static int tzparse(const char *name, struct state *sp, const int lastditch)
#define ast_mutex_init(pmutex)
you may need to compile with DHAVE_STDINT_H typedef long int_fast64_t
static int long_increment_overflow(long *number, int delta)
unsigned char types[TZ_MAX_TIMES]
static pthread_t inotify_thread
struct locale_entry::@424 list
static const char * store_by_locale(locale_t prevlocale)
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 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 void add_notify(struct state *sp, const char *path)
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 snd_pcm_format_t format
static const struct state * ast_tzset(const char *zone)
int ast_strftime_locale(char *buf, size_t len, const char *tmp, const struct ast_tm *tm, const char *locale)
struct ttinfo ttis[TZ_MAX_TYPES]
#define ast_cond_timedwait(cond, mutex, time)
void clean_time_zones(void)
Structure for mutex and tracking information.
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 zo...
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.
#define ast_mutex_unlock(a)