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