diff options
Diffstat (limited to 'src/time')
-rw-r--r-- | src/time/__map_file.c | 5 | ||||
-rw-r--r-- | src/time/__tz.c | 49 | ||||
-rw-r--r-- | src/time/__year_to_secs.c | 4 | ||||
-rw-r--r-- | src/time/clock_getcpuclockid.c | 1 | ||||
-rw-r--r-- | src/time/clock_gettime.c | 7 | ||||
-rw-r--r-- | src/time/strftime.c | 8 | ||||
-rw-r--r-- | src/time/strptime.c | 66 | ||||
-rw-r--r-- | src/time/timer_create.c | 16 |
8 files changed, 129 insertions, 27 deletions
diff --git a/src/time/__map_file.c b/src/time/__map_file.c index d3cefa82..c2b29fe8 100644 --- a/src/time/__map_file.c +++ b/src/time/__map_file.c @@ -2,15 +2,14 @@ #include <fcntl.h> #include <sys/stat.h> #include "syscall.h" -#include "kstat.h" const char unsigned *__map_file(const char *pathname, size_t *size) { - struct kstat st; + struct stat st; const unsigned char *map = MAP_FAILED; int fd = sys_open(pathname, O_RDONLY|O_CLOEXEC|O_NONBLOCK); if (fd < 0) return 0; - if (!syscall(SYS_fstat, fd, &st)) { + if (!__fstat(fd, &st)) { map = __mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); *size = st.st_size; } diff --git a/src/time/__tz.c b/src/time/__tz.c index 49a7371e..c34b3eb7 100644 --- a/src/time/__tz.c +++ b/src/time/__tz.c @@ -4,8 +4,15 @@ #include <stdlib.h> #include <string.h> #include <sys/mman.h> +#include <ctype.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; @@ -30,6 +37,7 @@ static char *old_tz = old_tz_buf; static size_t old_tz_size = sizeof old_tz_buf; static volatile int lock[1]; +volatile int *const __timezone_lockptr = lock; static int getint(const char **p) { @@ -147,10 +155,21 @@ static void do_tzset() } if (old_tz) memcpy(old_tz, s, i+1); + 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 == ':' || ((p=strchr(s, '/')) && !memchr(s, ',', p-s))) { + if (!posix_form) { if (*s == ':') s++; if (*s == '/' || *s == '.') { if (!libc.secure || !strcmp(s, "/etc/localtime")) @@ -178,7 +197,7 @@ static void do_tzset() 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++; @@ -274,22 +293,20 @@ static size_t scan_trans(long long t, int local, size_t *alt) n = (index-trans)>>scale; if (a == n-1) return -1; if (a == 0) { - x = zi_read32(trans + (a<<scale)); - if (scale == 3) x = x<<32 | zi_read32(trans + (a<<scale) + 4); + x = zi_read32(trans); + if (scale == 3) x = x<<32 | zi_read32(trans + 4); else x = (int32_t)x; - if (local) off = (int32_t)zi_read32(types + 6 * index[a-1]); + /* Find the lowest non-DST type, or 0 if none. */ + size_t j = 0; + for (size_t i=abbrevs-types; i; i-=6) { + if (!types[i-6+4]) j = i-6; + } + if (local) off = (int32_t)zi_read32(types + j); + /* If t is before first transition, use the above-found type + * and the index-zero (after transition) type as the alt. */ if (t - off < (int64_t)x) { - for (a=0; a<(abbrevs-types)/6; a++) { - if (types[6*a+4] != types[4]) break; - } - if (a == (abbrevs-types)/6) a = 0; - if (types[6*a+4]) { - *alt = a; - return 0; - } else { - *alt = 0; - return a; - } + if (alt) *alt = index[0]; + return j/6; } } diff --git a/src/time/__year_to_secs.c b/src/time/__year_to_secs.c index 2824ec6d..b42f5a6d 100644 --- a/src/time/__year_to_secs.c +++ b/src/time/__year_to_secs.c @@ -10,9 +10,9 @@ long long __year_to_secs(long long year, int *is_leap) return 31536000*(y-70) + 86400*leaps; } - int cycles, centuries, leaps, rem; + int cycles, centuries, leaps, rem, dummy; - if (!is_leap) is_leap = &(int){0}; + if (!is_leap) is_leap = &dummy; cycles = (year-100) / 400; rem = (year-100) % 400; if (rem < 0) { diff --git a/src/time/clock_getcpuclockid.c b/src/time/clock_getcpuclockid.c index 8a0e2d4c..bce1e8ab 100644 --- a/src/time/clock_getcpuclockid.c +++ b/src/time/clock_getcpuclockid.c @@ -8,6 +8,7 @@ int clock_getcpuclockid(pid_t pid, clockid_t *clk) struct timespec ts; clockid_t id = (-pid-1)*8U + 2; int ret = __syscall(SYS_clock_getres, id, &ts); + if (ret == -EINVAL) ret = -ESRCH; if (ret) return -ret; *clk = id; return 0; diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c index 3e1d0975..4d2ec22f 100644 --- a/src/time/clock_gettime.c +++ b/src/time/clock_gettime.c @@ -42,6 +42,9 @@ static int cgt_init(clockid_t clk, struct timespec *ts) p = cgt_time32_wrap; } } +#ifdef VDSO_CGT_WORKAROUND + if (!__vdsosym(VDSO_CGT32_VER, VDSO_CGT32_SYM)) p = 0; +#endif #endif int (*f)(clockid_t, struct timespec *) = (int (*)(clockid_t, struct timespec *))p; @@ -80,10 +83,12 @@ int __clock_gettime(clockid_t clk, struct timespec *ts) return __syscall_ret(r); long ts32[2]; r = __syscall(SYS_clock_gettime, clk, ts32); +#ifdef SYS_gettimeofday if (r==-ENOSYS && clk==CLOCK_REALTIME) { r = __syscall(SYS_gettimeofday, ts32, 0); ts32[1] *= 1000; } +#endif if (!r) { ts->tv_sec = ts32[0]; ts->tv_nsec = ts32[1]; @@ -92,6 +97,7 @@ int __clock_gettime(clockid_t clk, struct timespec *ts) return __syscall_ret(r); #else r = __syscall(SYS_clock_gettime, clk, ts); +#ifdef SYS_gettimeofday if (r == -ENOSYS) { if (clk == CLOCK_REALTIME) { __syscall(SYS_gettimeofday, ts, 0); @@ -100,6 +106,7 @@ int __clock_gettime(clockid_t clk, struct timespec *ts) } r = -EINVAL; } +#endif return __syscall_ret(r); #endif } diff --git a/src/time/strftime.c b/src/time/strftime.c index cc53d536..c40246db 100644 --- a/src/time/strftime.c +++ b/src/time/strftime.c @@ -3,6 +3,7 @@ #include <string.h> #include <langinfo.h> #include <locale.h> +#include <ctype.h> #include <time.h> #include <limits.h> #include "locale_impl.h" @@ -233,7 +234,12 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st pad = 0; if (*f == '-' || *f == '_' || *f == '0') pad = *f++; if ((plus = (*f == '+'))) f++; - width = strtoul(f, &p, 10); + if (isdigit(*f)) { + width = strtoul(f, &p, 10); + } else { + width = 0; + p = (void *)f; + } if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') { if (!width && p!=f) width = 1; } else { diff --git a/src/time/strptime.c b/src/time/strptime.c index c54a0d8c..b1147242 100644 --- a/src/time/strptime.c +++ b/src/time/strptime.c @@ -59,6 +59,22 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri s = strptime(s, "%m/%d/%y", tm); if (!s) return 0; break; + case 'F': + /* Use temp buffer to implement the odd requirement + * that entire field be width-limited but the year + * subfield not itself be limited. */ + i = 0; + char tmp[20]; + if (*s == '-' || *s == '+') tmp[i++] = *s++; + while (*s=='0' && isdigit(s[1])) s++; + for (; *s && i<(size_t)w && i+1<sizeof tmp; i++) { + tmp[i] = *s++; + } + tmp[i] = 0; + char *p = strptime(tmp, "%12Y-%m-%d", tm); + if (!p) return 0; + s -= tmp+i-p; + break; case 'H': dest = &tm->tm_hour; min = 0; @@ -114,6 +130,13 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri s = strptime(s, "%H:%M", tm); if (!s) return 0; break; + case 's': + /* Parse only. Effect on tm is unspecified + * and presently no effect is implemented.. */ + if (*s == '-') s++; + if (!isdigit(*s)) return 0; + while (isdigit(*s)) s++; + break; case 'S': dest = &tm->tm_sec; min = 0; @@ -125,11 +148,30 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri break; case 'U': case 'W': - /* Throw away result, for now. (FIXME?) */ + /* Throw away result of %U, %V, %W, %g, and %G. Effect + * is unspecified and there is no clear right choice. */ dest = &dummy; min = 0; range = 54; goto numeric_range; + case 'V': + dest = &dummy; + min = 1; + range = 53; + goto numeric_range; + case 'g': + dest = &dummy; + w = 2; + goto numeric_digits; + case 'G': + dest = &dummy; + if (w<0) w=4; + goto numeric_digits; + case 'u': + dest = &tm->tm_wday; + min = 1; + range = 7; + goto numeric_range; case 'w': dest = &tm->tm_wday; min = 0; @@ -154,6 +196,28 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri adj = 1900; want_century = 0; goto numeric_digits; + case 'z': + if (*s == '+') neg = 0; + else if (*s == '-') neg = 1; + else return 0; + for (i=0; i<4; i++) if (!isdigit(s[1+i])) return 0; + tm->__tm_gmtoff = (s[1]-'0')*36000+(s[2]-'0')*3600 + + (s[3]-'0')*600 + (s[4]-'0')*60; + if (neg) tm->__tm_gmtoff = -tm->__tm_gmtoff; + s += 5; + break; + case 'Z': + if (!strncmp(s, tzname[0], len = strlen(tzname[0]))) { + tm->tm_isdst = 0; + s += len; + } else if (!strncmp(s, tzname[1], len=strlen(tzname[1]))) { + tm->tm_isdst = 1; + s += len; + } else { + /* FIXME: is this supposed to be an error? */ + while ((*s|32)-'a' <= 'z'-'a') s++; + } + break; case '%': if (*s++ != '%') return 0; break; diff --git a/src/time/timer_create.c b/src/time/timer_create.c index 5ddfda27..9216b3ab 100644 --- a/src/time/timer_create.c +++ b/src/time/timer_create.c @@ -43,6 +43,8 @@ static void *start(void *arg) union sigval val = args->sev->sigev_value; pthread_barrier_wait(&args->b); + if (self->cancel) + return 0; for (;;) { siginfo_t si; while (sigwaitinfo(SIGTIMER_SET, &si) < 0); @@ -59,7 +61,7 @@ static void *start(void *arg) int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict res) { - volatile static int init = 0; + static volatile int init = 0; pthread_t td; pthread_attr_t attr; int r; @@ -71,11 +73,15 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict switch (evp ? evp->sigev_notify : SIGEV_SIGNAL) { case SIGEV_NONE: case SIGEV_SIGNAL: + case SIGEV_THREAD_ID: if (evp) { ksev.sigev_value = evp->sigev_value; ksev.sigev_signo = evp->sigev_signo; ksev.sigev_notify = evp->sigev_notify; - ksev.sigev_tid = 0; + if (evp->sigev_notify == SIGEV_THREAD_ID) + ksev.sigev_tid = evp->sigev_notify_thread_id; + else + ksev.sigev_tid = 0; ksevp = &ksev; } if (syscall(SYS_timer_create, clk, ksevp, &timerid) < 0) @@ -107,10 +113,12 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict ksev.sigev_value.sival_ptr = 0; ksev.sigev_signo = SIGTIMER; - ksev.sigev_notify = 4; /* SIGEV_THREAD_ID */ + ksev.sigev_notify = SIGEV_THREAD_ID; ksev.sigev_tid = td->tid; - if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0) + if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0) { timerid = -1; + td->cancel = 1; + } td->timer_id = timerid; pthread_barrier_wait(&args.b); if (timerid < 0) return -1; |