1 /* Copyright (C) 2006-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <errno.h>
19 #include <signal.h>
20 #include <time.h>
21 #include <sys/poll.h>
22 #include <sysdep-cancel.h>
23 
24 int
__ppoll64(struct pollfd * fds,nfds_t nfds,const struct __timespec64 * timeout,const sigset_t * sigmask)25 __ppoll64 (struct pollfd *fds, nfds_t nfds, const struct __timespec64 *timeout,
26            const sigset_t *sigmask)
27 {
28   /* The Linux kernel can in some situations update the timeout value.
29      We do not want that so use a local variable.  */
30   struct __timespec64 tval;
31   if (timeout != NULL)
32     {
33       tval = *timeout;
34       timeout = &tval;
35     }
36 
37 #ifndef __NR_ppoll_time64
38 # define __NR_ppoll_time64 __NR_ppoll
39 #endif
40 
41 #ifdef __ASSUME_TIME64_SYSCALLS
42   return SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
43 			 __NSIG_BYTES);
44 #else
45   int ret;
46   bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
47   if (need_time64)
48     {
49       ret = SYSCALL_CANCEL (ppoll_time64, fds, nfds, timeout, sigmask,
50 			    __NSIG_BYTES);
51       if (ret == 0 || errno != ENOSYS)
52 	return ret;
53       __set_errno (EOVERFLOW);
54       return -1;
55     }
56 
57   struct timespec ts32;
58   if (timeout != NULL)
59     ts32 = valid_timespec64_to_timespec (*timeout);
60 
61   return SYSCALL_CANCEL (ppoll, fds, nfds, timeout ? &ts32 : NULL, sigmask,
62 			 __NSIG_BYTES);
63 #endif
64 }
65 
66 #if __TIMESIZE != 64
libc_hidden_def(__ppoll64)67 libc_hidden_def (__ppoll64)
68 
69 int
70 __ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
71          const sigset_t *sigmask)
72 {
73   struct __timespec64 ts64;
74   if (timeout)
75     ts64 = valid_timespec_to_timespec64 (*timeout);
76 
77   return __ppoll64 (fds, nfds, timeout ? &ts64 : NULL, sigmask);
78 }
79 #endif
80 strong_alias (__ppoll, ppoll)
81 libc_hidden_def (ppoll)
82