From: Albert ARIBAUD (3ADEV) Date: Thu, 7 Sep 2017 22:42:05 +0000 (+0200) Subject: Y2038: add function __adjtime64, __adjtimex64 and __ntp_adjtime64 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4a7c14136ed979efd94dfb98e5321b3e06509764;p=thirdparty%2Fglibc.git Y2038: add function __adjtime64, __adjtimex64 and __ntp_adjtime64 --- diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c index 6edecb70e82..4238abd698d 100644 --- a/sysdeps/unix/sysv/linux/adjtime.c +++ b/sysdeps/unix/sysv/linux/adjtime.c @@ -19,6 +19,7 @@ #include #include #include +#include #define MAX_SEC (INT_MAX / 1000000L - 2) #define MIN_SEC (INT_MIN / 1000000L + 2) diff --git a/sysdeps/unix/sysv/linux/adjtime64.c b/sysdeps/unix/sysv/linux/adjtime64.c new file mode 100644 index 00000000000..c305717958c --- /dev/null +++ b/sysdeps/unix/sysv/linux/adjtime64.c @@ -0,0 +1,164 @@ +/* Copyright (C) 1995-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include + +#define MAX_SEC (INT_MAX / 1000000L - 2) +#define MIN_SEC (INT_MIN / 1000000L + 2) + +#ifndef MOD_OFFSET +#define modes mode +#endif + +#ifndef TIMEVAL +#define TIMEVAL timeval +#endif + +#ifndef TIMEX +#define TIMEX timex +#endif + +#ifndef ADJTIME +#define ADJTIME __adjtime +#endif + +#ifndef ADJTIMEX +#define NO_LOCAL_ADJTIME +#define ADJTIMEX(x) __adjtimex (x) +#endif + +#ifndef LINKAGE +#define LINKAGE +#endif + +int __adjtime64 (const struct __timeval64 *itv, + struct __timeval64 *otv) +{ + struct TIMEX tntx; + + if (itv) + { + struct TIMEVAL tmp; + + /* We will do some check here. */ + tmp.tv_sec = itv->tv_sec + itv->tv_usec / 1000000L; + tmp.tv_usec = itv->tv_usec % 1000000L; + if (tmp.tv_sec > MAX_SEC || tmp.tv_sec < MIN_SEC) + return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); + tntx.offset = tmp.tv_usec + tmp.tv_sec * 1000000L; + tntx.modes = ADJ_OFFSET_SINGLESHOT; + } + else + tntx.modes = ADJ_OFFSET_SS_READ; + + if (__glibc_unlikely (ADJTIMEX (&tntx) < 0)) + return -1; + + if (otv) + { + if (tntx.offset < 0) + { + otv->tv_usec = -(-tntx.offset % 1000000); + otv->tv_sec = -(-tntx.offset / 1000000); + } + else + { + otv->tv_usec = tntx.offset % 1000000; + otv->tv_sec = tntx.offset / 1000000; + } + } + return 0; +} + +int +__adjtimex64(struct __timex64 *tx) +{ + struct timex tx32; + + if (tx == NULL) + { + __set_errno (EFAULT); + return -1; + } + + if ((tx->modes & ADJ_SETOFFSET) != 0 && tx->time.tv_sec > INT_MAX) + { + __set_errno (EOVERFLOW); + return -1; + } + + /* Implement with existing 32-bit time syscall */ + + /* Just copy everything */ + tx32.modes = tx->modes; + tx32.offset = tx->offset; + tx32.freq = tx->freq; + tx32.maxerror = tx->maxerror; + tx32.esterror = tx->esterror; + tx32.status = tx->status; + tx32.constant = tx->constant; + tx32.precision = tx->precision; + tx32.tolerance = tx->tolerance; + tx32.time.tv_sec = tx->time.tv_sec; + tx32.time.tv_usec = tx->time.tv_usec; + tx32.tick = tx->tick; + tx32.ppsfreq = tx->ppsfreq; + tx32.jitter = tx->jitter; + tx32.shift = tx->shift; + tx32.stabil = tx->stabil; + tx32.jitcnt = tx->jitcnt; + tx32.calcnt = tx->calcnt; + tx32.errcnt = tx->errcnt; + tx32.stbcnt = tx->stbcnt; + + tx32.tai = tx->tai; + /* WARNING -- anonymous fields after TAI are not copied. */ + + int result = ADJTIMEX(&tx32); + + if (result == 0) + { + /* Just copy back everything */ + tx->modes = tx32.modes; + tx->offset = tx32.offset; + tx->freq = tx32.freq; + tx->maxerror = tx32.maxerror; + tx->esterror = tx32.esterror; + tx->status = tx32.status; + tx->constant = tx32.constant; + tx->precision = tx32.precision; + tx->tolerance = tx32.tolerance; + tx->time.tv_sec = tx32.time.tv_sec; + tx->time.tv_usec = tx32.time.tv_usec; + tx->tick = tx32.tick; + tx->ppsfreq = tx32.ppsfreq; + tx->jitter = tx32.jitter; + tx->shift = tx32.shift; + tx->stabil = tx32.stabil; + tx->jitcnt = tx32.jitcnt; + tx->calcnt = tx32.calcnt; + tx->errcnt = tx32.errcnt; + tx->stbcnt = tx32.stbcnt; + } + + return result; +} +weak_alias (__adjtimex64, __ntp_adjtime64); diff --git a/time/Versions b/time/Versions index c28dab69a15..a965b6982b9 100644 --- a/time/Versions +++ b/time/Versions @@ -85,5 +85,7 @@ libc { __time64; __stime64; __utimes64; + __adjtime64; + __adjtimex64; } } diff --git a/time/adjtime.c b/time/adjtime.c index 4a972d66cd6..800715c0162 100644 --- a/time/adjtime.c +++ b/time/adjtime.c @@ -31,3 +31,13 @@ __adjtime (const struct timeval *delta, struct timeval *olddelta) stub_warning (adjtime) weak_alias (__adjtime, adjtime) + +/* 64-bit time version */ + +int +__adjtime64 (const struct __timeval64 *delta, struct __timeval64 *olddelta) +{ + __set_errno (ENOSYS); + return -1; +} +stub_warning (__adjtime64)