59#include <sys/inotify.h>
60#elif defined(HAVE_KQUEUE)
82static 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
110static const char gmt[] =
"GMT";
111static const struct timeval
WRONG = { 0, 0 };
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
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)
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)
258#define MONTH_NTH_DAY_OF_WEEK 2
268static const char *
getqzname P((
const char * strp,
const int delim));
269static const char *
getnum P((
const char * strp,
int * nump,
int min,
271static const char *
getsecs P((
const char * strp,
long * secsp));
272static const char *
getoffset P((
const char * strp,
long * offsetp));
273static const char *
getrule P((
const char * strp,
struct rule * rulep));
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));
301 const struct ast_tm * btmp));
303 const struct rule * rulep,
long offset));
313#if defined(HAVE_NEWLOCALE) && defined(HAVE_USELOCALE)
318#define TZ_STRLEN_MAX 255
337 if (sp->
name[0] ==
'/') {
356 struct inotify_event *iev;
357 size_t real_sizeof_iev =
sizeof(*iev) +
FILENAME_MAX + 1;
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");
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
451#elif defined(HAVE_KQUEUE)
452static 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)
476static 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;
533static 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);
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));
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));
702static void *notify_daemon(
void *data)
706 struct timespec sixty_seconds = { 60, 0 };
717 nanosleep(&sixty_seconds,
NULL);
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]) {
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]);
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 };
827 result = (codep[0] & 0x80) ? ~0L : 0;
828 for (i = 0; i < 4; ++i)
839 for (i = 0; i < 8; ++i)
846 const long long at1 = t1, at0 = t0;
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);
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';
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 !=
'-' &&
1137static const char *
getqzname(
const char *strp,
const int delim)
1141 while ((
c = *strp) !=
'\0' &&
c != delim)
1153static const char *
getnum(
const char *strp,
int *nump,
const int min,
const int max)
1162 num = num * 10 + (
c -
'0');
1181static const char *
getsecs(
const char *strp,
long *
const secsp)
1220static 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') {
1295static 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)
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;
1357 for (i = 1; i < rulep->
r_week; ++i) {
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;
1446 if (*
name ==
'\0' && load_result != 0)
1448 if (*
name ==
',' || *
name ==
';') {
1484 starttime =
transtime(janfirst, year, &start,
1488 if (starttime > endtime) {
1500 newfirst = janfirst;
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));
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] ||
1687 newy =
tmp->tm_year;
1688 if (t.tv_sec < sp->
ats[0])
1692 tmp->tm_year = newy;
1693 if (
tmp->tm_year != newy)
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));
1754void 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)
1789 seconds = sp->
ats[0] - t;
1795 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1808 bounds_exceeded = 1;
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"))
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) ||
1961 if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
1964 idelta = (tdays < 0) ? -1 : 1;
1983 rem += offset - corr;
2005 tmp->tm_yday = idays;
2016 if (
tmp->tm_wday < 0)
2027 for (
tmp->tm_mon = 0; idays >= ip[
tmp->tm_mon]; ++(
tmp->tm_mon))
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;
2105static 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);
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))
2279static 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)
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)
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);
2407 cur->
locale = prevlocale;
2423 locale_t prevlocale = LC_GLOBAL_LOCALE;
2431 prevlocale = uselocale(cur->
locale);
2439 prevlocale = uselocale(cur->
locale);
2454 size_t fmtlen = strlen(
tmp) + 1;
2455 char *format =
ast_calloc(1, fmtlen), *fptr = format, *newfmt;
2456 int decimals = -1, i, res;
2458 const char *prevlocale;
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);
2508defcase: *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));
Prototypes for public functions only of internal interest,.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_realloc(p, len)
A wrapper for realloc()
#define ast_calloc(num, len)
A wrapper for calloc()
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
A set of macros to manage forward-linked lists.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_LOCK(head)
Locks a list.
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define AST_LIST_TRYLOCK(head)
Locks a list, without blocking if the list is locked.
static long detzcode P((const char *codep))
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...
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 void common_startup(void)
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 int tzload(const char *name, struct state *const sp, const int doextend)
static const struct timeval WRONG
static int differ_by_repeat(const time_t t1, const time_t t0)
static const struct state * ast_tzset(const char *zone)
static struct state * sstate_alloc(void)
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *tmp, const char *zone)
Timezone-independent version of localtime_r(3).
static ast_cond_t initialization
static void * inotify_daemon(void *data)
static struct locale_entry * find_by_name(const char *name)
const char * ast_setlocale(const char *locale)
Set the thread-local representation of the current locale.
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 ...
#define SP_STACK_CHECK(sp)
static void sstate_free(struct state *p)
static int long_increment_overflow(long *number, int delta)
int ast_strftime_locale(char *buf, size_t len, const char *tmp, const struct ast_tm *tm, const char *locale)
static void add_notify(struct state *sp, const char *path)
void ast_localtime_wakeup_monitor(struct ast_test *info)
static int increment_overflow(int *number, int delta)
Simplified normalize logic courtesy Paul Eggert.
struct timeval ast_mktime(struct ast_tm *tmp, const char *zone)
Timezone-independent version of mktime(3).
static struct ast_tm * timesub(const struct timeval *timep, const long offset, const struct state *sp, struct ast_tm *tmp)
static int long_normalize_overflow(long *tensptr, int *unitsptr, const int base)
static const char * store_by_locale(locale_t prevlocale)
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...
void clean_time_zones(void)
static int tzparse(const char *name, struct state *sp, const int lastditch)
static ast_mutex_t initialization_lock
static struct locale_entry * find_by_locale(locale_t locale)
static int normalize_overflow(int *tensptr, int *unitsptr, const int base)
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 int gmtload(struct state *sp)
char * ast_strptime_locale(const char *s, const char *format, struct ast_tm *tm, const char *locale)
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)
static long detzcode(const char *const codep)
static pthread_t inotify_thread
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,...
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 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 struct ast_tm * localsub(const struct timeval *timep, const long offset, struct ast_tm *tmp, const struct state *sp)
#define MONTH_NTH_DAY_OF_WEEK
static struct ast_tm * gmtsub(const struct timeval *timep, const long offset, struct ast_tm *tmp)
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,...
static int tmcomp(const struct ast_tm *atmp, const struct ast_tm *btmp)
#define SP_STACK_INIT(sp)
static const int year_lengths[2]
static const int mon_lengths[2][MONSPERYEAR]
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 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)
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....
static time_t detzcode64(const char *const codep)
Custom localtime functions for multiple timezones.
Asterisk locking-related definitions:
#define ast_cond_wait(cond, mutex)
#define AST_PTHREADT_NULL
#define ast_cond_init(cond, attr)
#define ast_cond_timedwait(cond, mutex, time)
#define ast_mutex_init(pmutex)
#define ast_mutex_unlock(a)
#define ast_cond_broadcast(cond)
pthread_cond_t ast_cond_t
#define ast_mutex_lock(a)
#define ast_cond_signal(cond)
#define TYPE_INTEGRAL(type)
you may need to compile with DHAVE_STDINT_H typedef long int_fast64_t
#define SECSPERREPEAT_BITS
#define TYPE_SIGNED(type)
String manipulation functions.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Structure for mutex and tracking information.
struct locale_entry::@401 list
char name[TZ_STRLEN_MAX+1]
struct lsinfo lsis[TZ_MAX_LEAPS]
struct ttinfo ttis[TZ_MAX_TYPES]
unsigned char types[TZ_MAX_TIMES]
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, sizeof gmt),(2 *(MY_TZNAME_MAX+1)))]
#define ast_test_status_update(a, b, c...)
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define ast_pthread_create_background(a, b, c, d)