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 <sys/select.h>
19 #include <sysdep-cancel.h>
20 
21 static int
pselect64_syscall(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,const struct __timespec64 * timeout,const sigset_t * sigmask)22 pselect64_syscall (int nfds, fd_set *readfds, fd_set *writefds,
23 		   fd_set *exceptfds, const struct __timespec64 *timeout,
24 		   const sigset_t *sigmask)
25 {
26 #ifndef __NR_pselect6_time64
27 # define __NR_pselect6_time64 __NR_pselect6
28 #endif
29   /* NB: This is required by ARGIFY used in x32 internal_syscallN.  */
30   __syscall_ulong_t data[2] =
31     {
32       (uintptr_t) sigmask, __NSIG_BYTES
33     };
34   return SYSCALL_CANCEL (pselect6_time64, nfds, readfds, writefds, exceptfds,
35 			 timeout, data);
36 }
37 
38 int
__pselect64(int nfds,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,const struct __timespec64 * timeout,const sigset_t * sigmask)39 __pselect64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
40 	     const struct __timespec64 *timeout, const sigset_t *sigmask)
41 {
42   /* The Linux kernel can in some situations update the timeout value.
43      We do not want that so use a local variable.  */
44   struct __timespec64 tval;
45   if (timeout != NULL)
46     {
47       tval = *timeout;
48       timeout = &tval;
49     }
50 
51   /* Note: the system call expects 7 values but on most architectures
52      we can only pass in 6 directly.  If there is an architecture with
53      support for more parameters a new version of this file needs to
54      be created.  */
55 #ifdef __ASSUME_TIME64_SYSCALLS
56   return pselect64_syscall (nfds, readfds, writefds, exceptfds, timeout,
57 			    sigmask);
58 #else
59   bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
60   if (need_time64)
61     {
62       int r = pselect64_syscall (nfds, readfds, writefds, exceptfds, timeout,
63 				 sigmask);
64       if (r == 0 || errno != ENOSYS)
65 	return r;
66       __set_errno (EOVERFLOW);
67       return -1;
68     }
69 
70   return __pselect32 (nfds, readfds, writefds, exceptfds, timeout, sigmask);
71 #endif
72 }
73 
74 #if __TIMESIZE != 64
libc_hidden_def(__pselect64)75 libc_hidden_def (__pselect64)
76 
77 int
78 __pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
79 	   const struct timespec *timeout, const sigset_t *sigmask)
80 {
81   struct __timespec64 ts64, *pts64 = NULL;
82   if (timeout != NULL)
83     {
84       ts64 = valid_timespec_to_timespec64 (*timeout);
85       pts64 = &ts64;
86     }
87   return __pselect64 (nfds, readfds, writefds, exceptfds, pts64, sigmask);
88 }
89 #endif
90 
91 #ifndef __pselect
92 weak_alias (__pselect, pselect)
93 #endif
94