Home | History | Annotate | Download | only in tests-mx32
      1 /*
      2  * Check decoding of preadv2 and pwritev2 syscalls.
      3  *
      4  * Copyright (c) 2016 Dmitry V. Levin <ldv (at) altlinux.org>
      5  * Copyright (c) 2016-2017 The strace developers.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "tests.h"
     32 #include <asm/unistd.h>
     33 #include "scno.h"
     34 
     35 #if defined __NR_preadv2 && defined __NR_pwritev2
     36 
     37 # include <errno.h>
     38 # include <fcntl.h>
     39 # include <stdio.h>
     40 # include <sys/uio.h>
     41 # include <unistd.h>
     42 
     43 static int
     44 pr(const int fd, const struct iovec *const vec,
     45    const unsigned long vlen, const unsigned long pos)
     46 {
     47 	return syscall(__NR_preadv2, fd, vec, vlen, pos, 0L, 0L);
     48 }
     49 
     50 static int
     51 pw(const int fd, const struct iovec *const vec,
     52    const unsigned long vlen, const unsigned long pos)
     53 {
     54 	return syscall(__NR_pwritev2, fd, vec, vlen, pos, 0L, 0L);
     55 }
     56 
     57 static void
     58 dumpio(void)
     59 {
     60 	static char tmp[] = "preadv2-pwritev2-tmpfile";
     61 	if (open(tmp, O_CREAT|O_RDONLY|O_TRUNC, 0600) != 0)
     62 		perror_msg_and_fail("creat: %s", tmp);
     63 	if (open(tmp, O_WRONLY) != 1)
     64 		perror_msg_and_fail("open: %s", tmp);
     65 	if (unlink(tmp))
     66 		perror_msg_and_fail("unlink: %s", tmp);
     67 
     68 	static const char w0_c[] = "012";
     69 	const char *w0_d = hexdump_strdup(w0_c);
     70 	void *w0 = tail_memdup(w0_c, LENGTH_OF(w0_c));
     71 
     72 	static const char w1_c[] = "34567";
     73 	const char *w1_d = hexdump_strdup(w1_c);
     74 	void *w1 = tail_memdup(w1_c, LENGTH_OF(w1_c));
     75 
     76 	static const char w2_c[] = "89abcde";
     77 	const char *w2_d = hexdump_strdup(w2_c);
     78 	void *w2 = tail_memdup(w2_c, LENGTH_OF(w2_c));
     79 
     80 	long rc;
     81 
     82 	static const char r0_c[] = "01234567";
     83 	const char *r0_d = hexdump_strdup(r0_c);
     84 	static const char r1_c[] = "89abcde";
     85 	const char *r1_d = hexdump_strdup(r1_c);
     86 
     87 	const struct iovec w_iov_[] = {
     88 		{
     89 			.iov_base = w0,
     90 			.iov_len = LENGTH_OF(w0_c)
     91 		}, {
     92 			.iov_base = w1,
     93 			.iov_len = LENGTH_OF(w1_c)
     94 		}, {
     95 			.iov_base = w2,
     96 			.iov_len = LENGTH_OF(w2_c)
     97 		}
     98 	};
     99 	const struct iovec *w_iov = tail_memdup(w_iov_, sizeof(w_iov_));
    100 
    101 	rc = pw(1, w_iov, 0, 0);
    102 	if (rc)
    103 		perror_msg_and_fail("pwritev2: expected 0, returned %ld", rc);
    104 	tprintf("pwritev2(1, [], 0, 0, 0) = 0\n");
    105 
    106 	rc = pw(1, w_iov + ARRAY_SIZE(w_iov_) - 1, 2, 0);
    107 	tprintf("pwritev2(1, [{iov_base=\"%s\", iov_len=%u}, %p], 2, 0, 0)"
    108 		" = %ld %s (%m)\n",
    109 		w2_c, LENGTH_OF(w2_c), w_iov + ARRAY_SIZE(w_iov_),
    110 		rc, errno2name());
    111 
    112 	const unsigned int w_len =
    113 		LENGTH_OF(w0_c) + LENGTH_OF(w1_c) + LENGTH_OF(w2_c);
    114 
    115 	rc = pw(1, w_iov, ARRAY_SIZE(w_iov_), 0);
    116 	if (rc != (int) w_len)
    117 		perror_msg_and_fail("pwritev2: expected %u, returned %ld",
    118 				    w_len, rc);
    119 	close(1);
    120 	tprintf("pwritev2(1, [{iov_base=\"%s\", iov_len=%u}"
    121 		", {iov_base=\"%s\", iov_len=%u}"
    122 		", {iov_base=\"%s\", iov_len=%u}], %u, 0, 0) = %u\n"
    123 		" * %u bytes in buffer 0\n"
    124 		" | 00000 %-49s  %-16s |\n"
    125 		" * %u bytes in buffer 1\n"
    126 		" | 00000 %-49s  %-16s |\n"
    127 		" * %u bytes in buffer 2\n"
    128 		" | 00000 %-49s  %-16s |\n",
    129 		w0_c, LENGTH_OF(w0_c), w1_c, LENGTH_OF(w1_c),
    130 		w2_c, LENGTH_OF(w2_c), (unsigned int) ARRAY_SIZE(w_iov_), w_len,
    131 		LENGTH_OF(w0_c), w0_d, w0_c,
    132 		LENGTH_OF(w1_c), w1_d, w1_c, LENGTH_OF(w2_c), w2_d, w2_c);
    133 
    134 	const unsigned int r_len = (w_len + 1) / 2;
    135 	void *r0 = tail_alloc(r_len);
    136 	const struct iovec r0_iov_[] = {
    137 		{
    138 			.iov_base = r0,
    139 			.iov_len = r_len
    140 		}
    141 	};
    142 	const struct iovec *r_iov = tail_memdup(r0_iov_, sizeof(r0_iov_));
    143 
    144 	rc = pr(0, r_iov, ARRAY_SIZE(r0_iov_), 0);
    145 	if (rc != (int) r_len)
    146 		perror_msg_and_fail("preadv2: expected %u, returned %ld",
    147 				    r_len, rc);
    148 	tprintf("preadv2(0, [{iov_base=\"%s\", iov_len=%u}], %u, 0, 0) = %u\n"
    149 		" * %u bytes in buffer 0\n"
    150 		" | 00000 %-49s  %-16s |\n",
    151 		r0_c, r_len, (unsigned int) ARRAY_SIZE(r0_iov_),
    152 		r_len, r_len, r0_d, r0_c);
    153 
    154 	void *r1 = tail_alloc(r_len);
    155 	void *r2 = tail_alloc(w_len);
    156 	const struct iovec r1_iov_[] = {
    157 		{
    158 			.iov_base = r1,
    159 			.iov_len = r_len
    160 		},
    161 		{
    162 			.iov_base = r2,
    163 			.iov_len = w_len
    164 		}
    165 	};
    166 	r_iov = tail_memdup(r1_iov_, sizeof(r1_iov_));
    167 
    168 	rc = pr(0, r_iov, ARRAY_SIZE(r1_iov_), r_len);
    169 	if (rc != (int) w_len - (int) r_len)
    170 		perror_msg_and_fail("preadv2: expected %d, returned %ld",
    171 				    (int) w_len - r_len, rc);
    172 	tprintf("preadv2(0, [{iov_base=\"%s\", iov_len=%u}"
    173 		", {iov_base=\"\", iov_len=%u}], %u, %u, 0) = %u\n"
    174 		" * %u bytes in buffer 0\n"
    175 		" | 00000 %-49s  %-16s |\n",
    176 		r1_c, r_len, w_len, (unsigned int) ARRAY_SIZE(r1_iov_),
    177 		r_len, w_len - r_len,
    178 		w_len - r_len, r1_d, r1_c);
    179 	close(0);
    180 }
    181 
    182 int
    183 main(void)
    184 {
    185 	const kernel_ulong_t vlen = (kernel_ulong_t) 0xfac1fed2dad3bef4ULL;
    186 	const unsigned long long pos = 0x7ac5fed6dad7bef8;
    187 	const kernel_ulong_t pos_l = (kernel_ulong_t) pos;
    188 	long rc;
    189 	int test_dumpio;
    190 
    191 	tprintf("%s", "");
    192 
    193 #if defined __x86_64__ && defined __ILP32__
    194 	/*
    195 	 * x32 is the only architecture where preadv2 takes 5 arguments,
    196 	 * see preadv64v2 in kernel sources.
    197 	 */
    198 	rc = syscall(__NR_preadv2, -1, NULL, vlen, pos_l, 1);
    199 #else
    200 	const kernel_ulong_t pos_h =
    201 		(sizeof(pos_l) == sizeof(pos)) ?
    202 		(kernel_ulong_t) 0xbadc0deddeadbeefULL :
    203 		(kernel_ulong_t) (pos >> 32);
    204 	rc = syscall(__NR_preadv2, -1, NULL, vlen, pos_l, pos_h, 1);
    205 #endif
    206 	if (rc != -1 || (ENOSYS != errno && EBADF != errno))
    207 		perror_msg_and_fail("preadv2");
    208 	test_dumpio = EBADF == errno;
    209 	tprintf("preadv2(-1, NULL, %lu, %lld, RWF_HIPRI) = %s\n",
    210 		(unsigned long) vlen, pos, sprintrc(rc));
    211 
    212 #if defined __x86_64__ && defined __ILP32__
    213 	/*
    214 	 * x32 is the only architecture where pwritev2 takes 5 arguments,
    215 	 * see pwritev64v2 in kernel sources.
    216 	 */
    217 	rc = syscall(__NR_pwritev2, -1, NULL, vlen, pos_l, 1);
    218 #else
    219 	rc = syscall(__NR_pwritev2, -1, NULL, vlen, pos_l, pos_h, 1);
    220 #endif
    221 	if (rc != -1 || (ENOSYS != errno && EBADF != errno))
    222 		perror_msg_and_fail("pwritev2");
    223 	tprintf("pwritev2(-1, NULL, %lu, %lld, RWF_HIPRI) = %s\n",
    224 		(unsigned long) vlen, pos, sprintrc(rc));
    225 
    226 	if (test_dumpio)
    227 		dumpio();
    228 
    229 	tprintf("%s\n", "+++ exited with 0 +++");
    230 	return 0;
    231 }
    232 
    233 #else
    234 
    235 SKIP_MAIN_UNDEFINED("__NR_preadv2 && __NR_pwritev2")
    236 
    237 #endif
    238