61 #include <sys/inotify.h>
62 #elif defined(HAVE_KQUEUE)
63 #include <sys/types.h>
65 #include <sys/event.h>
84 static char __attribute__((unused))
elsieid[] = "@(
#)localtime.c 8.5";
88 #ifndef TZ_ABBR_MAX_LEN
89 #define TZ_ABBR_MAX_LEN 16
92 #ifndef TZ_ABBR_CHAR_SET
93 #define TZ_ABBR_CHAR_SET \
94 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
97 #ifndef TZ_ABBR_ERR_CHAR
98 #define TZ_ABBR_ERR_CHAR '_'
106 #define OPEN_MODE (O_RDONLY | O_BINARY)
109 #define OPEN_MODE O_RDONLY
112 static const char gmt[] =
"GMT";
113 static const struct timeval
WRONG = { 0, 0 };
115 #ifdef TEST_FRAMEWORK
117 static struct ast_test *test = NULL;
129 #ifndef TZDEFRULESTRING
130 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
148 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
151 #define MY_TZNAME_MAX TZNAME_MAX
154 #define MY_TZNAME_MAX 255
156 #ifndef TZ_STRLEN_MAX
157 #define TZ_STRLEN_MAX 255
177 #elif defined(HAVE_KQUEUE)
179 # ifdef HAVE_O_SYMLINK
205 #define DAY_OF_YEAR 1
206 #define MONTH_NTH_DAY_OF_WEEK 2
212 static long detzcode P((
const char * codep));
215 static const char *
getzname P((
const char * strp));
216 static const char *
getqzname P((
const char * strp,
const int delim));
217 static const char *
getnum P((
const char * strp,
int * nump,
int min,
219 static const char *
getsecs P((
const char * strp,
long * secsp));
220 static const char *
getoffset P((
const char * strp,
long * offsetp));
221 static const char *
getrule P((
const char * strp,
struct rule * rulep));
223 static struct ast_tm *
gmtsub P((
const struct timeval * timep,
long offset,
225 static struct ast_tm *
localsub P((
const struct timeval * timep,
long offset,
231 int * unitsptr,
const int base));
235 struct ast_tm * (*funcp)
P((
const struct timeval *,
237 long offset,
const struct state *sp));
239 struct ast_tm * (*funcp)
P((
const struct timeval *,
241 long offset,
int * okayp,
const struct state *sp));
243 struct ast_tm * (*funcp) (
const struct timeval *,
245 long offset,
int * okayp,
int do_norm_secs,
const struct state *sp));
246 static struct ast_tm *
timesub P((
const struct timeval * timep,
long offset,
249 const struct ast_tm * btmp));
250 static time_t
transtime P((time_t janfirst,
int year,
251 const struct rule * rulep,
long offset));
258 #ifdef HAVE_NEWLOCALE
262 #ifndef TZ_STRLEN_MAX
263 #define TZ_STRLEN_MAX 255
275 struct inotify_event iev;
281 inotify_fd = inotify_init();
287 if (inotify_fd < 0) {
295 if ((res = read(inotify_fd, &buf,
sizeof(buf))) <
sizeof(buf.iev) && res > 0) {
297 ast_log(
LOG_ERROR,
"Inotify read less than a full event (%zd < %zu)?!!\n", res,
sizeof(buf.iev));
299 }
else if (res < 0) {
313 if (cur->
wd[0] == buf.iev.wd || cur->
wd[1] == buf.iev.wd) {
338 fprintf(stderr,
"Unable to start notification thread\n");
345 if (inotify_fd > -1) {
347 if (readlink(path, fullpath,
sizeof(fullpath) - 1) != -1) {
349 sp->
wd[1] = inotify_add_watch(inotify_fd, fullpath, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE );
354 sp->
wd[0] = inotify_add_watch(inotify_fd, path, IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_CLOSE_WRITE
355 #ifdef IN_DONT_FOLLOW
361 #elif defined(HAVE_KQUEUE)
362 static int queue_fd = -1;
364 static void *kqueue_daemon(
void *data)
368 struct timespec no_wait = { 0, 1 };
371 if ((queue_fd = kqueue()) < 0) {
374 fprintf(stderr,
"Unable to initialize kqueue(): %s\n", strerror(
errno));
387 if (kevent(queue_fd, NULL, 0, &kev, 1, NULL) < 0) {
412 EV_SET(&kev, sp->fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
413 kevent(queue_fd, &kev, 1, NULL, 0, &no_wait);
416 #ifdef HAVE_O_SYMLINK
419 EV_SET(&kev, sp->fds, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
420 kevent(queue_fd, &kev, 1, NULL, 0, &no_wait);
426 EV_SET(&kev, dirfd(sp->dir), EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
427 kevent(queue_fd, &kev, 1, NULL, 0, &no_wait);
443 struct timespec no_wait = { 0, 1 };
444 char watchdir[PATH_MAX + 1] =
"";
462 #ifdef HAVE_O_SYMLINK
463 if (readlink(path, watchdir,
sizeof(watchdir) - 1) != -1 && (sp->fds = open(path, O_RDONLY | O_SYMLINK
464 # ifdef HAVE_O_EVTONLY
468 EV_SET(&kev, sp->fds, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, NOTE_WRITE | NOTE_EXTEND | NOTE_DELETE | NOTE_REVOKE | NOTE_ATTRIB, 0, sp);
469 if (kevent(queue_fd, &kev, 1, NULL, 0, &no_wait) < 0 &&
errno != 0) {
474 fprintf(stderr,
"Unable to watch '%s': %s\n", path, strerror(
errno));
480 if (readlink(path, watchdir,
sizeof(watchdir) - 1) != -1) {
486 if ((slash = strrchr(watchdir,
'/'))) {
489 if (!(sp->dir = opendir(watchdir))) {
490 fprintf(stderr,
"Unable to watch directory with symlink '%s': %s\n", path, strerror(
errno));
503 EV_SET(&kev, dirfd(sp->dir), EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
504 NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_REVOKE | NOTE_ATTRIB, 0, sp);
505 if (kevent(queue_fd, &kev, 1, NULL, 0, &no_wait) < 0 &&
errno != 0) {
506 fprintf(stderr,
"Unable to watch '%s': %s\n", watchdir, strerror(
errno));
515 if ((sp->fd = open(path, O_RDONLY
516 # ifdef HAVE_O_EVTONLY
520 fprintf(stderr,
"Unable to watch '%s' for changes: %s\n", path, strerror(
errno));
524 EV_SET(&kev, sp->fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, NOTE_WRITE | NOTE_EXTEND | NOTE_DELETE | NOTE_REVOKE | NOTE_ATTRIB, 0, sp);
525 if (kevent(queue_fd, &kev, 1, NULL, 0, &no_wait) < 0 &&
errno != 0) {
530 fprintf(stderr,
"Unable to watch '%s': %s\n", path, strerror(
errno));
536 static void *notify_daemon(
void *data)
540 struct timespec sixty_seconds = { 60, 0 };
549 nanosleep(&sixty_seconds, NULL);
556 if (name[0] !=
'/') {
557 (void) strcpy(fullname,
TZDIR "/");
558 (void) strcat(fullname, name);
563 if (st.st_mtime > cur->mtime[0] || lst.st_mtime > cur->mtime[1]) {
564 #ifdef TEST_FRAMEWORK
566 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]);
570 ast_log(
LOG_NOTICE,
"Removing cached TZ entry '%s' because underlying file changed.\n", name);
601 sp->mtime[0] = st.st_mtime;
603 sp->mtime[1] = st.st_mtime;
611 #ifdef TEST_FRAMEWORK
614 pthread_kill(inotify_thread, SIGURG);
616 #ifdef TEST_FRAMEWORK
636 result = (codep[0] & 0x80) ? ~0L : 0;
637 for (i = 0; i < 4; ++i)
638 result = (result << 8) | (codep[i] & 0xff);
648 for (i = 0; i < 8; ++i)
649 result = result * 256 + (codep[i] & 0xff);
655 const long long at1 =
t1, at0 = t0;
662 static int tzload(
const char *name,
struct state *
const sp,
const int doextend)
671 char buf[2 *
sizeof(
struct tzhead) +
676 if (name == NULL && (name =
TZDEFAULT) == NULL)
691 doaccess = name[0] ==
'/';
693 if ((p =
TZDIR) == NULL)
695 if ((strlen(p) + strlen(name) + 1) >=
sizeof fullname)
697 (void) strcpy(fullname, p);
698 (void) strcat(fullname,
"/");
699 (void) strcat(fullname, name);
703 if (strchr(name,
'.') != NULL)
707 if (doaccess && access(name, R_OK) != 0)
720 nread = read(fid, u.buf,
sizeof u.buf);
721 if (close(fid) < 0 || nread <= 0)
723 for (stored = 4; stored <= 8; stored *= 2) {
727 ttisstdcnt = (int)
detzcode(u.tzhead.tzh_ttisstdcnt);
728 ttisgmtcnt = (int)
detzcode(u.tzhead.tzh_ttisgmtcnt);
733 p = u.tzhead.tzh_charcnt +
sizeof u.tzhead.tzh_charcnt;
738 (ttisstdcnt != sp->
typecnt && ttisstdcnt != 0) ||
739 (ttisgmtcnt != sp->
typecnt && ttisgmtcnt != 0))
741 if (nread - (p - u.buf) <
750 for (i = 0; i < sp->
timecnt; ++i) {
751 sp->
ats[i] = (stored == 4) ?
755 for (i = 0; i < sp->
timecnt; ++i) {
756 sp->
types[i] = (
unsigned char) *p++;
760 for (i = 0; i < sp->
typecnt; ++i) {
763 ttisp = &sp->
ttis[i];
766 ttisp->
tt_isdst = (
unsigned char) *p++;
774 for (i = 0; i < sp->
charcnt; ++i)
780 lsisp = &sp->
lsis[i];
787 for (i = 0; i < sp->
typecnt; ++i) {
790 ttisp = &sp->
ttis[i];
800 for (i = 0; i < sp->
typecnt; ++i) {
803 ttisp = &sp->
ttis[i];
818 for (i = 0; i < sp->
timecnt - 2; ++i)
819 if (sp->
ats[i] > sp->
ats[i + 1]) {
832 for (j = 0; j + i < sp->
timecnt; ++j) {
833 sp->
ats[j] = sp->
ats[j + i];
843 if (u.tzhead.tzh_version[0] ==
'\0')
846 for (i = 0; i < nread; ++i)
854 if (doextend && nread > 2 &&
855 u.buf[0] ==
'\n' && u.buf[nread - 1] ==
'\n' &&
860 u.buf[nread - 1] =
'\0';
862 if (result == 0 && ts.
typecnt == 2 &&
864 for (i = 0; i < 2; ++i)
901 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
902 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
919 while ((c = *strp) !=
'\0' && !
is_digit(c) && c !=
',' && c !=
'-' &&
934 static const char *
getqzname(
const char *strp,
const int delim)
938 while ((c = *strp) !=
'\0' && c != delim)
950 static const char *
getnum(
const char *strp,
int *nump,
const int min,
const int max)
955 if (strp == NULL || !
is_digit(c = *strp))
959 num = num * 10 + (c -
'0');
978 static const char *
getsecs(
const char *strp,
long *
const secsp)
1001 strp =
getnum(strp, &num, 0, SECSPERMIN);
1017 static const char *
getoffset(
const char *strp,
long *offsetp)
1024 }
else if (*strp ==
'+')
1026 strp =
getsecs(strp, offsetp);
1030 *offsetp = -*offsetp;
1050 }
else if (*strp ==
'M') {
1092 static time_t
transtime(
const time_t janfirst,
const int year,
const struct rule *rulep,
const long offset)
1097 int d, m1, yy0, yy1, yy2, dow;
1112 if (leapyear && rulep->
r_day >= 60)
1130 for (i = 0; i < rulep->
r_mon - 1; ++i)
1131 value += mon_lengths[leapyear][i] *
SECSPERDAY;
1137 m1 = (rulep->
r_mon + 9) % 12 + 1;
1138 yy0 = (rulep->
r_mon <= 2) ? (year - 1) : year;
1141 dow = ((26 * m1 - 2) / 10 +
1142 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1151 d = rulep->
r_day - dow;
1154 for (i = 1; i < rulep->
r_week; ++i) {
1156 mon_lengths[leapyear][rulep->
r_mon - 1])
1174 return value + rulep->
r_time + offset;
1182 static int tzparse(
const char *name,
struct state *sp,
const int lastditch)
1184 const char * stdname;
1185 const char * dstname;
1191 unsigned char * typep;
1198 stdlen = strlen(name);
1200 if (stdlen >=
sizeof sp->
chars)
1201 stdlen = (
sizeof sp->
chars) - 1;
1210 stdlen = name - stdname;
1214 stdlen = name - stdname;
1223 if (load_result != 0)
1225 if (*name !=
'\0') {
1231 dstlen = name - dstname;
1236 dstlen = name - dstname;
1238 if (*name !=
'\0' && *name !=
',' && *name !=
';') {
1243 if (*name ==
'\0' && load_result != 0)
1245 if (*name ==
',' || *name ==
';') {
1254 if ((name =
getrule(name, &start)) == NULL)
1258 if ((name =
getrule(name, &end)) == NULL)
1281 starttime =
transtime(janfirst, year, &start,
1283 endtime =
transtime(janfirst, year, &end,
1285 if (starttime > endtime) {
1297 newfirst = janfirst;
1298 newfirst += year_lengths[
isleap(year)] *
1300 if (newfirst <= janfirst)
1302 janfirst = newfirst;
1305 long theirstdoffset;
1306 long theirdstoffset;
1318 for (i = 0; i < sp->
timecnt; ++i) {
1327 for (i = 0; i < sp->
timecnt; ++i) {
1339 theiroffset = theirstdoffset;
1344 for (i = 0; i < sp->
timecnt; ++i) {
1365 sp->
ats[i] += dstoffset -
1368 sp->
ats[i] += stdoffset -
1374 theirdstoffset = theiroffset;
1375 else theirstdoffset = theiroffset;
1403 (void) strncpy(cp, stdname, stdlen);
1407 (void) strncpy(cp, dstname, dstlen);
1408 *(cp + dstlen) =
'\0';
1438 zone = getenv(
"TZ");
1443 zone =
"/etc/localtime";
1449 if (!strcmp(sp->
name, zone)) {
1481 const struct ttinfo * ttisp;
1485 memcpy(&t, timep,
sizeof(t));
1488 return gmtsub(timep, offset, tmp);
1489 if ((sp->
goback && t.tv_sec < sp->
ats[0]) ||
1491 struct timeval newt = t;
1496 if (t.tv_sec < sp->
ats[0])
1497 seconds = sp->
ats[0] - t.tv_sec;
1498 else seconds = t.tv_sec - sp->
ats[sp->
timecnt - 1];
1503 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1508 if (t.tv_sec < sp->
ats[0])
1509 newt.tv_sec += seconds;
1510 else newt.tv_sec -= seconds;
1511 if (newt.tv_sec < sp->
ats[0] ||
1514 result =
localsub(&newt, offset, tmp, sp);
1515 if (result == tmp) {
1519 if (t.tv_sec < sp->
ats[0])
1529 if (sp->
timecnt == 0 || t.tv_sec < sp->
ats[0]) {
1542 int mid = (lo + hi) >> 1;
1544 if (t.tv_sec < sp->
ats[mid])
1549 i = (int) sp->
types[lo - 1];
1551 ttisp = &sp->
ttis[i];
1566 tmp->
tm_usec = timep->tv_usec;
1573 memset(tmp, 0,
sizeof(*tmp));
1574 return sp ?
localsub(timep, 0L, tmp, sp) : NULL;
1585 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)
1588 int transition1 = -1;
1589 int transition2 = -1;
1591 int bounds_exceeded = 0;
1593 const struct state *sp;
1595 if (NULL == dst_enabled)
1599 if (NULL == dst_start || NULL == dst_end || NULL == gmt_off)
1620 seconds = sp->
ats[0] - t;
1626 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1636 if (t < sp->ats[0] || t > sp->
ats[sp->
timecnt - 1])
1639 bounds_exceeded = 1;
1642 if (sp->
timecnt == 0 || t < sp->ats[0]) {
1656 for (i = 1; i < sp->
timecnt; ++i) {
1657 if (t < sp->ats[i]) {
1658 transition1 = sp->
types[i - 1];
1659 transition2 = sp->
types[i];
1665 if (i >= sp->
timecnt || 0 > transition1 || 0 > transition2 ||
1677 if (!bounds_exceeded) {
1681 *dst_start = sp->
ats[i];
1682 *dst_end = sp->
ats[i -1];
1684 *dst_start = sp->
ats[i -1];
1685 *dst_end = sp->
ats[i];
1703 if (!strcmp(sp->
name,
"UTC"))
1715 result =
timesub(timep, offset, sp, tmp);
1725 tmp->TM_ZONE = sp->
chars;
1737 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1743 const struct lsinfo * lp;
1757 i = (sp == NULL) ? 0 : sp->
leapcnt;
1760 if (timep->tv_sec >= lp->
ls_trans) {
1761 if (timep->tv_sec == lp->
ls_trans) {
1762 hit = ((i == 0 && lp->
ls_corr > 0) ||
1781 while (tdays < 0 || tdays >= year_lengths[
isleap(y)]) {
1789 if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
1792 idelta = (tdays < 0) ? -1 : 1;
1803 seconds = tdays * SECSPERDAY + 0.5;
1811 rem += offset - corr;
1816 while (rem >= SECSPERDAY) {
1823 idays += year_lengths[
isleap(y)];
1825 while (idays >= year_lengths[
isleap(y)]) {
1826 idays -= year_lengths[
isleap(y)];
1854 ip = mon_lengths[
isleap(y)];
1856 idays -= ip[tmp->
tm_mon];
1857 tmp->
tm_mday = (int) (idays + 1);
1860 tmp->TM_GMTOFF = offset;
1862 tmp->
tm_usec = timep->tv_usec;
1885 return (*number < number0) != (delta < 0);
1894 return (*number < number0) != (delta < 0);
1901 tensdelta = (*unitsptr >= 0) ?
1902 (*unitsptr / base) :
1903 (-1 - (-1 - *unitsptr) / base);
1904 *unitsptr -= tensdelta * base;
1912 tensdelta = (*unitsptr >= 0) ?
1913 (*unitsptr / base) :
1914 (-1 - (-1 - *unitsptr) / base);
1915 *unitsptr -= tensdelta * base;
1933 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)
1942 struct timeval newt = { 0, 0 };
1943 struct timeval t = { 0, 0 };
1944 struct ast_tm yourtm, mytm;
1969 li = y + (1 < yourtm.
tm_mon);
1973 li = y + (1 < yourtm.
tm_mon);
2007 saved_seconds = yourtm.
tm_sec;
2010 saved_seconds = yourtm.
tm_sec;
2020 if (
sizeof(time_t) >
sizeof(
float))
2021 hi = (time_t) DBL_MAX;
2022 else hi = (time_t) FLT_MAX;
2026 for (i = 0; i < (int)
TYPE_BIT(time_t) - 1; ++i)
2031 t.tv_sec = lo / 2 + hi / 2;
2034 else if (t.tv_sec > hi)
2036 if ((*funcp)(&t, offset, &mytm, sp) == NULL) {
2042 dir = (t.tv_sec > 0) ? 1 : -1;
2043 }
else dir =
tmcomp(&mytm, &yourtm);
2045 if (t.tv_sec == lo) {
2050 }
else if (t.tv_sec == hi) {
2074 for (i = sp->
typecnt - 1; i >= 0; --i) {
2077 for (j = sp->
typecnt - 1; j >= 0; --j) {
2082 if ((*funcp)(&newt, offset, &mytm, sp) == NULL)
2084 if (
tmcomp(&mytm, &yourtm) != 0)
2086 if (mytm.tm_isdst != yourtm.
tm_isdst)
2098 newt.tv_sec = t.tv_sec + saved_seconds;
2099 if ((newt.tv_sec < t.tv_sec) != (saved_seconds < 0))
2101 t.tv_sec = newt.tv_sec;
2102 if ((*funcp)(&t, offset, tmp, sp))
2107 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)
2117 return *okayp ? t :
time2sub(tmp, funcp, offset, okayp,
TRUE, sp);
2120 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)
2124 int sameind, otherind;
2131 if (tmp->tm_isdst > 1)
2133 t =
time2(tmp, funcp, offset, &okay, sp);
2140 if (tmp->tm_isdst < 0)
2144 if (okay || tmp->tm_isdst < 0)
2155 for (i = 0; i < sp->
typecnt; ++i)
2158 for (i = sp->
timecnt - 1; i >= 0; --i)
2159 if (!seen[sp->
types[i]]) {
2161 types[nseen++] = sp->
types[i];
2163 for (sameind = 0; sameind < nseen; ++sameind) {
2164 samei = types[sameind];
2167 for (otherind = 0; otherind < nseen; ++otherind) {
2168 otheri = types[otherind];
2173 tmp->tm_isdst = !tmp->tm_isdst;
2174 t =
time2(tmp, funcp, offset, &okay, sp);
2179 tmp->tm_isdst = !tmp->tm_isdst;
2187 const struct state *sp;
2193 #ifdef HAVE_NEWLOCALE
2196 struct locale_entry *cur;
2198 if (locale == cur->
locale) {
2207 struct locale_entry *cur;
2209 if (strcmp(name, cur->
name) == 0) {
2218 struct locale_entry *cur;
2219 if (prevlocale == LC_GLOBAL_LOCALE) {
2230 for (x = 0; x < 10000; x++) {
2232 snprintf(name,
sizeof(name),
"%04d", x);
2234 if ((cur =
ast_calloc(1,
sizeof(*cur) + strlen(name) + 1))) {
2235 cur->
locale = prevlocale;
2236 strcpy(cur->
name, name);
2243 return cur ? cur->
name : NULL;
2250 struct locale_entry *cur;
2251 locale_t prevlocale = LC_GLOBAL_LOCALE;
2253 if (locale == NULL) {
2259 prevlocale = uselocale(cur->
locale);
2263 if ((cur =
ast_calloc(1,
sizeof(*cur) + strlen(locale) + 1))) {
2264 cur->
locale = newlocale(LC_ALL_MASK, locale, NULL);
2265 strcpy(cur->
name, locale);
2267 prevlocale = uselocale(cur->
locale);
2282 size_t fmtlen = strlen(tmp) + 1;
2284 int decimals = -1, i, res;
2286 const char *prevlocale;
2291 for (; *tmp; tmp++) {
2300 if (tmp[2] !=
'q') {
2303 decimals = tmp[1] -
'0';
2307 if (decimals == -1) {
2317 fptr = fptr - format + newfmt;
2322 for (i = 6, fraction = tm->
tm_usec; i > decimals; i--) {
2325 fptr += sprintf(fptr,
"%0*ld", decimals, fraction);
2335 defcase: *fptr++ = *tmp;
2343 res = (int)strftime(buf, len, format, (
struct tm *)tm);
2358 struct tm tm2 = { 0, };
2360 const char *prevlocale;
2363 res = strptime(s, format, &tm2);
2369 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)
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.
static struct state * ast_tzset(const char *zone)
String manipulation functions.
static ast_cond_t initialization
char name[TZ_STRLEN_MAX+1]
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
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 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)
#define ast_mutex_lock(a)
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define ast_cond_signal(cond)
char * ast_strptime_locale(const char *s, const char *format, struct ast_tm *tm, const char *locale)
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)
pthread_cond_t ast_cond_t
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 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
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#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.
int ast_strftime_locale(char *buf, size_t len, const char *format, const struct ast_tm *tm, const char *locale)
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.
#define SECSPERREPEAT_BITS
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 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.
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 int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
#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.
const char * ast_setlocale(const char *locale)
Set the thread-local representation of the current locale.
#define TYPE_INTEGRAL(type)
Prototypes for public functions only of internal interest,.
#define MONTH_NTH_DAY_OF_WEEK
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 strfti...
static int differ_by_repeat(const time_t t1, const time_t t0)
if(yyss+yystacksize-1<=yyssp)
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...
void clean_time_zones(void)
static int tmcomp(const struct ast_tm *atmp, const struct ast_tm *btmp)
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define ast_realloc(a, b)
static const int year_lengths[2]
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 timeval WRONG
you may need to compile with DHAVE_STDINT_H typedef long int_fast64_t
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)
static int long_increment_overflow(long *number, int delta)
unsigned char types[TZ_MAX_TIMES]
static pthread_t inotify_thread
static const char * store_by_locale(locale_t prevlocale)
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 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)
#define TYPE_SIGNED(type)
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
struct ttinfo ttis[TZ_MAX_TYPES]
void ast_localtime_wakeup_monitor(struct ast_test *info)
Structure for mutex and tracking information.
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
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)