This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[glibc/zack/y2038-preliminaries] Linux/Alpha: don’t use timeval32 system calls.


https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=61120e45ef0b8a7c108ccec12e0221f4472479af

commit 61120e45ef0b8a7c108ccec12e0221f4472479af
Author: Zack Weinberg <zackw@panix.com>
Date:   Mon Aug 19 14:18:08 2019 -0400

    Linux/Alpha: donâ??t use timeval32 system calls.
    
    Linux/Alpha has two versions of several system call wrappers that take
    or return data of type â??struct timevalâ?? (possibly nested inside a
    larger structure).  The GLIBC_2.0 version is a compat symbol that
    calls __NR_osf_foo or __NR_old_foo and uses a struct timeval with a
    32-bit tv_sec field.  The GLIBC_2.1 version is used for current code,
    calls __NR_foo, and uses a struct timeval with a 64-bit tv_sec field.
    
    This patch changes all of the remaining compat symbols of this type to
    be wrappers around their GLIBC_2.1 counterparts.  (gettimeofday
    already received this treatment in an earlier patch in this series.)
    The compat symbols that copy out a 32-bit struct timeval all check for
    overflow.  After the Y2038 deadline, they will fail with errno set to
    EOVERFLOW, but only after copying out as much as they can, and filling
    in the overflowed â??struct timevalâ??(s) with tv_sec set to INT32_MAX and
    tv_nsec set to zero.
    
    The new header file tv32-compat.h is currently Alpha-specific but I
    donâ??t know any reason why it couldnâ??t be reused to aid in writing
    wrappers for all affected architectures.
    
    	* sysdeps/unix/sysv/linux/alpha/tv32-compat.h: New file declaring
    	types and helper functions for 32/64-bit time_t conversion.
    
    	* sysdeps/unix/sysv/linux/alpha/syscalls.list: Remove entries for
    	osf_getitimer, osf_setitimer, osf_utimes, osf_getrusage, and osf_wait4.
    
    	* sysdeps/unix/sysv/linux/alpha/osf_getitimer.c
    	* sysdeps/unix/sysv/linux/alpha/osf_getrusage.c
    	* sysdeps/unix/sysv/linux/alpha/osf_setitimer.c
    	* sysdeps/unix/sysv/linux/alpha/osf_utimes.c
    	* sysdeps/unix/sysv/linux/alpha/osf_wait4.c:
    	New files defining compatibility symbols formerly defined by
    	alpha/syscalls.list.
    
    	* sysdeps/unix/sysv/linux/alpha/adjtime.c: Split the compat code to...
    	* sysdeps/unix/sysv/linux/alpha/osf_adjtime.c: ...this new file.
    
    	* sysdeps/unix/sysv/linux/alpha/Makefile (sysdep_routines):
            Add osf_adjtime.
    
    	* sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
    	* sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c:
    	Use tv32-compat.h helpers.

Diff:
---
 sysdeps/unix/sysv/linux/alpha/Makefile           |   2 +-
 sysdeps/unix/sysv/linux/alpha/adjtime.c          |  70 ++---------
 sysdeps/unix/sysv/linux/alpha/osf_adjtime.c      | 135 ++++++++++++++++++++
 sysdeps/unix/sysv/linux/alpha/osf_getitimer.c    |  48 +++++++
 sysdeps/unix/sysv/linux/alpha/osf_getrusage.c    |  44 +++++++
 sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c |  27 ++--
 sysdeps/unix/sysv/linux/alpha/osf_setitimer.c    |  55 +++++++++
 sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c |  12 +-
 sysdeps/unix/sysv/linux/alpha/osf_utimes.c       |  36 ++++++
 sysdeps/unix/sysv/linux/alpha/osf_wait4.c        |  47 +++++++
 sysdeps/unix/sysv/linux/alpha/syscalls.list      |   9 +-
 sysdeps/unix/sysv/linux/alpha/tv32-compat.h      | 151 +++++++++++++++++++++++
 12 files changed, 536 insertions(+), 100 deletions(-)

diff --git a/sysdeps/unix/sysv/linux/alpha/Makefile b/sysdeps/unix/sysv/linux/alpha/Makefile
index fdd089a..2e132e4 100644
--- a/sysdeps/unix/sysv/linux/alpha/Makefile
+++ b/sysdeps/unix/sysv/linux/alpha/Makefile
@@ -9,7 +9,7 @@ sysdep_routines += ieee_get_fp_control ieee_set_fp_control \
 		   ioperm
 
 # Support old timeval32 entry points
-sysdep_routines += osf_gettimeofday osf_settimeofday \
+sysdep_routines += osf_adjtime osf_gettimeofday osf_settimeofday \
 		   osf_getitimer osf_setitimer osf_utimes \
 		   osf_getrusage osf_wait4
 
diff --git a/sysdeps/unix/sysv/linux/alpha/adjtime.c b/sysdeps/unix/sysv/linux/alpha/adjtime.c
index 65641e9..f67f522 100644
--- a/sysdeps/unix/sysv/linux/alpha/adjtime.c
+++ b/sysdeps/unix/sysv/linux/alpha/adjtime.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1998-2019 Free Software Foundation, Inc.
+/* adjtime -- adjust the system clock.  Linux/Alpha/tv64 version.
+   Copyright (C) 1998-2019 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
@@ -15,76 +16,19 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <shlib-compat.h>
 #include <sysdep.h>
 #include <sys/time.h>
+#include <shlib-compat.h>
 
-
-#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
-struct timeval32
-{
-    int tv_sec, tv_usec;
-};
-
-struct timex32 {
-	unsigned int modes;	/* mode selector */
-	long offset;		/* time offset (usec) */
-	long freq;		/* frequency offset (scaled ppm) */
-	long maxerror;		/* maximum error (usec) */
-	long esterror;		/* estimated error (usec) */
-	int status;		/* clock command/status */
-	long constant;		/* pll time constant */
-	long precision;		/* clock precision (usec) (read only) */
-	long tolerance;		/* clock frequency tolerance (ppm)
-				 * (read only)
-				 */
-	struct timeval32 time;	/* (read only) */
-	long tick;		/* (modified) usecs between clock ticks */
-
-	long ppsfreq;           /* pps frequency (scaled ppm) (ro) */
-	long jitter;            /* pps jitter (us) (ro) */
-	int shift;              /* interval duration (s) (shift) (ro) */
-	long stabil;            /* pps stability (scaled ppm) (ro) */
-	long jitcnt;            /* jitter limit exceeded (ro) */
-	long calcnt;            /* calibration intervals (ro) */
-	long errcnt;            /* calibration errors (ro) */
-	long stbcnt;            /* stability limit exceeded (ro) */
-
-	int  :32; int  :32; int  :32; int  :32;
-	int  :32; int  :32; int  :32; int  :32;
-	int  :32; int  :32; int  :32; int  :32;
-};
-
-#define TIMEVAL		timeval32
-#define TIMEX		timex32
-#define ADJTIME		attribute_compat_text_section __adjtime_tv32
-#define ADJTIMEX(x)	INLINE_SYSCALL (old_adjtimex, 1, x)
-#define ADJTIMEX32(x)	INLINE_SYSCALL (old_adjtimex, 1, x)
-
-#include <sysdeps/unix/sysv/linux/adjtime.c>
-
-int attribute_compat_text_section
-__adjtimex_tv32 (struct timex32 *tx) { return ADJTIMEX (tx); }
-
-strong_alias (__adjtimex_tv32, __adjtimex_tv32_1);
-strong_alias (__adjtimex_tv32, __adjtimex_tv32_2);
-compat_symbol (libc, __adjtimex_tv32_1, __adjtimex, GLIBC_2_0);
-compat_symbol (libc, __adjtimex_tv32_2, adjtimex, GLIBC_2_0);
-compat_symbol (libc, __adjtime_tv32, adjtime, GLIBC_2_0);
-#endif /* SHLIB_COMPAT */
-
-#undef TIMEVAL
-#undef TIMEX
-#undef ADJTIME
-#undef ADJTIMEX
-#define TIMEVAL		timeval
-#define TIMEX		timex
 #define ADJTIMEX(x)	INLINE_SYSCALL (adjtimex, 1, x)
 
 #include <sysdeps/unix/sysv/linux/adjtime.c>
 
 int
-__adjtimex_tv64 (struct timex *tx) { return ADJTIMEX (tx); }
+__adjtimex_tv64 (struct timex *tx)
+{
+  return ADJTIMEX (tx);
+}
 
 libc_hidden_ver (__adjtimex_tv64, __adjtimex)
 strong_alias (__adjtimex_tv64, __adjtimex_tv64p);
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_adjtime.c b/sysdeps/unix/sysv/linux/alpha/osf_adjtime.c
new file mode 100644
index 0000000..57c77c3
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_adjtime.c
@@ -0,0 +1,135 @@
+/* adjtime -- adjust the system clock.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+#include <errno.h>
+#include <tv32-compat.h>
+
+struct timex32 {
+	unsigned int modes;	/* mode selector */
+	long offset;		/* time offset (usec) */
+	long freq;		/* frequency offset (scaled ppm) */
+	long maxerror;		/* maximum error (usec) */
+	long esterror;		/* estimated error (usec) */
+	int status;		/* clock command/status */
+	long constant;		/* pll time constant */
+	long precision;		/* clock precision (usec) (read only) */
+	long tolerance;		/* clock frequency tolerance (ppm)
+				 * (read only)
+				 */
+	struct timeval32 time;	/* (read only) */
+	long tick;		/* (modified) usecs between clock ticks */
+
+	long ppsfreq;           /* pps frequency (scaled ppm) (ro) */
+	long jitter;            /* pps jitter (us) (ro) */
+	int shift;              /* interval duration (s) (shift) (ro) */
+	long stabil;            /* pps stability (scaled ppm) (ro) */
+	long jitcnt;            /* jitter limit exceeded (ro) */
+	long calcnt;            /* calibration intervals (ro) */
+	long errcnt;            /* calibration errors (ro) */
+	long stbcnt;            /* stability limit exceeded (ro) */
+
+	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32; int  :32;
+};
+
+int attribute_compat_text_section
+__adjtime_tv32 (const struct timeval32 *itv, struct timeval32 *otv)
+{
+  struct timeval itv64, otv64;
+  TV32_TO_TV64 (&itv64, itv);
+  if (__adjtime (&itv64, &otv64))
+    return -1;
+  if (TV64_TO_TV32 (otv, &itv64))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+  return 0;
+}
+
+int attribute_compat_text_section
+__adjtimex_tv32 (struct timex32 *tx)
+{
+  struct timex tx64;
+  memset (&tx64, 0, sizeof tx64);
+  tx64.modes     = tx->modes;
+  tx64.offset    = tx->offset;
+  tx64.freq      = tx->freq;
+  tx64.maxerror  = tx->maxerror;
+  tx64.esterror  = tx->esterror;
+  tx64.status    = tx->status;
+  tx64.constant  = tx->constant;
+  tx64.precision = tx->precision;
+  tx64.tolerance = tx->tolerance;
+  tx64.tick      = tx->tick;
+  tx64.ppsfreq   = tx->ppsfreq;
+  tx64.jitter    = tx->jitter;
+  tx64.shift     = tx->shift;
+  tx64.stabil    = tx->stabil;
+  tx64.jitcnt    = tx->jitcnt;
+  tx64.calcnt    = tx->calcnt;
+  tx64.errcnt    = tx->errcnt;
+  tx64.stbcnt    = tx->stbcnt;
+  TV32_TO_TV64 (&tx64.time, &tx->time);
+
+  int status = __adjtimex (&tx64);
+  if (status < 0)
+    return status;
+
+  memset (tx, 0, sizeof *tx);
+  tx->modes     = tx64.modes;
+  tx->offset    = tx64.offset;
+  tx->freq      = tx64.freq;
+  tx->maxerror  = tx64.maxerror;
+  tx->esterror  = tx64.esterror;
+  tx->status    = tx64.status;
+  tx->constant  = tx64.constant;
+  tx->precision = tx64.precision;
+  tx->tolerance = tx64.tolerance;
+  tx->tick      = tx64.tick;
+  tx->ppsfreq   = tx64.ppsfreq;
+  tx->jitter    = tx64.jitter;
+  tx->shift     = tx64.shift;
+  tx->stabil    = tx64.stabil;
+  tx->jitcnt    = tx64.jitcnt;
+  tx->calcnt    = tx64.calcnt;
+  tx->errcnt    = tx64.errcnt;
+  tx->stbcnt    = tx64.stbcnt;
+  if (TV64_TO_TV32 (&tx->time, &tx64.time))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  return status;
+}
+
+strong_alias (__adjtimex_tv32, __adjtimex_tv32_1);
+strong_alias (__adjtimex_tv32, __adjtimex_tv32_2);
+compat_symbol (libc, __adjtimex_tv32_1, __adjtimex, GLIBC_2_0);
+compat_symbol (libc, __adjtimex_tv32_2, adjtimex, GLIBC_2_0);
+compat_symbol (libc, __adjtime_tv32, adjtime, GLIBC_2_0);
+
+#endif /* SHLIB_COMPAT */
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_getitimer.c b/sysdeps/unix/sysv/linux/alpha/osf_getitimer.c
new file mode 100644
index 0000000..d15d8f5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_getitimer.c
@@ -0,0 +1,48 @@
+/* getitimer -- Get the state of an interval timer.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/time.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+#include <errno.h>
+#include <tv32-compat.h>
+
+int
+__getitimer_tv32 (int which, struct itimerval32 *curr_value)
+{
+  struct itimerval curr_value_64;
+  if (__getitimer (which, &curr_value_64))
+    return -1;
+
+  /* Make sure both fields of the output are filled in, even if one of them
+     overflows.  */
+  int e;
+  e  = TV64_TO_TV32 (&curr_value->it_interval, &curr_value_64.it_interval);
+  e |= TV64_TO_TV32 (&curr_value->it_value, &curr_value_64.it_value);
+  if (e)
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+  return 0;
+}
+
+compat_symbol (libc, __getitimer_tv32, getitimer, GLIBC_2_0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_getrusage.c b/sysdeps/unix/sysv/linux/alpha/osf_getrusage.c
new file mode 100644
index 0000000..ac094dd
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_getrusage.c
@@ -0,0 +1,44 @@
+/* utimes -- change file timestamps.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+#include <errno.h>
+#include <tv32-compat.h>
+
+int
+__getrusage_tv32 (int who, struct rusage32 *usage32)
+{
+  struct rusage usage64;
+  if (__getrusage (who, &usage64))
+    return -1;
+
+  if (RUSAGE64_TO_RUSAGE32 (usage32, &usage64))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+  return 0;
+}
+
+compat_symbol (libc, __getrusage_tv32, getrusage, GLIBC_2_0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c b/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
index 9868dfd..cc4c4ee 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_gettimeofday.c
@@ -16,19 +16,15 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <limits.h>
-#include <string.h>
-#include <time.h>
 #include <sys/time.h>
 #include <shlib-compat.h>
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
 
-struct timeval32
-{
-    int tv_sec, tv_usec;
-};
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <tv32-compat.h>
 
 /* Get the current time of day, putting it into *TV.
    If *TZ is not NULL, clear it.
@@ -36,29 +32,20 @@ struct timeval32
 
 int
 attribute_compat_text_section
-__gettimeofday_tv32 (struct timeval32 *tv32,
-                     struct timezone *tz)
+__gettimeofday_tv32 (struct timeval32 *restrict tv32, void *restrict tz)
 {
   if (__glibc_unlikely (tz != 0))
-    memset (tz, 0, sizeof *tz);
+    memset (tz, 0, sizeof (struct timezone));
 
   struct timespec ts;
   if (__clock_gettime (CLOCK_REALTIME, &ts))
     return -1;
 
-  if (__glibc_unlikely (ts.tv_sec > (time_t)INT_MAX))
+  if (TS64_TO_TV32 (tv32, &ts))
     {
-      /* The clock has advanced past the time representable in a 32-bit
-         time_t.  Fail, but write a saturated value to the output first,
-         because callers don't typically expect gettimeofday to fail.  */
       __set_errno (EOVERFLOW);
-      tv32->tv_sec  = INT_MAX;
-      tv32->tv_usec = 0;
       return -1;
     }
-
-  tv32->tv_sec = ts.tv_sec;
-  tv32->tv_usec = ts.tv_nsec / 1000;
   return 0;
 }
 
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_setitimer.c b/sysdeps/unix/sysv/linux/alpha/osf_setitimer.c
new file mode 100644
index 0000000..48d5bbc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_setitimer.c
@@ -0,0 +1,55 @@
+/* getitimer -- Get the state of an interval timer.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/time.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+#include <errno.h>
+#include <tv32-compat.h>
+
+int
+__setitimer_tv32 (int which, const struct itimerval32 *restrict new_value,
+		  struct itimerval32 *restrict old_value)
+{
+  struct itimerval new_value_64;
+  TV32_TO_TV64 (&new_value_64.it_interval, &new_value->it_interval);
+  TV32_TO_TV64 (&new_value_64.it_value, &new_value->it_value);
+
+  if (!old_value)
+    return __setitimer (which, &new_value_64, 0);
+
+  struct itimerval old_value_64;
+  if (__setitimer (which, &new_value_64, &old_value_64))
+    return -1;
+
+  /* Write all fields of 'old_value' even on error.  */
+  int e = 0;
+  e |= TV64_TO_TV32 (&old_value->it_interval, &old_value_64.it_interval);
+  e |= TV64_TO_TV32 (&old_value->it_value, &old_value_64.it_value);
+  if (e)
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+  return 0;
+}
+
+compat_symbol (libc, __setitimer_tv32, setitimer, GLIBC_2_0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
index a61fcab..d793b24 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
@@ -16,17 +16,14 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <errno.h>
-#include <time.h>
 #include <sys/time.h>
 #include <shlib-compat.h>
 
 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
 
-struct timeval32
-{
-    int tv_sec, tv_usec;
-};
+#include <errno.h>
+#include <time.h>
+#include <tv32-compat.h>
 
 /* Set the current time of day and timezone information.
    This call is restricted to the super-user.  */
@@ -46,8 +43,7 @@ __settimeofday_tv32 (const struct timeval32 *tv32,
     }
 
   struct timespec ts;
-  ts.tv_sec = tv32->tv_sec;
-  ts.tv_nsec = tv32->tv_usec * 1000;
+  TV32_TO_TS64 (&ts, tv32);
   return __clock_settime (CLOCK_REALTIME, &ts);
 }
 
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_utimes.c b/sysdeps/unix/sysv/linux/alpha/osf_utimes.c
new file mode 100644
index 0000000..7ed483f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_utimes.c
@@ -0,0 +1,36 @@
+/* utimes -- change file timestamps.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/time.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+#include <tv32-compat.h>
+
+int
+__utimes_tv32 (const char *filename, const struct timeval32 times32[2])
+{
+  struct timeval times[2];
+  TV32_TO_TV64 (&times[0], &times32[0]);
+  TV32_TO_TV64 (&times[1], &times32[1]);
+  return __utimes (filename, times);
+}
+
+compat_symbol (libc, __utimes_tv32, utimes, GLIBC_2_0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_wait4.c b/sysdeps/unix/sysv/linux/alpha/osf_wait4.c
new file mode 100644
index 0000000..6ad3f1d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/osf_wait4.c
@@ -0,0 +1,47 @@
+/* wait4 -- wait for process to change state.  Linux/Alpha/tv32 version.
+   Copyright (C) 2019 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
+
+#include <errno.h>
+#include <string.h>
+#include <tv32-compat.h>
+
+pid_t
+__wait4_tv32 (pid_t pid, int *status, int options, struct rusage32 *usage32)
+{
+  struct rusage usage64;
+  pid_t child = __wait4 (pid, status, options, &usage64);
+  if (child < 0)
+    return child;
+
+  if (RUSAGE64_TO_RUSAGE32 (usage32, &usage64))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+  return child;
+}
+
+compat_symbol (libc, __wait4_tv32, wait4, GLIBC_2_0);
+#endif
diff --git a/sysdeps/unix/sysv/linux/alpha/syscalls.list b/sysdeps/unix/sysv/linux/alpha/syscalls.list
index 9ceed78..0e472b4 100644
--- a/sysdeps/unix/sysv/linux/alpha/syscalls.list
+++ b/sysdeps/unix/sysv/linux/alpha/syscalls.list
@@ -22,14 +22,7 @@ pciconfig_read	EXTRA	pciconfig_read	5	pciconfig_read
 pciconfig_write	EXTRA	pciconfig_write	5	pciconfig_write
 pciconfig_iobase EXTRA	pciconfig_iobase 3	__pciconfig_iobase pciconfig_iobase
 
-# support old timeval32 entry points
-osf_getitimer	-	osf_getitimer	2	__getitimer_tv32  getitimer@GLIBC_2.0
-osf_setitimer	-	osf_setitimer	3	__setitimer_tv32  setitimer@GLIBC_2.0
-osf_utimes	-	osf_utimes	2	__utimes_tv32  utimes@GLIBC_2.0
-osf_getrusage	-	osf_getrusage	2	__getrusage_tv32  getrusage@GLIBC_2.0
-osf_wait4	-	osf_wait4	4	__wait4_tv32  wait4@GLIBC_2.0
-
-# support new timeval64 entry points
+# new timeval64 entry points (see osf_* for the GLIBC_2.0 versions)
 getitimer	-	getitimer	2	__getitimer getitimer@@GLIBC_2.1
 setitimer	-	setitimer	3	__setitimer setitimer@@GLIBC_2.1
 utimes		-	utimes		2	__utimes utimes@@GLIBC_2.1
diff --git a/sysdeps/unix/sysv/linux/alpha/tv32-compat.h b/sysdeps/unix/sysv/linux/alpha/tv32-compat.h
new file mode 100644
index 0000000..926e8ce
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/tv32-compat.h
@@ -0,0 +1,151 @@
+/* Compatibility definitions for `struct timeval' with 32-bit time_t.
+   Copyright (C) 2019 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
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _TV32_COMPAT_H
+#define _TV32_COMPAT_H 1
+
+#include <features.h>
+
+#include <bits/types.h>
+#include <bits/types/time_t.h>
+#include <bits/types/struct_timeval.h>
+#include <bits/types/struct_timespec.h>
+#include <bits/types/struct_rusage.h>
+
+#include <stdint.h> // for INT32_MAX
+#include <string.h> // for memset
+
+/* A version of 'struct timeval' with 32-bit time_t.  */
+struct timeval32
+{
+  int32_t tv_sec;
+  int32_t tv_usec;
+};
+
+/* Structures containing 'struct timeval' with 32-bit time_t.  */
+struct itimerval32
+{
+  struct timeval32 it_interval;
+  struct timeval32 it_value;
+};
+
+struct rusage32
+{
+  struct timeval32 ru_utime;	/* user time used */
+  struct timeval32 ru_stime;	/* system time used */
+  long ru_maxrss;		/* maximum resident set size */
+  long ru_ixrss;		/* integral shared memory size */
+  long ru_idrss;		/* integral unshared data size */
+  long ru_isrss;		/* integral unshared stack size */
+  long ru_minflt;		/* page reclaims */
+  long ru_majflt;		/* page faults */
+  long ru_nswap;		/* swaps */
+  long ru_inblock;		/* block input operations */
+  long ru_oublock;		/* block output operations */
+  long ru_msgsnd;		/* messages sent */
+  long ru_msgrcv;		/* messages received */
+  long ru_nsignals;		/* signals received */
+  long ru_nvcsw;		/* voluntary context switches */
+  long ru_nivcsw;		/* involuntary " */
+};
+
+/* Conversion functions.  If the seconds field of a timeval32 would
+   overflow, they write { INT32_MAX, 0 } to the output and return -1;
+   otherwise they return 0.  */
+
+__extern_always_inline void
+TV32_TO_TV64 (struct timeval *restrict tv64,
+              const struct timeval32 *restrict tv32)
+{
+  tv64->tv_sec = tv32->tv_sec;
+  tv64->tv_usec = tv32->tv_usec;
+}
+
+__extern_always_inline void
+TV32_TO_TS64 (struct timespec *restrict ts64,
+              const struct timeval32 *restrict tv32)
+{
+  ts64->tv_sec = tv32->tv_sec;
+  ts64->tv_nsec = tv32->tv_usec * 1000;
+}
+
+__extern_always_inline int
+TV64_TO_TV32 (struct timeval32 *restrict tv32,
+              const struct timeval *restrict tv64)
+{
+  if (__glibc_unlikely (tv64->tv_sec > (time_t) INT32_MAX))
+    {
+      tv32->tv_sec = INT32_MAX;
+      tv32->tv_usec = 0;
+      return -1;
+    }
+  else
+    {
+      tv32->tv_sec = tv64->tv_sec;
+      tv32->tv_usec = tv64->tv_usec;
+      return 0;
+    }
+}
+
+__extern_always_inline int
+TS64_TO_TV32 (struct timeval32 *restrict tv32,
+              const struct timespec *restrict ts64)
+{
+  if (__glibc_unlikely (ts64->tv_sec > (time_t) INT32_MAX))
+    {
+      tv32->tv_sec = INT32_MAX;
+      tv32->tv_usec = 0;
+      return -1;
+    }
+  else
+    {
+      tv32->tv_sec = ts64->tv_sec;
+      tv32->tv_usec = ts64->tv_nsec / 1000;
+      return 0;
+    }
+}
+
+__extern_always_inline int
+RUSAGE64_TO_RUSAGE32 (struct rusage32 *restrict r32,
+                      const struct rusage *restrict r64)
+{
+  /* Fill out the entire structure even on failure.  */
+  memset (r32, 0, sizeof *r32);
+
+  int e = 0;
+  e |= TV64_TO_TV32 (&r32->ru_utime, &r64->ru_utime);
+  e |= TV64_TO_TV32 (&r32->ru_stime, &r64->ru_stime);
+  r32->ru_maxrss   = r64->ru_maxrss;
+  r32->ru_ixrss    = r64->ru_ixrss;
+  r32->ru_idrss    = r64->ru_idrss;
+  r32->ru_isrss    = r64->ru_isrss;
+  r32->ru_minflt   = r64->ru_minflt;
+  r32->ru_majflt   = r64->ru_majflt;
+  r32->ru_nswap    = r64->ru_nswap;
+  r32->ru_inblock  = r64->ru_inblock;
+  r32->ru_oublock  = r64->ru_oublock;
+  r32->ru_msgsnd   = r64->ru_msgsnd;
+  r32->ru_msgrcv   = r64->ru_msgrcv;
+  r32->ru_nsignals = r64->ru_nsignals;
+  r32->ru_nvcsw    = r64->ru_nvcsw;
+  r32->ru_nivcsw   = r64->ru_nivcsw;
+
+  return e;
+}
+
+#endif /* tv32-compat.h */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]