1  /* Copyright (C) 2006-2023 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
      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
      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_int32_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
      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