1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
/*
* Copyright (c) 2014-2016 Dmitry V. Levin <ldv@strace.io>
* Copyright (c) 2016-2024 The strace developers.
* All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "tests.h"
#ifdef HAVE_PWRITEV
# include <fcntl.h>
# include <stdio.h>
# include <sys/uio.h>
# include <unistd.h>
# define LEN 8
# define LIM (LEN - 1)
static void
print_iov(const struct iovec *iov)
{
unsigned int i;
unsigned char *buf = iov->iov_base;
fputs("{iov_base=\"", stdout);
for (i = 0; i < iov->iov_len; ++i) {
if (i < LIM)
printf("\\%d", (int) buf[i]);
}
printf("\"%s, iov_len=%u}",
i > LIM ? "..." : "", (unsigned) iov->iov_len);
}
static void
print_iovec(const struct iovec *iov, unsigned int cnt, unsigned int size)
{
if (!size) {
printf("%p", iov);
return;
}
putchar('[');
for (unsigned int i = 0; i < cnt; ++i) {
if (i)
fputs(", ", stdout);
if (i == size) {
printf("... /* %p */", &iov[i]);
break;
}
if (i == LIM) {
fputs("...", stdout);
break;
}
print_iov(&iov[i]);
}
putchar(']');
}
/* for pwritev(0, NULL, 1, -3) */
DIAG_PUSH_IGNORE_NONNULL
int
main(void)
{
(void) close(0);
if (open("/dev/null", O_WRONLY))
perror_msg_and_fail("open");
char *buf = tail_alloc(LEN);
for (unsigned int i = 0; i < LEN; ++i)
buf[i] = i;
TAIL_ALLOC_OBJECT_VAR_ARR(struct iovec, iov, LEN);
for (unsigned int i = 0; i < LEN; ++i) {
buf[i] = i;
iov[i].iov_base = &buf[i];
iov[i].iov_len = LEN - i;
}
const off_t offset = 0xdefaceddeadbeefLL;
long rc;
int written = 0;
for (unsigned int i = 0; i < LEN; ++i) {
written += iov[i].iov_len;
if (pwritev(0, iov, i + 1, offset + i) != written)
perror_msg_and_fail("pwritev");
fputs("pwritev(0, ", stdout);
print_iovec(iov, i + 1, LEN);
printf(", %u, %lld) = %d\n",
i + 1, (long long) offset + i, written);
}
for (unsigned int i = 0; i <= LEN; ++i) {
unsigned int n = LEN + 1 - i;
fputs("pwritev(0, ", stdout);
print_iovec(iov + i, n, LEN - i);
rc = pwritev(0, iov + i, n, offset + LEN + i);
printf(", %u, %lld) = %s\n",
n, (long long) offset + LEN + i, sprintrc(rc));
}
iov->iov_base = iov + LEN * 2;
rc = pwritev(0, iov, 1, -1);
printf("pwritev(0, [{iov_base=%p, iov_len=%d}], 1, -1) = %s\n",
iov->iov_base, LEN, sprintrc(rc));
iov += LEN;
rc = pwritev(0, iov, 42, -2);
printf("pwritev(0, %p, 42, -2) = %s\n",
iov, sprintrc(rc));
rc = pwritev(0, NULL, 1, -3);
printf("pwritev(0, NULL, 1, -3) = %s\n",
sprintrc(rc));
rc = pwritev(0, iov, 0, -4);
printf("pwritev(0, [], 0, -4) = %s\n",
sprintrc(rc));
puts("+++ exited with 0 +++");
return 0;
}
DIAG_POP_IGNORE_NONNULL
#else
SKIP_MAIN_UNDEFINED("HAVE_PWRITEV")
#endif
|