summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2019-08-28 08:25:49 -0400
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2019-10-30 17:05:14 -0300
commitc3f9aef063cd9d5911e20d4f2b919ff2914c7965 (patch)
treebe4e804c1cef9e7be1b37e09de8d8f5e9b7dec08 /sysdeps
parent12cbde1dae6fa4a9a792b64564c7e0debf7544cc (diff)
downloadglibc-c3f9aef063cd9d5911e20d4f2b919ff2914c7965.tar.gz
glibc-c3f9aef063cd9d5911e20d4f2b919ff2914c7965.tar.xz
glibc-c3f9aef063cd9d5911e20d4f2b919ff2914c7965.zip
Use clock_settime to implement settimeofday.
Unconditionally, on all ports, use clock_settime to implement
settimeofday.  Remove sysdeps/unix/clock_settime.c, which implemented
clock_settime by calling settimeofday; new OS ports must henceforth
provide a real implementation of clock_settime.

Hurd had a real implementation of settimeofday but not of
clock_settime; this patch converts it into an implementation of
clock_settime.  It only supports CLOCK_REALTIME and microsecond
resolution; Hurd/Mach does not appear to have any support for
finer-resolution clocks.

The vestigial "set time zone" feature of settimeofday complicates the
generic settimeofday implementation a little.  The only remaining uses
of this feature that aren't just bugs, are using it to inform the
Linux kernel of the offset between the hardware clock and UTC, on
systems where the hardware clock doesn't run in UTC (usually because
of dual-booting with Windows).  There currently isn't any other way to
do this.  However, the callers that do this call settimeofday with
_only_ the timezone argument non-NULL.  Therefore, glibc's new
behavior is: callers of settimeofday must supply one and only one of
the two arguments.  If both arguments are non-NULL, or both arguments
are NULL, the call fails and sets errno to EINVAL.

When only the timeval argument is supplied, settimeofday calls
__clock_settime(CLOCK_REALTIME), same as stime.

When only the timezone argument is supplied, settimeofday calls a new
internal function called __settimezone.  On Linux, only, this function
will pass the timezone structure to the settimeofday system call.  On
all other operating systems, and on Linux architectures that don't
define __NR_settimeofday, __settimezone is a stub that always sets
errno to ENOSYS and returns -1.

The settimeoday syscall is enabled on Linux by the flag
COMPAT_32BIT_TIME, which is an option to either 32-bits ABIs or COMPAT
builds (defined usually by 64-bit kernels that want to support 32-bit
 ABIs, such as x86).  The idea to future 64-bit time_t only ABIs
is to not provide settimeofday syscall.

The same semantics are implemented for Linux/Alpha's GLIBC_2.0 compat
symbol for settimeofday.

There are no longer any internal callers of __settimeofday, so the
internal prototype is removed.

Checked on x86_64-linux-gnu, i686-linux-gnu, powerpc64le-linux-gnu,
powerpc64-linux-gnu, powerpc-linux-gnu, and aarch64-linux-gnu.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Reviewed-by: Lukasz Majewski <lukma@denx.de>
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/mach/hurd/clock_settime.c (renamed from sysdeps/unix/clock_settime.c)52
-rw-r--r--sysdeps/mach/hurd/settimeofday.c52
-rw-r--r--sysdeps/unix/syscalls.list1
-rw-r--r--sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c14
-rw-r--r--sysdeps/unix/sysv/linux/alpha/settimeofday.c22
-rw-r--r--sysdeps/unix/sysv/linux/alpha/syscalls.list1
-rw-r--r--sysdeps/unix/sysv/linux/alpha/tv32-compat.h6
-rw-r--r--sysdeps/unix/sysv/linux/settimezone.c36
8 files changed, 99 insertions, 85 deletions
diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/mach/hurd/clock_settime.c
index 54c917949f..a69fdca46a 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/mach/hurd/clock_settime.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999-2019 Free Software Foundation, Inc.
+/* Copyright (C) 1991-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
@@ -17,38 +17,32 @@
 
 #include <errno.h>
 #include <time.h>
-#include <sys/time.h>
+#include <hurd.h>
+#include <hurd/port.h>
 #include <shlib-compat.h>
 
-/* Set CLOCK to value TP.  */
+/* Set the current time of day.
+   This call is restricted to the super-user.  */
 int
-__clock_settime (clockid_t clock_id, const struct timespec *tp)
+__clock_settime (clockid_t clock_id, const struct timespec *ts)
 {
-  int retval = -1;
-
-  /* Make sure the time cvalue is OK.  */
-  if (! valid_nanoseconds (tp->tv_nsec))
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  switch (clock_id)
-    {
-    case CLOCK_REALTIME:
-      {
-	struct timeval tv;
-	TIMESPEC_TO_TIMEVAL (&tv, tp);
-	retval = __settimeofday (&tv, NULL);
-      }
-      break;
-
-    default:
-      __set_errno (EINVAL);
-      break;
-    }
-
-  return retval;
+  error_t err;
+  mach_port_t hostpriv;
+  time_value_t tv;
+
+  if (clock_id != CLOCK_REALTIME
+      || ! valid_nanoseconds (ts->tv_nsec))
+    return __hurd_fail (EINVAL);
+
+  err = __get_privileged_ports (&hostpriv, NULL);
+  if (err)
+    return __hurd_fail (EPERM);
+
+  TIMESPEC_TO_TIME_VALUE (&tv, ts);
+  err = __host_set_time (hostpriv, tv);
+  __mach_port_deallocate (__mach_task_self (), hostpriv);
+
+  return __hurd_fail (err);
 }
 libc_hidden_def (__clock_settime)
 
diff --git a/sysdeps/mach/hurd/settimeofday.c b/sysdeps/mach/hurd/settimeofday.c
deleted file mode 100644
index 31bffcad9d..0000000000
--- a/sysdeps/mach/hurd/settimeofday.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (C) 1991-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
-   <https://www.gnu.org/licenses/>.  */
-
-#include <errno.h>
-#include <sys/time.h>
-#include <hurd.h>
-#include <hurd/port.h>
-
-/* Set the current time of day and timezone information.
-   This call is restricted to the super-user.  */
-int
-__settimeofday (const struct timeval *tv, const struct timezone *tz)
-{
-  error_t err;
-  mach_port_t hostpriv;
-
-  if (tz != NULL)
-    {
-      errno = ENOSYS;
-      return -1;
-    }
-
-  err = __get_privileged_ports (&hostpriv, NULL);
-  if (err)
-    return __hurd_fail (EPERM);
-
-  /* `time_value_t' and `struct timeval' are in fact identical with the
-     names changed.  */
-  err = __host_set_time (hostpriv, *(time_value_t *) tv);
-  __mach_port_deallocate (__mach_task_self (), hostpriv);
-
-  if (err)
-    return __hurd_fail (err);
-
-  return 0;
-}
-
-weak_alias (__settimeofday, settimeofday)
diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list
index 61e5360b4d..5fedd5733d 100644
--- a/sysdeps/unix/syscalls.list
+++ b/sysdeps/unix/syscalls.list
@@ -76,7 +76,6 @@ setreuid	-	setreuid	i:ii	__setreuid	setreuid
 setrlimit	-	setrlimit	i:ip	__setrlimit setrlimit
 setsid		-	setsid		i:	__setsid	setsid
 setsockopt	-	setsockopt	i:iiibn	setsockopt	__setsockopt
-settimeofday	-	settimeofday	i:PP	__settimeofday	settimeofday
 setuid		-	setuid		i:i	__setuid	setuid
 shutdown	-	shutdown	i:ii	shutdown
 sigaction	-	sigaction	i:ipp	__sigaction	sigaction
diff --git a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
index 22de7b510c..48eef67429 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
@@ -32,8 +32,18 @@ attribute_compat_text_section
 __settimeofday_tv32 (const struct timeval32 *tv32,
                      const struct timezone *tz)
 {
-  struct timeval tv = valid_timeval_to_timeval64 (*tv32);
-  return __settimeofday (&tv, tz);
+  if (__glibc_unlikely (tz != 0))
+    {
+      if (tv32 != 0)
+	{
+	  __set_errno (EINVAL);
+	  return -1;
+	}
+      return __settimezone (tz);
+    }
+
+  struct timespec ts = valid_timeval32_to_timespec (*tv32);
+  return __clock_settime (CLOCK_REALTIME, &ts);
 }
 
 compat_symbol (libc, __settimeofday_tv32, settimeofday, GLIBC_2_0);
diff --git a/sysdeps/unix/sysv/linux/alpha/settimeofday.c b/sysdeps/unix/sysv/linux/alpha/settimeofday.c
new file mode 100644
index 0000000000..36a6901e4e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/settimeofday.c
@@ -0,0 +1,22 @@
+/* settimeofday -- Set the current time of day.  Linux/Alpha/tv64 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/>.  */
+
+/* We can use the generic implementation, but we have to override its
+   default symbol version.  */
+#define VERSION_settimeofday GLIBC_2.1
+#include <time/settimeofday.c>
diff --git a/sysdeps/unix/sysv/linux/alpha/syscalls.list b/sysdeps/unix/sysv/linux/alpha/syscalls.list
index c786aa751e..95a27e18e8 100644
--- a/sysdeps/unix/sysv/linux/alpha/syscalls.list
+++ b/sysdeps/unix/sysv/linux/alpha/syscalls.list
@@ -24,7 +24,6 @@ pciconfig_iobase EXTRA	pciconfig_iobase 3	__pciconfig_iobase pciconfig_iobase
 
 # timeval64 entry points (see osf_*.c for GLIBC_2.0 timeval32 equivalents)
 gettimeofday	-	gettimeofday	i:pP	__GI___gettimeofday gettimeofday@@GLIBC_2.1 __gettimeofday@@GLIBC_2.1
-settimeofday	-	settimeofday	i:PP	__settimeofday	settimeofday@@GLIBC_2.1
 getitimer	-	getitimer	i:ip	__getitimer	getitimer@@GLIBC_2.1
 setitimer	-	setitimer	i:ipP	__setitimer	setitimer@@GLIBC_2.1
 utimes		-	utimes		i:sp	__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
index d0b4cdcef3..5f86e66e08 100644
--- a/sysdeps/unix/sysv/linux/alpha/tv32-compat.h
+++ b/sysdeps/unix/sysv/linux/alpha/tv32-compat.h
@@ -83,6 +83,12 @@ valid_timeval64_to_timeval (const struct timeval tv64)
   return (struct timeval32) { tv64.tv_sec, tv64.tv_usec };
 }
 
+static inline struct timespec
+valid_timeval32_to_timespec (const struct timeval32 tv)
+{
+  return (struct timespec) { tv.tv_sec, tv.tv_usec * 1000 };
+}
+
 static inline void
 rusage64_to_rusage32 (struct rusage32 *restrict r32,
                       const struct rusage *restrict r64)
diff --git a/sysdeps/unix/sysv/linux/settimezone.c b/sysdeps/unix/sysv/linux/settimezone.c
new file mode 100644
index 0000000000..4aa86b3289
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/settimezone.c
@@ -0,0 +1,36 @@
+/* Obsolete set system time.  Linux 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 <errno.h>
+#include <sys/time.h>
+#include <sysdep.h>
+
+/* Set the system-wide timezone.
+   This call is restricted to the super-user.
+   This operation is considered obsolete, kernel support may not be
+   available on all architectures.  */
+int
+__settimezone (const struct timezone *tz)
+{
+#ifdef __NR_settimeofday
+  return INLINE_SYSCALL_CALL (settimeofday, NULL, tz);
+#else
+  __set_errno (ENOSYS);
+  return -1;
+#endif
+}