[RFC,48/52] Y2038: add function __adjtimex_t64 (and __ntp_adjtime_t64)

Message ID 20170907224219.12483-49-albert.aribaud@3adev.fr
State New
Headers show
Series
  • Make GLIBC Y2038-proof
Related show

Commit Message

Albert ARIBAUD Sept. 7, 2017, 10:42 p.m.
Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
---
 include/time.h                    | 31 +++++++++++++++
 sysdeps/unix/sysv/linux/adjtime.c | 81 +++++++++++++++++++++++++++++++++++++++
 time/Versions                     |  1 +
 3 files changed, 113 insertions(+)

Patch

diff --git a/include/time.h b/include/time.h
index 5db1d44470..1914c20a75 100644
--- a/include/time.h
+++ b/include/time.h
@@ -72,6 +72,37 @@  struct __ntptimeval_t64
   long int __glibc_reserved4;
 };
 
+/* 64-bit time version of the current struct timex */
+struct __timex_t64
+{
+  unsigned int modes;		/* mode selector */
+  __syscall_slong_t offset;	/* time offset (usec) */
+  __syscall_slong_t freq;	/* frequency offset (scaled ppm) */
+  __syscall_slong_t maxerror;	/* maximum error (usec) */
+  __syscall_slong_t esterror;	/* estimated error (usec) */
+  int status;			/* clock command/status */
+  __syscall_slong_t constant;	/* pll time constant */
+  __syscall_slong_t precision;	/* clock precision (usec) (ro) */
+  __syscall_slong_t tolerance;	/* clock frequency tolerance (ppm) (ro) */
+  struct __timeval64 time;	/* (read only, except for ADJ_SETOFFSET) */
+  __syscall_slong_t tick;	/* (modified) usecs between clock ticks */
+  __syscall_slong_t ppsfreq;	/* pps frequency (scaled ppm) (ro) */
+  __syscall_slong_t jitter;	/* pps jitter (us) (ro) */
+  int shift;			/* interval duration (s) (shift) (ro) */
+  __syscall_slong_t stabil;	/* pps stability (scaled ppm) (ro) */
+  __syscall_slong_t jitcnt;	/* jitter limit exceeded (ro) */
+  __syscall_slong_t calcnt;	/* calibration intervals (ro) */
+  __syscall_slong_t errcnt;	/* calibration errors (ro) */
+  __syscall_slong_t stbcnt;	/* stability limit exceeded (ro) */
+
+  int tai;			/* TAI offset (ro) */
+
+  /* ??? */
+  int  :32; int  :32; int  :32; int  :32;
+  int  :32; int  :32; int  :32; int  :32;
+  int  :32; int  :32; int  :32;
+};
+
 extern __typeof (clock_getres) __clock_getres;
 extern __typeof (clock_gettime) __clock_gettime;
 libc_hidden_proto (__clock_gettime)
diff --git a/sysdeps/unix/sysv/linux/adjtime.c b/sysdeps/unix/sysv/linux/adjtime.c
index 28a75a2e40..60211a5223 100644
--- a/sysdeps/unix/sysv/linux/adjtime.c
+++ b/sysdeps/unix/sysv/linux/adjtime.c
@@ -19,6 +19,7 @@ 
 #include <limits.h>
 #include <sys/time.h>
 #include <sys/timex.h>
+#include <include/time.h>
 
 #define MAX_SEC	(INT_MAX / 1000000L - 2)
 #define MIN_SEC	(INT_MIN / 1000000L + 2)
@@ -133,3 +134,83 @@  int __adjtime_t64 (const struct __timeval64 *itv,
     }
   return 0;
 }
+
+int
+__adjtimex_t64(struct __timex_t64 *tx)
+{
+  struct timex tx32;
+
+  if (__y2038_linux_support)
+    {
+      /* TODO: implement with a 64-bit time syscall */
+    }
+
+  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 (__adjtimex_t64, __ntp_adjtime_t64);
diff --git a/time/Versions b/time/Versions
index b847718757..9e23793cfb 100644
--- a/time/Versions
+++ b/time/Versions
@@ -79,5 +79,6 @@  libc {
     __adjtime_t64;
     __getitimer_t64;
     __setitimer_t64;
+    __adjtimex_t64;
   }
 }