1  /* Send a message to a message queue with a timeout.  Linux version.
       2     Copyright (C) 2017-2023 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
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the 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; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <mqueue.h>
      20  #include <sysdep-cancel.h>
      21  #include <shlib-compat.h>
      22  
      23  /* Add message pointed by MSG_PTR to message queue MQDES, stop blocking
      24     on full message queue if ABS_TIMEOUT expires.  */
      25  int
      26  ___mq_timedsend_time64 (mqd_t mqdes, const char *msg_ptr, size_t msg_len,
      27  			unsigned int msg_prio,
      28  			const struct __timespec64 *abs_timeout)
      29  {
      30  # ifndef __NR_mq_timedsend_time64
      31  #  define __NR_mq_timedsend_time64 __NR_mq_timedsend
      32  # endif
      33  
      34  #ifdef __ASSUME_TIME64_SYSCALLS
      35    return SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr, msg_len,
      36  			 msg_prio, abs_timeout);
      37  #else
      38    bool need_time64 = abs_timeout != NULL
      39  		     && !in_int32_t_range (abs_timeout->tv_sec);
      40    if (need_time64)
      41      {
      42        int r = SYSCALL_CANCEL (mq_timedsend_time64, mqdes, msg_ptr, msg_len,
      43  			      msg_prio, abs_timeout);
      44        if (r == 0 || errno != ENOSYS)
      45  	return r;
      46        __set_errno (EOVERFLOW);
      47        return -1;
      48      }
      49  
      50    struct timespec ts32, *pts32 = NULL;
      51    if (abs_timeout != NULL)
      52      {
      53        ts32 = valid_timespec64_to_timespec (*abs_timeout);
      54        pts32 = &ts32;
      55      }
      56  
      57    return SYSCALL_CANCEL (mq_timedsend, mqdes, msg_ptr, msg_len, msg_prio,
      58  			 pts32);
      59  #endif
      60  }
      61  
      62  #if __TIMESIZE == 64
      63  versioned_symbol (libc, ___mq_timedsend_time64, mq_timedsend, GLIBC_2_34);
      64  libc_hidden_ver (___mq_timedsend_time64, __mq_timedsend)
      65  # ifndef SHARED
      66  strong_alias (___mq_timedsend_time64, __mq_timedsend)
      67  # endif
      68  # if OTHER_SHLIB_COMPAT (librt, GLIBC_2_3_4, GLIBC_2_34)
      69  compat_symbol (librt, ___mq_timedsend_time64, mq_timedsend, GLIBC_2_3_4);
      70  # endif
      71  
      72  #else /* __TIMESIZE != 64 */
      73  libc_hidden_ver (___mq_timedsend_time64, __mq_timedsend_time64)
      74  versioned_symbol (libc, ___mq_timedsend_time64, __mq_timedsend_time64,
      75  		  GLIBC_2_34);
      76  
      77  int
      78  ___mq_timedsend (mqd_t mqdes, const char *msg_ptr, size_t msg_len,
      79                  unsigned int msg_prio, const struct timespec *abs_timeout)
      80  {
      81    struct __timespec64 ts64;
      82    if (abs_timeout != NULL)
      83      ts64 = valid_timespec_to_timespec64 (*abs_timeout);
      84  
      85    return __mq_timedsend_time64 (mqdes, msg_ptr, msg_len, msg_prio,
      86                                  abs_timeout != NULL ? &ts64 : NULL);
      87  }
      88  versioned_symbol (libc, ___mq_timedsend, mq_timedsend, GLIBC_2_34);
      89  libc_hidden_ver (___mq_timedsend, __mq_timedsend)
      90  # ifndef SHARED
      91  strong_alias (___mq_timedsend, __mq_timedsend)
      92  # endif
      93  # if OTHER_SHLIB_COMPAT (librt, GLIBC_2_3_4, GLIBC_2_34)
      94  compat_symbol (librt, ___mq_timedsend, mq_timedsend, GLIBC_2_3_4);
      95  # endif
      96  
      97  #endif /* __TIMESIZE != 64 */