add aarch64/bits/mman.h with PROT_BTI from linux v5.8
[musl] / src / time / __tz.c
index ffe8d40..09a6317 100644 (file)
@@ -3,7 +3,15 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/mman.h>
 #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,7 +23,7 @@ weak_alias(__tzname, tzname);
 
 static char std_name[TZNAME_MAX+1];
 static char dst_name[TZNAME_MAX+1];
-const char __gmt[] = "GMT";
+const char __utc[] = "UTC";
 
 static int dst_off;
 static int r0[5], r1[5];
@@ -27,7 +35,8 @@ static char old_tz_buf[32];
 static char *old_tz = old_tz_buf;
 static size_t old_tz_size = sizeof old_tz_buf;
 
-static volatile int lock[2];
+static volatile int lock[1];
+volatile int *const __timezone_lockptr = lock;
 
 static int getint(const char **p)
 {
@@ -84,15 +93,15 @@ static void getname(char *d, const char **p)
        int i;
        if (**p == '<') {
                ++*p;
-               for (i=0; (*p)[i]!='>' && i<TZNAME_MAX; i++)
-                       d[i] = (*p)[i];
-               ++*p;
+               for (i=0; (*p)[i] && (*p)[i]!='>'; i++)
+                       if (i<TZNAME_MAX) d[i] = (*p)[i];
+               if ((*p)[i]) ++*p;
        } else {
-               for (i=0; ((*p)[i]|32)-'a'<26U && i<TZNAME_MAX; i++)
-                       d[i] = (*p)[i];
+               for (i=0; ((*p)[i]|32)-'a'<26U; i++)
+                       if (i<TZNAME_MAX) d[i] = (*p)[i];
        }
        *p += i;
-       d[i] = 0;
+       d[i<TZNAME_MAX?i:TZNAME_MAX] = 0;
 }
 
 #define VEC(...) ((const unsigned char[]){__VA_ARGS__})
@@ -113,8 +122,6 @@ static size_t zi_dotprod(const unsigned char *z, const unsigned char *v, size_t
        return y;
 }
 
-int __munmap(void *, size_t);
-
 static void do_tzset()
 {
        char buf[NAME_MAX+25], *pathname=buf+24;
@@ -126,17 +133,19 @@ static void do_tzset()
 
        s = getenv("TZ");
        if (!s) s = "/etc/localtime";
-       if (!*s) s = __gmt;
+       if (!*s) s = __utc;
 
        if (old_tz && !strcmp(s, old_tz)) return;
 
+       for (i=0; i<5; i++) r0[i] = r1[i] = 0;
+
        if (zi) __munmap((void *)zi, map_size);
 
        /* Cache the old value of TZ to check if it has changed. Avoid
         * free so as not to pull it into static programs. Growth
         * strategy makes it so free would have minimal benefit anyway. */
        i = strlen(s);
-       if (i > PATH_MAX+1) s = __gmt, i = 3;
+       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;
@@ -165,18 +174,18 @@ static void do_tzset()
                                }
                        }
                }
-               if (!map) s = __gmt;
+               if (!map) s = __utc;
        }
        if (map && (map_size < 44 || memcmp(map, "TZif", 4))) {
                __munmap((void *)map, map_size);
                map = 0;
-               s = __gmt;
+               s = __utc;
        }
 
        zi = map;
        if (map) {
                int scale = 2;
-               if (sizeof(time_t) > 4 && map[4]=='2') {
+               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++;
@@ -194,7 +203,6 @@ static void do_tzset()
                        const unsigned char *p;
                        __tzname[0] = __tzname[1] = 0;
                        __daylight = __timezone = dst_off = 0;
-                       for (i=0; i<5; i++) r0[i] = r1[i] = 0;
                        for (p=types; p<abbrevs; p+=6) {
                                if (!p[4] && !__tzname[0]) {
                                        __tzname[0] = (char *)abbrevs + p[5];
@@ -207,7 +215,7 @@ static void do_tzset()
                                }
                        }
                        if (!__tzname[0]) __tzname[0] = __tzname[1];
-                       if (!__tzname[0]) __tzname[0] = (char *)__gmt;
+                       if (!__tzname[0]) __tzname[0] = (char *)__utc;
                        if (!__daylight) {
                                __tzname[1] = __tzname[0];
                                dst_off = __timezone;
@@ -216,7 +224,7 @@ static void do_tzset()
                }
        }
 
-       if (!s) s = __gmt;
+       if (!s) s = __utc;
        getname(std_name, &s);
        __tzname[0] = std_name;
        __timezone = getoff(&s);
@@ -230,7 +238,7 @@ static void do_tzset()
                        dst_off = __timezone - 3600;
        } else {
                __daylight = 0;
-               dst_off = 0;
+               dst_off = __timezone;
        }
 
        if (*s == ',') s++, getrule(&s, r0);
@@ -399,7 +407,7 @@ dst:
        UNLOCK(lock);
 }
 
-void __tzset()
+static void __tzset()
 {
        LOCK(lock);
        do_tzset();
@@ -413,7 +421,7 @@ const char *__tm_to_tzname(const struct tm *tm)
        const void *p = tm->__tm_zone;
        LOCK(lock);
        do_tzset();
-       if (p != __gmt && p != __tzname[0] && p != __tzname[1] &&
+       if (p != __utc && p != __tzname[0] && p != __tzname[1] &&
            (!zi || (uintptr_t)p-(uintptr_t)abbrevs >= abbrevs_end - abbrevs))
                p = "";
        UNLOCK(lock);