clock_settime: add time64 syscall support, decouple 32-bit time_t

time64 syscall is used only if it's the only one defined for the arch,
or if the requested time does not fit in 32 bits. on current 32-bit
archs where time_t is a 32-bit type, this makes it statically
unreachable.

if the time64 syscall is needed because the requested time does not
fit in 32 bits, we define this as an error ENOTSUP, for "The
implementation does not support the requested feature or value".

on 64-bit archs, there is no change to the code after preprocessing.
on current 32-bit archs, the time is moved through an intermediate
copy to remove the assumption that time_t is a 32-bit type.
This commit is contained in:
Rich Felker 2019-07-28 18:43:51 -04:00
parent e1501091c4
commit 7aeecf3e0b
1 changed files with 17 additions and 0 deletions

View File

@ -1,7 +1,24 @@
#include <time.h>
#include <errno.h>
#include "syscall.h"
#define IS32BIT(x) !((x)+0x80000000ULL>>32)
int clock_settime(clockid_t clk, const struct timespec *ts)
{
#ifdef SYS_clock_settime64
time_t s = ts->tv_sec;
long ns = ts->tv_nsec;
int r = -ENOSYS;
if (SYS_clock_settime == SYS_clock_settime64 || !IS32BIT(s))
r = __syscall(SYS_clock_settime64, clk,
((long long[]){s, ns}));
if (SYS_clock_settime == SYS_clock_settime64 || r!=-ENOSYS)
return __syscall_ret(r);
if (!IS32BIT(s))
return __syscall_ret(-ENOTSUP);
return syscall(SYS_clock_settime, clk, ts ? ((long[]){s, ns}) : 0);
#else
return syscall(SYS_clock_settime, clk, ts);
#endif
}