(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
recvmmsg.c
       1  /* Copyright (C) 2010-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/socket.h>
      19  #include <sysdep.h>
      20  #include <socketcall.h>
      21  
      22  static int
      23  recvmmsg_syscall (int fd, struct mmsghdr *vmessages, unsigned int vlen,
      24  		  int flags, struct __timespec64 *timeout)
      25  {
      26  #ifndef __NR_recvmmsg_time64
      27  # define __NR_recvmmsg_time64 __NR_recvmmsg
      28  #endif
      29    int r = SYSCALL_CANCEL (recvmmsg_time64, fd, vmessages, vlen, flags,
      30  			  timeout);
      31  #ifndef __ASSUME_TIME64_SYSCALLS
      32    if (r >= 0 || errno != ENOSYS)
      33      return r;
      34  
      35    struct timespec ts32, *pts32 = NULL;
      36    if (timeout != NULL)
      37      {
      38        if (! in_int32_t_range (timeout->tv_sec))
      39  	{
      40  	  __set_errno (EINVAL);
      41  	  return -1;
      42  	}
      43        ts32 = valid_timespec64_to_timespec (*timeout);
      44        pts32 = &ts32;
      45      }
      46  
      47  # ifdef __ASSUME_RECVMMSG_SYSCALL
      48    r = SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, pts32);
      49  # else
      50    r = SOCKETCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, pts32);
      51  # endif
      52    if (r >= 0)
      53      {
      54        if (timeout != NULL)
      55          *timeout = valid_timespec_to_timespec64 (ts32);
      56      }
      57  #endif
      58    return r;
      59  }
      60  
      61  int
      62  __recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
      63  	      struct __timespec64 *timeout)
      64  {
      65  #if __TIMESIZE != 64
      66    socklen_t csize[IOV_MAX];
      67    if (vlen > IOV_MAX)
      68      vlen = IOV_MAX;
      69    for (int i = 0; i < vlen; i++)
      70      csize[i] = vmessages[i].msg_hdr.msg_controllen;
      71  #endif
      72  
      73    int r = recvmmsg_syscall (fd, vmessages, vlen, flags, timeout);
      74  #if __TIMESIZE != 64
      75    if (r > 0)
      76      {
      77        for (int i=0; i < r; i++)
      78          __convert_scm_timestamps (&vmessages[i].msg_hdr, csize[i]);
      79      }
      80  #endif
      81    return r;
      82  }
      83  #if __TIMESIZE != 64
      84  libc_hidden_def (__recvmmsg64)
      85  
      86  int
      87  __recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
      88  	    struct timespec *timeout)
      89  {
      90    struct __timespec64 ts64, *pts64 = NULL;
      91    if (timeout != NULL)
      92      {
      93        ts64 = valid_timespec_to_timespec64 (*timeout);
      94        pts64 = &ts64;
      95      }
      96    int r = recvmmsg_syscall (fd, vmessages, vlen, flags, pts64);
      97    if (r >= 0 && timeout != NULL)
      98      /* The remanining timeout will be always less the input TIMEOUT.  */
      99      *timeout = valid_timespec64_to_timespec (ts64);
     100    return r;
     101  }
     102  #endif
     103  weak_alias (__recvmmsg, recvmmsg)