1  /* timerfd_settime -- start or stop the timer referred to by file descriptor.
       2     Copyright (C) 2020-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; see the file COPYING.LIB.  If
      17     not, see <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <stdlib.h>
      21  #include <time.h>
      22  #include <sysdep.h>
      23  #include <kernel-features.h>
      24  
      25  int
      26  __timerfd_settime64 (int fd, int flags, const struct __itimerspec64 *value,
      27                       struct __itimerspec64 *ovalue)
      28  {
      29  #ifndef __NR_timerfd_settime64
      30  # define __NR_timerfd_settime64 __NR_timerfd_settime
      31  #endif
      32  
      33  #ifdef __ASSUME_TIME64_SYSCALLS
      34    return INLINE_SYSCALL_CALL (timerfd_settime64, fd, flags, value, ovalue);
      35  #else
      36    bool need_time64 = !in_int32_t_range (value->it_value.tv_sec)
      37  		     || !in_int32_t_range (value->it_interval.tv_sec);
      38    if (need_time64)
      39      {
      40        int r = INLINE_SYSCALL_CALL (timerfd_settime64, fd, flags, value,
      41  				   ovalue);
      42        if (r == 0 || errno != ENOSYS)
      43  	return r;
      44        __set_errno (EOVERFLOW);
      45        return r;
      46      }
      47  
      48    struct itimerspec its32, oits32;
      49    its32.it_interval = valid_timespec64_to_timespec (value->it_interval);
      50    its32.it_value = valid_timespec64_to_timespec (value->it_value);
      51    int ret = INLINE_SYSCALL_CALL (timerfd_settime, fd, flags,
      52  				 &its32, ovalue != NULL ? &oits32 : NULL);
      53    if (ret == 0 && ovalue != NULL)
      54      {
      55        ovalue->it_interval = valid_timespec_to_timespec64 (oits32.it_interval);
      56        ovalue->it_value = valid_timespec_to_timespec64 (oits32.it_value);
      57      }
      58    return ret;
      59  #endif
      60  }
      61  
      62  #if __TIMESIZE != 64
      63  libc_hidden_def (__timerfd_settime64)
      64  
      65  int
      66  __timerfd_settime (int fd, int flags, const struct itimerspec *value,
      67                     struct itimerspec *ovalue)
      68  {
      69    struct __itimerspec64 its64, oits64;
      70    int retval;
      71  
      72    its64.it_interval = valid_timespec_to_timespec64 (value->it_interval);
      73    its64.it_value = valid_timespec_to_timespec64 (value->it_value);
      74  
      75    retval = __timerfd_settime64 (fd, flags, &its64, ovalue ? &oits64 : NULL);
      76    if (retval == 0 && ovalue)
      77      {
      78        ovalue->it_interval = valid_timespec64_to_timespec (oits64.it_interval);
      79        ovalue->it_value = valid_timespec64_to_timespec (oits64.it_value);
      80      }
      81  
      82    return retval;
      83  }
      84  #endif
      85  strong_alias (__timerfd_settime, timerfd_settime)