(root)/
strace-6.5/
tests-mx32/
preadv-pwritev.c
       1  /*
       2   * Check decoding of preadv and pwritev syscalls.
       3   *
       4   * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2016-2021 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include "tests.h"
      12  
      13  #if defined HAVE_PREADV && defined HAVE_PWRITEV
      14  
      15  # include <fcntl.h>
      16  # include <stdio.h>
      17  # include <sys/uio.h>
      18  # include <unistd.h>
      19  
      20  int
      21  main(void)
      22  {
      23  	tprintf("%s", "");
      24  
      25  	static char tmp[] = "preadv-pwritev-tmpfile";
      26  	if (open(tmp, O_CREAT|O_RDONLY|O_TRUNC, 0600) != 0)
      27  		perror_msg_and_fail("creat: %s", tmp);
      28  	if (open(tmp, O_WRONLY) != 1)
      29  		perror_msg_and_fail("open: %s", tmp);
      30  	if (unlink(tmp))
      31  		perror_msg_and_fail("unlink: %s", tmp);
      32  
      33  	static const char w0_c[] = "012";
      34  	const char *w0_d = hexdump_strdup(w0_c);
      35  	void *w0 = tail_memdup(w0_c, LENGTH_OF(w0_c));
      36  
      37  	const void *efault = w0 + LENGTH_OF(w0_c);
      38  
      39  	static const char w1_c[] = "34567";
      40  	const char *w1_d = hexdump_strdup(w1_c);
      41  	void *w1 = tail_memdup(w1_c, LENGTH_OF(w1_c));
      42  
      43  	static const char w2_c[] = "89abcde";
      44  	const char *w2_d = hexdump_strdup(w2_c);
      45  	void *w2 = tail_memdup(w2_c, LENGTH_OF(w2_c));
      46  
      47  	long rc;
      48  
      49  	rc = pwritev(1, efault, 42, 0);
      50  	tprintf("pwritev(1, %p, 42, 0) = %ld %s (%m)\n",
      51  		efault, rc, errno2name());
      52  
      53  	rc = preadv(0, efault, 42, 0);
      54  	tprintf("preadv(0, %p, 42, 0) = %ld %s (%m)\n",
      55  		efault, rc, errno2name());
      56  
      57  	static const char r0_c[] = "01234567";
      58  	const char *r0_d = hexdump_strdup(r0_c);
      59  	static const char r1_c[] = "89abcde";
      60  	const char *r1_d = hexdump_strdup(r1_c);
      61  
      62  	const struct iovec w_iov_[] = {
      63  		{
      64  			.iov_base = w0,
      65  			.iov_len = LENGTH_OF(w0_c)
      66  		}, {
      67  			.iov_base = w1,
      68  			.iov_len = LENGTH_OF(w1_c)
      69  		}, {
      70  			.iov_base = w2,
      71  			.iov_len = LENGTH_OF(w2_c)
      72  		}
      73  	};
      74  	const struct iovec *w_iov = tail_memdup(w_iov_, sizeof(w_iov_));
      75  
      76  	rc = pwritev(1, w_iov, 0, 0);
      77  	if (rc)
      78  		perror_msg_and_fail("pwritev: expected 0, returned %ld", rc);
      79  	tprintf("pwritev(1, [], 0, 0) = 0\n");
      80  
      81  	rc = pwritev(1, w_iov + ARRAY_SIZE(w_iov_) - 1, 2, 0);
      82  	tprintf("pwritev(1, [{iov_base=\"%s\", iov_len=%u}, ... /* %p */], 2, 0)"
      83  		" = %ld %s (%m)\n",
      84  		w2_c, LENGTH_OF(w2_c), w_iov + ARRAY_SIZE(w_iov_),
      85  		rc, errno2name());
      86  
      87  	const unsigned int w_len =
      88  		LENGTH_OF(w0_c) + LENGTH_OF(w1_c) + LENGTH_OF(w2_c);
      89  
      90  	rc = pwritev(1, w_iov, ARRAY_SIZE(w_iov_), 0);
      91  	if (rc != (int) w_len)
      92  		perror_msg_and_fail("pwritev: expected %u, returned %ld",
      93  				    w_len, rc);
      94  	close(1);
      95  	tprintf("pwritev(1, [{iov_base=\"%s\", iov_len=%u}"
      96  		", {iov_base=\"%s\", iov_len=%u}"
      97  		", {iov_base=\"%s\", iov_len=%u}], %u, 0) = %u\n"
      98  		" * %u bytes in buffer 0\n"
      99  		" | 00000 %-49s  %-16s |\n"
     100  		" * %u bytes in buffer 1\n"
     101  		" | 00000 %-49s  %-16s |\n"
     102  		" * %u bytes in buffer 2\n"
     103  		" | 00000 %-49s  %-16s |\n",
     104  		w0_c, LENGTH_OF(w0_c), w1_c, LENGTH_OF(w1_c),
     105  		w2_c, LENGTH_OF(w2_c), (unsigned int) ARRAY_SIZE(w_iov_), w_len,
     106  		LENGTH_OF(w0_c), w0_d, w0_c,
     107  		LENGTH_OF(w1_c), w1_d, w1_c, LENGTH_OF(w2_c), w2_d, w2_c);
     108  
     109  	const unsigned int r_len = (w_len + 1) / 2;
     110  	void *r0 = tail_alloc(r_len);
     111  	const struct iovec r0_iov_[] = {
     112  		{
     113  			.iov_base = r0,
     114  			.iov_len = r_len
     115  		}
     116  	};
     117  	const struct iovec *r_iov = tail_memdup(r0_iov_, sizeof(r0_iov_));
     118  
     119  	rc = preadv(0, r_iov, ARRAY_SIZE(r0_iov_), 0);
     120  	if (rc != (int) r_len)
     121  		perror_msg_and_fail("preadv: expected %u, returned %ld",
     122  				    r_len, rc);
     123  	tprintf("preadv(0, [{iov_base=\"%s\", iov_len=%u}], %u, 0) = %u\n"
     124  		" * %u bytes in buffer 0\n"
     125  		" | 00000 %-49s  %-16s |\n",
     126  		r0_c, r_len, (unsigned int) ARRAY_SIZE(r0_iov_),
     127  		r_len, r_len, r0_d, r0_c);
     128  
     129  	void *r1 = tail_alloc(r_len);
     130  	void *r2 = tail_alloc(w_len);
     131  	const struct iovec r1_iov_[] = {
     132  		{
     133  			.iov_base = r1,
     134  			.iov_len = r_len
     135  		},
     136  		{
     137  			.iov_base = r2,
     138  			.iov_len = w_len
     139  		}
     140  	};
     141  	r_iov = tail_memdup(r1_iov_, sizeof(r1_iov_));
     142  
     143  	rc = preadv(0, r_iov, ARRAY_SIZE(r1_iov_), r_len);
     144  	if (rc != (int) w_len - (int) r_len)
     145  		perror_msg_and_fail("preadv: expected %d, returned %ld",
     146  				    (int) w_len - r_len, rc);
     147  	tprintf("preadv(0, [{iov_base=\"%s\", iov_len=%u}"
     148  		", {iov_base=\"\", iov_len=%u}], %u, %u) = %u\n"
     149  		" * %u bytes in buffer 0\n"
     150  		" | 00000 %-49s  %-16s |\n",
     151  		r1_c, r_len, w_len, (unsigned int) ARRAY_SIZE(r1_iov_),
     152  		r_len, w_len - r_len,
     153  		w_len - r_len, r1_d, r1_c);
     154  	close(0);
     155  
     156  	tprintf("+++ exited with 0 +++\n");
     157  	return 0;
     158  }
     159  
     160  #else
     161  
     162  SKIP_MAIN_UNDEFINED("HAVE_PREADV && HAVE_PWRITEV")
     163  
     164  #endif