X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=inline;f=src%2Ftime%2F__tz.c;h=3e2fcdcbb6a48d000497e2bd36234a2e9c88f0cf;hb=937822abb6ac48880939be3c60e6b57bddf62cf6;hp=a76a7b4865149305d693aababac85a6c64ec1df1;hpb=1cc81f5cb0df2b66a795ff0c26d7bbc4d16e13c6;p=musl diff --git a/src/time/__tz.c b/src/time/__tz.c index a76a7b48..3e2fcdcb 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -3,7 +3,16 @@ #include #include #include +#include +#include #include "libc.h" +#include "lock.h" +#include "fork_impl.h" + +#define malloc __libc_malloc +#define calloc undef +#define realloc undef +#define free undef long __timezone = 0; int __daylight = 0; @@ -15,18 +24,20 @@ weak_alias(__tzname, tzname); static char std_name[TZNAME_MAX+1]; static char dst_name[TZNAME_MAX+1]; +const char __utc[] = "UTC"; static int dst_off; static int r0[5], r1[5]; -static const unsigned char *zi, *trans, *index, *types, *abbrevs; +static const unsigned char *zi, *trans, *index, *types, *abbrevs, *abbrevs_end; static size_t map_size; static char old_tz_buf[32]; static char *old_tz = old_tz_buf; static size_t old_tz_size = sizeof old_tz_buf; -static int lock[2]; +static volatile int lock[1]; +volatile int *const __timezone_lockptr = lock; static int getint(const char **p) { @@ -35,19 +46,16 @@ static int getint(const char **p) return x; } -static int getsigned(const char **p) +static int getoff(const char **p) { + int neg = 0; if (**p == '-') { ++*p; - return -getint(p); + neg = 1; + } else if (**p == '+') { + ++*p; } - if (**p == '+') ++*p; - return getint(p); -} - -static int getoff(const char **p) -{ - int off = 3600*getsigned(p); + int off = 3600*getint(p); if (**p == ':') { ++*p; off += 60*getint(p); @@ -56,7 +64,7 @@ static int getoff(const char **p) off += getint(p); } } - return off; + return neg ? -off : off; } static void getrule(const char **p, int rule[5]) @@ -86,15 +94,15 @@ static void getname(char *d, const char **p) int i; if (**p == '<') { ++*p; - for (i=0; **p!='>' && i PATH_MAX+1) s = "", i = 0; + if (i > PATH_MAX+1) s = __utc, i = 3; if (i >= old_tz_size) { old_tz_size *= 2; if (i >= old_tz_size) old_tz_size = i+1; @@ -146,37 +155,51 @@ static void do_tzset() } if (old_tz) memcpy(old_tz, s, i+1); - if (*s == ':') s++; + int posix_form = 0; + if (*s != ':') { + p = s; + char dummy_name[TZNAME_MAX+1]; + getname(dummy_name, &p); + if (p!=s && (*p == '+' || *p == '-' || isdigit(*p) + || !strcmp(dummy_name, "UTC") + || !strcmp(dummy_name, "GMT"))) + posix_form = 1; + } /* Non-suid can use an absolute tzfile pathname or a relative * pathame beginning with "."; in secure mode, only the * standard path will be searched. */ - if (*s == '/' || *s == '.') { - if (!libc.secure) map = __map_file(s, &map_size); - } else { - for (i=0; s[i] && s[i]!=','; i++) { - if (s[i]=='/') { - size_t l = strlen(s); - if (l > NAME_MAX || strchr(s, '.')) - break; + if (!posix_form) { + if (*s == ':') s++; + if (*s == '/' || *s == '.') { + if (!libc.secure || !strcmp(s, "/etc/localtime")) + map = __map_file(s, &map_size); + } else { + size_t l = strlen(s); + if (l <= NAME_MAX && !strchr(s, '.')) { memcpy(pathname, s, l+1); pathname[l] = 0; - for (try=search; !map && *try; try+=l) { + for (try=search; !map && *try; try+=l+1) { l = strlen(try); memcpy(pathname-l, try, l); map = __map_file(pathname-l, &map_size); } - break; } } + if (!map) s = __utc; + } + if (map && (map_size < 44 || memcmp(map, "TZif", 4))) { + __munmap((void *)map, map_size); + map = 0; + s = __utc; } zi = map; if (map) { int scale = 2; - if (sizeof(time_t) > 4 && map[4]=='2') { - size_t skip = zi_dotprod(zi, VEC(1,1,8,5,6,1), 6); - trans = zi+skip+44+20; + if (map[4]!='1') { + size_t skip = zi_dotprod(zi+20, VEC(1,1,8,5,6,1), 6); + trans = zi+skip+44+44; scale++; } else { trans = zi+44; @@ -184,15 +207,36 @@ static void do_tzset() index = trans + (zi_read32(trans-12) << scale); types = index + zi_read32(trans-12); abbrevs = types + 6*zi_read32(trans-8); + abbrevs_end = abbrevs + zi_read32(trans-4); if (zi[map_size-1] == '\n') { for (s = (const char *)zi+map_size-2; *s!='\n'; s--); s++; } else { - s = 0; + const unsigned char *p; + __tzname[0] = __tzname[1] = 0; + __daylight = __timezone = dst_off = 0; + for (p=types; p= t0 && t < t1) goto dst; goto std; } else { - if (!local) { - t1 += __timezone; - t0 += dst_off; - } if (t >= t1 && t < t0) goto std; goto dst; } std: *isdst = 0; - *offset = __timezone; - if (oppoff) *oppoff = dst_off; + *offset = -__timezone; + if (oppoff) *oppoff = -dst_off; *zonename = __tzname[0]; UNLOCK(lock); return; dst: *isdst = 1; - *offset = dst_off; - if (oppoff) *oppoff = __timezone; + *offset = -dst_off; + if (oppoff) *oppoff = -__timezone; *zonename = __tzname[1]; UNLOCK(lock); } -void __tzset() +static void __tzset() { LOCK(lock); do_tzset(); @@ -387,3 +427,15 @@ void __tzset() } weak_alias(__tzset, tzset); + +const char *__tm_to_tzname(const struct tm *tm) +{ + const void *p = tm->__tm_zone; + LOCK(lock); + do_tzset(); + if (p != __utc && p != __tzname[0] && p != __tzname[1] && + (!zi || (uintptr_t)p-(uintptr_t)abbrevs >= abbrevs_end - abbrevs)) + p = ""; + UNLOCK(lock); + return p; +}