diff mbox series

[v2,04/11] Use clock_settime to implement settimeofday.

Message ID 20191025120832.27667-5-adhemerval.zanella@linaro.org
State Accepted
Commit c3f9aef063cd9d5911e20d4f2b919ff2914c7965
Headers show
Series Y2038 preparation: use clock_[gs]ettime to implement the other time-getting and -setting functions. | expand

Commit Message

Adhemerval Zanella Oct. 25, 2019, 12:08 p.m. UTC
From: Zack Weinberg <zackw@panix.com>


Use clock_settime to implement settimeofday.

Changes from previous version:

  - Added a NEWS entry.

--

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>

---
 NEWS                                          | 24 +++++++++
 include/sys/time.h                            |  3 +-
 sysdeps/{unix => mach/hurd}/clock_settime.c   | 51 ++++++++-----------
 sysdeps/unix/syscalls.list                    |  1 -
 .../unix/sysv/linux/alpha/osf_settimeofday.c  | 16 ++++--
 sysdeps/unix/sysv/linux/alpha/settimeofday.c  | 22 ++++++++
 sysdeps/unix/sysv/linux/alpha/syscalls.list   |  1 -
 sysdeps/unix/sysv/linux/settimezone.c         | 36 +++++++++++++
 time/Makefile                                 |  8 +--
 time/settimeofday.c                           | 24 +++++++--
 .../hurd/settimeofday.c => time/settimezone.c | 34 ++-----------
 11 files changed, 147 insertions(+), 73 deletions(-)
 rename sysdeps/{unix => mach/hurd}/clock_settime.c (65%)
 create mode 100644 sysdeps/unix/sysv/linux/alpha/settimeofday.c
 create mode 100644 sysdeps/unix/sysv/linux/settimezone.c
 rename sysdeps/mach/hurd/settimeofday.c => time/settimezone.c (52%)

-- 
2.17.1

Comments

Lukasz Majewski Oct. 25, 2019, 3:28 p.m. UTC | #1
On Fri, 25 Oct 2019 09:08:25 -0300
Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote:

> From: Zack Weinberg <zackw@panix.com>

> 

> Use clock_settime to implement settimeofday.

> 

> Changes from previous version:

> 

>   - Added a NEWS entry.

> 

> --

> 

> 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>

> ---

>  NEWS                                          | 24 +++++++++

>  include/sys/time.h                            |  3 +-

>  sysdeps/{unix => mach/hurd}/clock_settime.c   | 51

> ++++++++----------- sysdeps/unix/syscalls.list                    |

> 1 - .../unix/sysv/linux/alpha/osf_settimeofday.c  | 16 ++++--

>  sysdeps/unix/sysv/linux/alpha/settimeofday.c  | 22 ++++++++

>  sysdeps/unix/sysv/linux/alpha/syscalls.list   |  1 -

>  sysdeps/unix/sysv/linux/settimezone.c         | 36 +++++++++++++

>  time/Makefile                                 |  8 +--

>  time/settimeofday.c                           | 24 +++++++--

>  .../hurd/settimeofday.c => time/settimezone.c | 34 ++-----------

>  11 files changed, 147 insertions(+), 73 deletions(-)

>  rename sysdeps/{unix => mach/hurd}/clock_settime.c (65%)

>  create mode 100644 sysdeps/unix/sysv/linux/alpha/settimeofday.c

>  create mode 100644 sysdeps/unix/sysv/linux/settimezone.c

>  rename sysdeps/mach/hurd/settimeofday.c => time/settimezone.c (52%)

> 

> diff --git a/NEWS b/NEWS

> index 8727b5e7f0..0b1476e745 100644

> --- a/NEWS

> +++ b/NEWS

> @@ -34,6 +34,30 @@ Deprecated and removed features, and other changes

> affecting compatibility: binaries and it has been removed from

> <time.h> header.  This function has been deprecated in favor of

> clock_settime. 

> +* The settimeofday function can still be used to set a system-wide

> time

> +  zone when the operating system supports it.  This is because the

> Linux

> +  kernel reused the API, on some architectures, to describe a

> system-wide

> +  time-zone-like offset between the software clock maintained by the

> kernel,

> +  and the “RTC” clock that keeps time when the system is shut down.

> +

> +  However, to reduce the odds of this offset being set by accident,

> +  settimeofday can no longer be used to set the time and the offset

> +  simultaneously.  If both of its two arguments are non-null, the

> call

> +  will fail (setting errno to EINVAL).

> +

> +  Callers attempting to set this offset should also be prepared for

> the call

> +  to fail and set errno to ENOSYS; this already happens on the Hurd

> and on

> +  some Linux architectures.  The Linux kernel maintainers are

> discussing a

> +  more principled replacement for the reused API.  After a

> replacement

> +  becomes available, we will change settimeofday to fail with ENOSYS

> on all

> +  platforms when its ‘tzp’ argument is not a null pointer.

> +

> +  Note that settimeofday itself is obsolescent according to POSIX.

> +  Programs that set the system time should use clock_settime and/or

> +  the adjtime family of functions instead.  We may also cease to make

> +  settimeofday available to newly linked binaries after there is a

> +  replacement for Linux’s time-zone-like offset API.

> +

>  Changes to build and runtime requirements:

>  

>    [Add changes to build and runtime requirements here]

> diff --git a/include/sys/time.h b/include/sys/time.h

> index 57208afa82..c0e30e70fb 100644

> --- a/include/sys/time.h

> +++ b/include/sys/time.h

> @@ -24,8 +24,7 @@ extern int __gettimeofday (struct timeval *__tv,

>  			   struct timezone *__tz);

>  libc_hidden_proto (__gettimeofday)

>  libc_hidden_proto (gettimeofday)

> -extern int __settimeofday (const struct timeval *__tv,

> -			   const struct timezone *__tz)

> +extern int __settimezone (const struct timezone *__tz)

>  	attribute_hidden;

>  extern int __adjtime (const struct timeval *__delta,

>  		      struct timeval *__olddelta);

> diff --git a/sysdeps/unix/clock_settime.c

> b/sysdeps/mach/hurd/clock_settime.c similarity index 65%

> rename from sysdeps/unix/clock_settime.c

> rename to sysdeps/mach/hurd/clock_settime.c

> index 18d7c99864..02239c097a 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,31 @@

>  

>  #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 (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)

> -    {

> -      __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)

> +    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/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

> fb2a36df19..914f5ac57b 100644 ---

> a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c +++

> b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c @@ -32,9 +32,19 @@

> attribute_compat_text_section __settimeofday_tv32 (const struct

> timeval32 *tv32, const struct timezone *tz) {

> -  struct timeval tv;

> -  tv32_to_tv64 (&tv, tv32);

> -  return __settimeofday (&tv, tz);

> +  if (__glibc_unlikely (tz != 0))

> +    {

> +      if (tv32 != 0)

> +	{

> +	  __set_errno (EINVAL);

> +	  return -1;

> +	}

> +      return __settimezone (tz);

> +    }

> +

> +  struct timespec ts;

> +  tv32_to_ts64 (&ts, tv32);


This can be replaced with valid_timeval_to_timespec64() from
include/time.h

> +  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/settimezone.c

> b/sysdeps/unix/sysv/linux/settimezone.c new file mode 100644 index

> 0000000000..90b38307c6 --- /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

> +}

> diff --git a/time/Makefile b/time/Makefile

> index ad8844ea34..6de4e418d9 100644

> --- a/time/Makefile

> +++ b/time/Makefile

> @@ -31,13 +31,13 @@ headers := time.h sys/time.h sys/timeb.h

> bits/time.h			\ 

>  routines := offtime asctime clock ctime ctime_r difftime \

>  	    gmtime localtime mktime time		 \

> -	    gettimeofday settimeofday adjtime tzset	 \

> -	    tzfile getitimer setitimer			 \

> +	    gettimeofday settimeofday settimezone	 \

> +	    adjtime tzset tzfile getitimer setitimer	 \

>  	    stime dysize timegm ftime			 \

>  	    getdate strptime strptime_l			 \

>  	    strftime wcsftime strftime_l wcsftime_l	 \

> -	    timespec_get 	 			 \

> -	    clock_getcpuclockid clock_getres 		 \

> +	    timespec_get				 \

> +	    clock_getcpuclockid clock_getres		 \

>  	    clock_gettime clock_settime clock_nanosleep

>  

>  aux :=	    era alt_digit lc-time-cleanup

> diff --git a/time/settimeofday.c b/time/settimeofday.c

> index 6aa4832d65..ad57ad41a1 100644

> --- a/time/settimeofday.c

> +++ b/time/settimeofday.c

> @@ -16,6 +16,7 @@

>     <https://www.gnu.org/licenses/>.  */

>  

>  #include <errno.h>

> +#include <time.h>

>  #include <sys/time.h>

>  

>  /* Set the current time of day and timezone information.

> @@ -23,9 +24,24 @@

>  int

>  __settimeofday (const struct timeval *tv, const struct timezone *tz)

>  {

> -  __set_errno (ENOSYS);

> -  return -1;

> +  if (__glibc_unlikely (tz != 0))

> +    {

> +      if (tv != 0)

> +	{

> +	  __set_errno (EINVAL);

> +	  return -1;

> +	}

> +      return __settimezone (tz);

> +    }

> +

> +  struct timespec ts;

> +  TIMEVAL_TO_TIMESPEC (tv, &ts);

> +  return __clock_settime (CLOCK_REALTIME, &ts);

>  }

> -stub_warning (settimeofday)

>  

> -weak_alias (__settimeofday, settimeofday)

> +#ifdef VERSION_settimeofday

> +weak_alias (__settimeofday, __settimeofday_w);

> +default_symbol_version (__settimeofday_w, settimeofday,

> VERSION_settimeofday); +#else

> +weak_alias (__settimeofday, settimeofday);

> +#endif

> diff --git a/sysdeps/mach/hurd/settimeofday.c b/time/settimezone.c

> similarity index 52%

> rename from sysdeps/mach/hurd/settimeofday.c

> rename to time/settimezone.c

> index 31bffcad9d..b9969c9dd5 100644

> --- a/sysdeps/mach/hurd/settimeofday.c

> +++ b/time/settimezone.c

> @@ -1,4 +1,4 @@

> -/* Copyright (C) 1991-2019 Free Software Foundation, Inc.

> +/* 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

> @@ -17,36 +17,12 @@

>  

>  #include <errno.h>

>  #include <sys/time.h>

> -#include <hurd.h>

> -#include <hurd/port.h>

>  

> -/* Set the current time of day and timezone information.

> +/* Set the system-wide timezone.

>     This call is restricted to the super-user.  */

>  int

> -__settimeofday (const struct timeval *tv, const struct timezone *tz)

> +__settimezone (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;

> +  __set_errno (ENOSYS);

> +  return -1;

>  }

> -

> -weak_alias (__settimeofday, settimeofday)


Reviewed-by: Lukasz Majewski <lukma@denx.de>



Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
Alistair Francis Oct. 25, 2019, 8:42 p.m. UTC | #2
On Fri, Oct 25, 2019 at 5:09 AM Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
>

> From: Zack Weinberg <zackw@panix.com>

>

> Use clock_settime to implement settimeofday.

>

> Changes from previous version:

>

>   - Added a NEWS entry.

>

> --

>

> 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>

> ---

>  NEWS                                          | 24 +++++++++

>  include/sys/time.h                            |  3 +-

>  sysdeps/{unix => mach/hurd}/clock_settime.c   | 51 ++++++++-----------

>  sysdeps/unix/syscalls.list                    |  1 -

>  .../unix/sysv/linux/alpha/osf_settimeofday.c  | 16 ++++--

>  sysdeps/unix/sysv/linux/alpha/settimeofday.c  | 22 ++++++++

>  sysdeps/unix/sysv/linux/alpha/syscalls.list   |  1 -

>  sysdeps/unix/sysv/linux/settimezone.c         | 36 +++++++++++++

>  time/Makefile                                 |  8 +--

>  time/settimeofday.c                           | 24 +++++++--

>  .../hurd/settimeofday.c => time/settimezone.c | 34 ++-----------

>  11 files changed, 147 insertions(+), 73 deletions(-)

>  rename sysdeps/{unix => mach/hurd}/clock_settime.c (65%)

>  create mode 100644 sysdeps/unix/sysv/linux/alpha/settimeofday.c

>  create mode 100644 sysdeps/unix/sysv/linux/settimezone.c

>  rename sysdeps/mach/hurd/settimeofday.c => time/settimezone.c (52%)

>

> diff --git a/NEWS b/NEWS

> index 8727b5e7f0..0b1476e745 100644

> --- a/NEWS

> +++ b/NEWS

> @@ -34,6 +34,30 @@ Deprecated and removed features, and other changes affecting compatibility:

>    binaries and it has been removed from <time.h> header.  This function

>    has been deprecated in favor of clock_settime.

>

> +* The settimeofday function can still be used to set a system-wide time

> +  zone when the operating system supports it.  This is because the Linux

> +  kernel reused the API, on some architectures, to describe a system-wide

> +  time-zone-like offset between the software clock maintained by the kernel,

> +  and the “RTC” clock that keeps time when the system is shut down.

> +

> +  However, to reduce the odds of this offset being set by accident,

> +  settimeofday can no longer be used to set the time and the offset

> +  simultaneously.  If both of its two arguments are non-null, the call

> +  will fail (setting errno to EINVAL).

> +

> +  Callers attempting to set this offset should also be prepared for the call

> +  to fail and set errno to ENOSYS; this already happens on the Hurd and on

> +  some Linux architectures.  The Linux kernel maintainers are discussing a

> +  more principled replacement for the reused API.  After a replacement

> +  becomes available, we will change settimeofday to fail with ENOSYS on all

> +  platforms when its ‘tzp’ argument is not a null pointer.

> +

> +  Note that settimeofday itself is obsolescent according to POSIX.

> +  Programs that set the system time should use clock_settime and/or

> +  the adjtime family of functions instead.  We may also cease to make

> +  settimeofday available to newly linked binaries after there is a

> +  replacement for Linux’s time-zone-like offset API.

> +

>  Changes to build and runtime requirements:

>

>    [Add changes to build and runtime requirements here]

> diff --git a/include/sys/time.h b/include/sys/time.h

> index 57208afa82..c0e30e70fb 100644

> --- a/include/sys/time.h

> +++ b/include/sys/time.h

> @@ -24,8 +24,7 @@ extern int __gettimeofday (struct timeval *__tv,

>                            struct timezone *__tz);

>  libc_hidden_proto (__gettimeofday)

>  libc_hidden_proto (gettimeofday)

> -extern int __settimeofday (const struct timeval *__tv,

> -                          const struct timezone *__tz)

> +extern int __settimezone (const struct timezone *__tz)

>         attribute_hidden;

>  extern int __adjtime (const struct timeval *__delta,

>                       struct timeval *__olddelta);

> diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/mach/hurd/clock_settime.c

> similarity index 65%

> rename from sysdeps/unix/clock_settime.c

> rename to sysdeps/mach/hurd/clock_settime.c

> index 18d7c99864..02239c097a 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,31 @@

>

>  #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 (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)

> -    {

> -      __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)

> +    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/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 fb2a36df19..914f5ac57b 100644

> --- a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c

> +++ b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c

> @@ -32,9 +32,19 @@ attribute_compat_text_section

>  __settimeofday_tv32 (const struct timeval32 *tv32,

>                       const struct timezone *tz)

>  {

> -  struct timeval tv;

> -  tv32_to_tv64 (&tv, tv32);

> -  return __settimeofday (&tv, tz);

> +  if (__glibc_unlikely (tz != 0))

> +    {

> +      if (tv32 != 0)

> +       {

> +         __set_errno (EINVAL);

> +         return -1;

> +       }

> +      return __settimezone (tz);

> +    }

> +

> +  struct timespec ts;

> +  tv32_to_ts64 (&ts, 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/settimezone.c b/sysdeps/unix/sysv/linux/settimezone.c

> new file mode 100644

> index 0000000000..90b38307c6

> --- /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


You are missing a semi-colon here.

Alistair

> +#endif

> +}

> diff --git a/time/Makefile b/time/Makefile

> index ad8844ea34..6de4e418d9 100644

> --- a/time/Makefile

> +++ b/time/Makefile

> @@ -31,13 +31,13 @@ headers := time.h sys/time.h sys/timeb.h bits/time.h                        \

>

>  routines := offtime asctime clock ctime ctime_r difftime \

>             gmtime localtime mktime time                 \

> -           gettimeofday settimeofday adjtime tzset      \

> -           tzfile getitimer setitimer                   \

> +           gettimeofday settimeofday settimezone        \

> +           adjtime tzset tzfile getitimer setitimer     \

>             stime dysize timegm ftime                    \

>             getdate strptime strptime_l                  \

>             strftime wcsftime strftime_l wcsftime_l      \

> -           timespec_get                                 \

> -           clock_getcpuclockid clock_getres             \

> +           timespec_get                                 \

> +           clock_getcpuclockid clock_getres             \

>             clock_gettime clock_settime clock_nanosleep

>

>  aux :=     era alt_digit lc-time-cleanup

> diff --git a/time/settimeofday.c b/time/settimeofday.c

> index 6aa4832d65..ad57ad41a1 100644

> --- a/time/settimeofday.c

> +++ b/time/settimeofday.c

> @@ -16,6 +16,7 @@

>     <https://www.gnu.org/licenses/>.  */

>

>  #include <errno.h>

> +#include <time.h>

>  #include <sys/time.h>

>

>  /* Set the current time of day and timezone information.

> @@ -23,9 +24,24 @@

>  int

>  __settimeofday (const struct timeval *tv, const struct timezone *tz)

>  {

> -  __set_errno (ENOSYS);

> -  return -1;

> +  if (__glibc_unlikely (tz != 0))

> +    {

> +      if (tv != 0)

> +       {

> +         __set_errno (EINVAL);

> +         return -1;

> +       }

> +      return __settimezone (tz);

> +    }

> +

> +  struct timespec ts;

> +  TIMEVAL_TO_TIMESPEC (tv, &ts);

> +  return __clock_settime (CLOCK_REALTIME, &ts);

>  }

> -stub_warning (settimeofday)

>

> -weak_alias (__settimeofday, settimeofday)

> +#ifdef VERSION_settimeofday

> +weak_alias (__settimeofday, __settimeofday_w);

> +default_symbol_version (__settimeofday_w, settimeofday, VERSION_settimeofday);

> +#else

> +weak_alias (__settimeofday, settimeofday);

> +#endif

> diff --git a/sysdeps/mach/hurd/settimeofday.c b/time/settimezone.c

> similarity index 52%

> rename from sysdeps/mach/hurd/settimeofday.c

> rename to time/settimezone.c

> index 31bffcad9d..b9969c9dd5 100644

> --- a/sysdeps/mach/hurd/settimeofday.c

> +++ b/time/settimezone.c

> @@ -1,4 +1,4 @@

> -/* Copyright (C) 1991-2019 Free Software Foundation, Inc.

> +/* 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

> @@ -17,36 +17,12 @@

>

>  #include <errno.h>

>  #include <sys/time.h>

> -#include <hurd.h>

> -#include <hurd/port.h>

>

> -/* Set the current time of day and timezone information.

> +/* Set the system-wide timezone.

>     This call is restricted to the super-user.  */

>  int

> -__settimeofday (const struct timeval *tv, const struct timezone *tz)

> +__settimezone (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;

> +  __set_errno (ENOSYS);

> +  return -1;

>  }

> -

> -weak_alias (__settimeofday, settimeofday)

> --

> 2.17.1

>
Rafal Luzynski Oct. 25, 2019, 11:20 p.m. UTC | #3
25.10.2019 14:08 Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote:
> 

> 

> From: Zack Weinberg <zackw@panix.com>

> 

> Use clock_settime to implement settimeofday.

> 

> Changes from previous version:

> 

>   - Added a NEWS entry.

> 

> --

> 

> [...]

> diff --git a/NEWS b/NEWS

> index 8727b5e7f0..0b1476e745 100644

> --- a/NEWS

> +++ b/NEWS

> @@ -34,6 +34,30 @@ Deprecated and removed features, and other changes

> affecting compatibility:

>    binaries and it has been removed from <time.h> header.  This function

>    has been deprecated in favor of clock_settime.

>  

> +* The settimeofday function can still be used to set a system-wide time

> +  zone when the operating system supports it.  This is because the Linux

> +  kernel reused the API, on some architectures, to describe a system-wide

> +  time-zone-like offset between the software clock maintained by the

> kernel,

> +  and the “RTC” clock that keeps time when the system is shut down.


That's little off-topic and little nit-picky but are you sure you want to
use the Unicode quotes like “” instead of plain ASCII "" ?  No problem if
this is what you really want but I suspect your editor converted this.

> +  However, to reduce the odds of this offset being set by accident,

> +  settimeofday can no longer be used to set the time and the offset

> +  simultaneously.  If both of its two arguments are non-null, the call

> +  will fail (setting errno to EINVAL).

> +

> +  Callers attempting to set this offset should also be prepared for the

> call

> +  to fail and set errno to ENOSYS; this already happens on the Hurd and

> on

> +  some Linux architectures.  The Linux kernel maintainers are discussing

> a

> +  more principled replacement for the reused API.  After a replacement

> +  becomes available, we will change settimeofday to fail with ENOSYS on

> all

> +  platforms when its ‘tzp’ argument is not a null pointer.


Same here, the Unicode ‘’ instead of plain ASCII '' .

> +  Note that settimeofday itself is obsolescent according to POSIX.

> +  Programs that set the system time should use clock_settime and/or

> +  the adjtime family of functions instead.  We may also cease to make

> +  settimeofday available to newly linked binaries after there is a

> +  replacement for Linux’s time-zone-like offset API.


Again the Unicode apostrophe ’ instead of plain ASCII ' .

Regards,

Rafal
Adhemerval Zanella Oct. 28, 2019, 6:27 p.m. UTC | #4
On 25/10/2019 12:28, Lukasz Majewski wrote:
> On Fri, 25 Oct 2019 09:08:25 -0300

> Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote:

> 

>> From: Zack Weinberg <zackw@panix.com>

>>

[...]
>> fb2a36df19..914f5ac57b 100644 ---

>> a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c +++

>> b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c @@ -32,9 +32,19 @@

>> attribute_compat_text_section __settimeofday_tv32 (const struct

>> timeval32 *tv32, const struct timezone *tz) {

>> -  struct timeval tv;

>> -  tv32_to_tv64 (&tv, tv32);

>> -  return __settimeofday (&tv, tz);

>> +  if (__glibc_unlikely (tz != 0))

>> +    {

>> +      if (tv32 != 0)

>> +	{

>> +	  __set_errno (EINVAL);

>> +	  return -1;

>> +	}

>> +      return __settimezone (tz);

>> +    }

>> +

>> +  struct timespec ts;

>> +  tv32_to_ts64 (&ts, tv32);

> 

> This can be replaced with valid_timeval_to_timespec64() from

> include/time.h


Not really, the timeval32 is alpha-specific.
Adhemerval Zanella Oct. 28, 2019, 6:29 p.m. UTC | #5
On 25/10/2019 17:42, Alistair Francis wrote:
> On Fri, Oct 25, 2019 at 5:09 AM Adhemerval Zanella

> <adhemerval.zanella@linaro.org> wrote:

>>

>> From: Zack Weinberg <zackw@panix.com>


[...]

>> +

>> +/* 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

> 

> You are missing a semi-colon here.

> 

> Alistair


Ack, fixed.
Adhemerval Zanella Oct. 28, 2019, 6:46 p.m. UTC | #6
On 25/10/2019 20:20, Rafal Luzynski wrote:
> 25.10.2019 14:08 Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote:

>>

>>

>> From: Zack Weinberg <zackw@panix.com>

>>

>> Use clock_settime to implement settimeofday.

>>

>> Changes from previous version:

>>

>>   - Added a NEWS entry.

>>

>> --

>>

>> [...]

>> diff --git a/NEWS b/NEWS

>> index 8727b5e7f0..0b1476e745 100644

>> --- a/NEWS

>> +++ b/NEWS

>> @@ -34,6 +34,30 @@ Deprecated and removed features, and other changes

>> affecting compatibility:

>>    binaries and it has been removed from <time.h> header.  This function

>>    has been deprecated in favor of clock_settime.

>>  

>> +* The settimeofday function can still be used to set a system-wide time

>> +  zone when the operating system supports it.  This is because the Linux

>> +  kernel reused the API, on some architectures, to describe a system-wide

>> +  time-zone-like offset between the software clock maintained by the

>> kernel,

>> +  and the “RTC” clock that keeps time when the system is shut down.

> 

> That's little off-topic and little nit-picky but are you sure you want to

> use the Unicode quotes like “” instead of plain ASCII "" ?  No problem if

> this is what you really want but I suspect your editor converted this.


I think this came from the original patchset from Zack, I have split 
the last commit that added the NEWS entry for all the changes.
I changed to plan ASCII version.

> 

>> +  However, to reduce the odds of this offset being set by accident,

>> +  settimeofday can no longer be used to set the time and the offset

>> +  simultaneously.  If both of its two arguments are non-null, the call

>> +  will fail (setting errno to EINVAL).

>> +

>> +  Callers attempting to set this offset should also be prepared for the

>> call

>> +  to fail and set errno to ENOSYS; this already happens on the Hurd and

>> on

>> +  some Linux architectures.  The Linux kernel maintainers are discussing

>> a

>> +  more principled replacement for the reused API.  After a replacement

>> +  becomes available, we will change settimeofday to fail with ENOSYS on

>> all

>> +  platforms when its ‘tzp’ argument is not a null pointer.

> 

> Same here, the Unicode ‘’ instead of plain ASCII '' .


Ack, fixed.

> 

>> +  Note that settimeofday itself is obsolescent according to POSIX.

>> +  Programs that set the system time should use clock_settime and/or

>> +  the adjtime family of functions instead.  We may also cease to make

>> +  settimeofday available to newly linked binaries after there is a

>> +  replacement for Linux’s time-zone-like offset API.

> 

> Again the Unicode apostrophe ’ instead of plain ASCII ' .


Ack, fixed.

> 

> Regards,

> 

> Rafal

>
diff mbox series

Patch

diff --git a/NEWS b/NEWS
index 8727b5e7f0..0b1476e745 100644
--- a/NEWS
+++ b/NEWS
@@ -34,6 +34,30 @@  Deprecated and removed features, and other changes affecting compatibility:
   binaries and it has been removed from <time.h> header.  This function
   has been deprecated in favor of clock_settime.
 
+* The settimeofday function can still be used to set a system-wide time
+  zone when the operating system supports it.  This is because the Linux
+  kernel reused the API, on some architectures, to describe a system-wide
+  time-zone-like offset between the software clock maintained by the kernel,
+  and the “RTC” clock that keeps time when the system is shut down.
+
+  However, to reduce the odds of this offset being set by accident,
+  settimeofday can no longer be used to set the time and the offset
+  simultaneously.  If both of its two arguments are non-null, the call
+  will fail (setting errno to EINVAL).
+
+  Callers attempting to set this offset should also be prepared for the call
+  to fail and set errno to ENOSYS; this already happens on the Hurd and on
+  some Linux architectures.  The Linux kernel maintainers are discussing a
+  more principled replacement for the reused API.  After a replacement
+  becomes available, we will change settimeofday to fail with ENOSYS on all
+  platforms when its ‘tzp’ argument is not a null pointer.
+
+  Note that settimeofday itself is obsolescent according to POSIX.
+  Programs that set the system time should use clock_settime and/or
+  the adjtime family of functions instead.  We may also cease to make
+  settimeofday available to newly linked binaries after there is a
+  replacement for Linux’s time-zone-like offset API.
+
 Changes to build and runtime requirements:
 
   [Add changes to build and runtime requirements here]
diff --git a/include/sys/time.h b/include/sys/time.h
index 57208afa82..c0e30e70fb 100644
--- a/include/sys/time.h
+++ b/include/sys/time.h
@@ -24,8 +24,7 @@  extern int __gettimeofday (struct timeval *__tv,
 			   struct timezone *__tz);
 libc_hidden_proto (__gettimeofday)
 libc_hidden_proto (gettimeofday)
-extern int __settimeofday (const struct timeval *__tv,
-			   const struct timezone *__tz)
+extern int __settimezone (const struct timezone *__tz)
 	attribute_hidden;
 extern int __adjtime (const struct timeval *__delta,
 		      struct timeval *__olddelta);
diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/mach/hurd/clock_settime.c
similarity index 65%
rename from sysdeps/unix/clock_settime.c
rename to sysdeps/mach/hurd/clock_settime.c
index 18d7c99864..02239c097a 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,31 @@ 
 
 #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 (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000)
-    {
-      __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)
+    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/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 fb2a36df19..914f5ac57b 100644
--- a/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
+++ b/sysdeps/unix/sysv/linux/alpha/osf_settimeofday.c
@@ -32,9 +32,19 @@  attribute_compat_text_section
 __settimeofday_tv32 (const struct timeval32 *tv32,
                      const struct timezone *tz)
 {
-  struct timeval tv;
-  tv32_to_tv64 (&tv, tv32);
-  return __settimeofday (&tv, tz);
+  if (__glibc_unlikely (tz != 0))
+    {
+      if (tv32 != 0)
+	{
+	  __set_errno (EINVAL);
+	  return -1;
+	}
+      return __settimezone (tz);
+    }
+
+  struct timespec ts;
+  tv32_to_ts64 (&ts, 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/settimezone.c b/sysdeps/unix/sysv/linux/settimezone.c
new file mode 100644
index 0000000000..90b38307c6
--- /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
+}
diff --git a/time/Makefile b/time/Makefile
index ad8844ea34..6de4e418d9 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -31,13 +31,13 @@  headers := time.h sys/time.h sys/timeb.h bits/time.h			\
 
 routines := offtime asctime clock ctime ctime_r difftime \
 	    gmtime localtime mktime time		 \
-	    gettimeofday settimeofday adjtime tzset	 \
-	    tzfile getitimer setitimer			 \
+	    gettimeofday settimeofday settimezone	 \
+	    adjtime tzset tzfile getitimer setitimer	 \
 	    stime dysize timegm ftime			 \
 	    getdate strptime strptime_l			 \
 	    strftime wcsftime strftime_l wcsftime_l	 \
-	    timespec_get 	 			 \
-	    clock_getcpuclockid clock_getres 		 \
+	    timespec_get				 \
+	    clock_getcpuclockid clock_getres		 \
 	    clock_gettime clock_settime clock_nanosleep
 
 aux :=	    era alt_digit lc-time-cleanup
diff --git a/time/settimeofday.c b/time/settimeofday.c
index 6aa4832d65..ad57ad41a1 100644
--- a/time/settimeofday.c
+++ b/time/settimeofday.c
@@ -16,6 +16,7 @@ 
    <https://www.gnu.org/licenses/>.  */
 
 #include <errno.h>
+#include <time.h>
 #include <sys/time.h>
 
 /* Set the current time of day and timezone information.
@@ -23,9 +24,24 @@ 
 int
 __settimeofday (const struct timeval *tv, const struct timezone *tz)
 {
-  __set_errno (ENOSYS);
-  return -1;
+  if (__glibc_unlikely (tz != 0))
+    {
+      if (tv != 0)
+	{
+	  __set_errno (EINVAL);
+	  return -1;
+	}
+      return __settimezone (tz);
+    }
+
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (tv, &ts);
+  return __clock_settime (CLOCK_REALTIME, &ts);
 }
-stub_warning (settimeofday)
 
-weak_alias (__settimeofday, settimeofday)
+#ifdef VERSION_settimeofday
+weak_alias (__settimeofday, __settimeofday_w);
+default_symbol_version (__settimeofday_w, settimeofday, VERSION_settimeofday);
+#else
+weak_alias (__settimeofday, settimeofday);
+#endif
diff --git a/sysdeps/mach/hurd/settimeofday.c b/time/settimezone.c
similarity index 52%
rename from sysdeps/mach/hurd/settimeofday.c
rename to time/settimezone.c
index 31bffcad9d..b9969c9dd5 100644
--- a/sysdeps/mach/hurd/settimeofday.c
+++ b/time/settimezone.c
@@ -1,4 +1,4 @@ 
-/* Copyright (C) 1991-2019 Free Software Foundation, Inc.
+/* 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
@@ -17,36 +17,12 @@ 
 
 #include <errno.h>
 #include <sys/time.h>
-#include <hurd.h>
-#include <hurd/port.h>
 
-/* Set the current time of day and timezone information.
+/* Set the system-wide timezone.
    This call is restricted to the super-user.  */
 int
-__settimeofday (const struct timeval *tv, const struct timezone *tz)
+__settimezone (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;
+  __set_errno (ENOSYS);
+  return -1;
 }
-
-weak_alias (__settimeofday, settimeofday)