(root)/
glibc-2.38/
misc/
tst-preadvwritev-common.c
       1  /* Common definitions for preadv and pwritev.
       2     Copyright (C) 2016-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 <array_length.h>
      20  #include <stdbool.h>
      21  #include <stdio.h>
      22  #include <stdint.h>
      23  #include <errno.h>
      24  #include <string.h>
      25  #include <sys/uio.h>
      26  #include <sys/stat.h>
      27  
      28  #include <support/check.h>
      29  #include <support/temp_file.h>
      30  #include <support/support.h>
      31  #include <support/xunistd.h>
      32  
      33  static char *temp_filename;
      34  static int temp_fd;
      35  static bool temp_fd_supports_holes;
      36  
      37  static int do_test (void);
      38  
      39  static void
      40  do_prepare (int argc, char **argv)
      41  {
      42    temp_fd = create_temp_file ("tst-preadvwritev.", &temp_filename);
      43    if (temp_fd == -1)
      44      FAIL_EXIT1 ("cannot create temporary file");
      45    temp_fd_supports_holes = support_descriptor_supports_holes (temp_fd);
      46  }
      47  #define PREPARE do_prepare
      48  
      49  #ifndef PREADV
      50  # define PREADV(__fd, __iov, __iovcnt, __offset) \
      51    preadv (__fd, __iov, __iovcnt, __offset)
      52  #endif
      53  
      54  #ifndef PWRITEV
      55  # define PWRITEV(__fd, __iov, __iovcnt, __offset) \
      56    pwritev (__fd, __iov, __iovcnt, __offset)
      57  #endif
      58  
      59  static __attribute__ ((unused)) void
      60  do_test_without_offset (void)
      61  {
      62    xftruncate (temp_fd, 0);
      63  
      64    xwrite (temp_fd, "123", 3);
      65    xlseek (temp_fd, 2, SEEK_SET);
      66    {
      67      struct iovec iov[] =
      68        {
      69          { (void *) "abc", 3 },
      70          { (void *) "xyzt", 4 },
      71        };
      72      TEST_COMPARE (PWRITEV (temp_fd, iov, array_length (iov), -1), 7);
      73    }
      74    TEST_COMPARE (xlseek (temp_fd, 0, SEEK_CUR), 9);
      75  
      76    xlseek (temp_fd, 1, SEEK_SET);
      77    char buf1[3];
      78    char buf2[2];
      79    {
      80      struct iovec iov[] =
      81        {
      82          { buf1, sizeof (buf1) },
      83          { buf2, sizeof (buf2) },
      84        };
      85      TEST_COMPARE (PREADV (temp_fd, iov, array_length (iov), -1),
      86                    sizeof (buf1) + sizeof (buf2));
      87      TEST_COMPARE (memcmp ("2ab", buf1, sizeof (buf1)), 0);
      88      TEST_COMPARE (memcmp ("cx", buf2, sizeof (buf2)), 0);
      89      TEST_COMPARE (xlseek (temp_fd, 0, SEEK_CUR), 6);
      90    }
      91  
      92    xftruncate (temp_fd, 0);
      93  }
      94  
      95  static int
      96  do_test_with_offset (off_t offset)
      97  {
      98    struct iovec iov[2];
      99    ssize_t ret;
     100  
     101    char buf1[32];
     102    char buf2[64];
     103  
     104    memset (buf1, 0xf0, sizeof buf1);
     105    memset (buf2, 0x0f, sizeof buf2);
     106  
     107    /* Write two buffer with 32 and 64 bytes respectively.  */
     108    memset (iov, 0, sizeof iov);
     109    iov[0].iov_base = buf1;
     110    iov[0].iov_len = sizeof buf1;
     111    iov[1].iov_base = buf2;
     112    iov[1].iov_len = sizeof buf2;
     113  
     114    ret = PWRITEV (temp_fd, iov, 2, offset);
     115    if (ret == -1)
     116      FAIL_RET ("first pwritev returned -1");
     117    if (ret != (sizeof buf1 + sizeof buf2))
     118      FAIL_RET ("first pwritev returned an unexpected value");
     119  
     120    ret = PWRITEV (temp_fd, iov, 2, sizeof buf1 + sizeof buf2 + offset);
     121    if (ret == -1)
     122      FAIL_RET ("second pwritev returned -1");
     123    if (ret != (sizeof buf1 + sizeof buf2))
     124      FAIL_RET ("second pwritev returned an unexpected value");
     125  
     126    char buf3[32];
     127    char buf4[64];
     128  
     129    memset (buf3, 0x0f, sizeof buf3);
     130    memset (buf4, 0xf0, sizeof buf4);
     131  
     132    iov[0].iov_base = buf3;
     133    iov[0].iov_len = sizeof buf3;
     134    iov[1].iov_base = buf4;
     135    iov[1].iov_len = sizeof buf4;
     136  
     137    /* Now read two buffer with 32 and 64 bytes respectively.  */
     138    ret = PREADV (temp_fd, iov, 2, offset);
     139    if (ret == -1)
     140      FAIL_RET ("first preadv returned -1");
     141    if (ret != (sizeof buf3 + sizeof buf4))
     142      FAIL_RET ("first preadv returned an unexpected value");
     143  
     144    if (memcmp (buf1, buf3, sizeof buf1) != 0)
     145      FAIL_RET ("first buffer from first preadv different than expected");
     146    if (memcmp (buf2, buf4, sizeof buf2) != 0)
     147      FAIL_RET ("second buffer from first preadv different than expected");
     148  
     149    ret = PREADV (temp_fd, iov, 2, sizeof buf3 + sizeof buf4 + offset);
     150    if (ret == -1)
     151      FAIL_RET ("second preadv returned -1");
     152    if (ret != (sizeof buf3 + sizeof buf4))
     153      FAIL_RET ("second preadv returned an unexpected value");
     154  
     155    /* And compare the buffers read and written to check if there are equal.  */
     156    if (memcmp (buf1, buf3, sizeof buf1) != 0)
     157      FAIL_RET ("first buffer from second preadv different than expected");
     158    if (memcmp (buf2, buf4, sizeof buf2) != 0)
     159      FAIL_RET ("second buffer from second preadv different than expected");
     160  
     161    return 0;
     162  }
     163  
     164  #include <support/test-driver.c>