1 /* timerfd_settime -- start or stop the timer referred to by file descriptor.
2    Copyright (C) 2020-2021 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
__timerfd_settime64(int fd,int flags,const struct __itimerspec64 * value,struct __itimerspec64 * ovalue)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_time_t_range (value->it_value.tv_sec)
37 		     || !in_time_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
libc_hidden_def(__timerfd_settime64)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)
86