]> granicus.if.org Git - strace/blob - tests/pread64-pwrite64.c
strace: terminate itself if interrupted by a signal
[strace] / tests / pread64-pwrite64.c
1 /*
2  * Check decoding of pread64 and pwrite64 syscalls.
3  *
4  * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
5  * Copyright (c) 2016-2018 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 #include <fcntl.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17
18 static void
19 dump_str(const char *str, const unsigned int len)
20 {
21         static const char dots[16] = "................";
22         unsigned int i;
23
24         for (i = 0; i < len; i += 16) {
25                 unsigned int n = len - i > 16 ? 16 : len - i;
26                 const char *dump = hexdump_memdup(str + i, n);
27
28                 tprintf(" | %05x %-49s  %-16.*s |\n",
29                         i, dump, n, dots);
30
31                 free((void *) dump);
32         }
33 }
34
35 static void
36 print_hex(const char *str, const unsigned int len)
37 {
38         const unsigned char *ustr = (const unsigned char *) str;
39         unsigned int i;
40
41         for (i = 0; i < len; ++i) {
42                 unsigned int c = ustr[i];
43
44                 switch (c) {
45                 case '\t':
46                         tprintf("\\t"); break;
47                 case '\n':
48                         tprintf("\\n"); break;
49                 case '\v':
50                         tprintf("\\v"); break;
51                 case '\f':
52                         tprintf("\\f"); break;
53                 case '\r':
54                         tprintf("\\r"); break;
55                 default:
56                         tprintf("\\%o", ustr[i]);
57                 }
58         }
59 }
60
61 static void
62 test_dump(const unsigned int len)
63 {
64         static char *buf;
65
66         if (buf) {
67                 size_t ps1 = get_page_size() - 1;
68                 buf = (void *) (((size_t) buf + ps1) & ~ps1) - len;
69         } else {
70                 buf = tail_alloc(len);
71         }
72
73         const off_t offset = 0xdefaceddeadbeefLL + len;
74         long rc = pread(0, buf, len, offset);
75         if (rc != (int) len)
76                 perror_msg_and_fail("pread64: expected %d, returned %ld",
77                                     len, rc);
78
79         tprintf("%s(%d, \"", "pread64", 0);
80         print_hex(buf, len);
81         tprintf("\", %d, %lld) = %ld\n", len, (long long) offset, rc);
82         dump_str(buf, len);
83
84         unsigned int i;
85         for (i = 0; i < len; ++i)
86                 buf[i] = i;
87
88         rc = pwrite(1, buf, len, offset);
89         if (rc != (int) len)
90                 perror_msg_and_fail("pwrite64: expected %d, returned %ld",
91                                     len, rc);
92
93         tprintf("%s(%d, \"", "pwrite64", 1);
94         print_hex(buf, len);
95         tprintf("\", %d, %lld) = %ld\n", len, (long long) offset, rc);
96         dump_str(buf, len);
97
98         if (!len)
99                 buf = 0;
100 }
101
102 int
103 main(void)
104 {
105         tprintf("%s", "");
106
107         skip_if_unavailable("/proc/self/fd/");
108
109         static const char tmp[] = "pread64-pwrite64-tmpfile";
110         if (open(tmp, O_CREAT|O_RDONLY|O_TRUNC, 0600) != 0)
111                 perror_msg_and_fail("creat: %s", tmp);
112         if (open(tmp, O_WRONLY) != 1)
113                 perror_msg_and_fail("open: %s", tmp);
114
115         char *nil = tail_alloc(1);
116         *nil = '\0';
117
118         static const char w_c[] = "0123456789abcde";
119         const unsigned int w_len = LENGTH_OF(w_c);
120         const char *w_d = hexdump_strdup(w_c);
121         const void *w = tail_memdup(w_c, w_len);
122
123         static const char r0_c[] = "01234567";
124         const char *r0_d = hexdump_strdup(r0_c);
125         const unsigned int r0_len = (w_len + 1) / 2;
126         void *r0 = tail_alloc(r0_len);
127
128         static const char r1_c[] = "89abcde";
129         const char *r1_d = hexdump_strdup(r1_c);
130         const unsigned int r1_len = w_len - r0_len;
131         void *r1 = tail_alloc(w_len);
132
133         void *efault = r1 - get_page_size();
134
135         long rc;
136
137         rc = pwrite(1, w, 0, 0);
138         if (rc)
139                 perror_msg_and_fail("pwrite64: expected 0, returned %ld", rc);
140         tprintf("pwrite64(1, \"\", 0, 0) = 0\n");
141
142         rc = pwrite(1, efault, 1, 0);
143         if (rc != -1)
144                 perror_msg_and_fail("pwrite64: expected -1 EFAULT"
145                                     ", returned %ld", rc);
146         tprintf("pwrite64(1, %p, 1, 0) = -1 EFAULT (%m)\n", efault);
147
148         rc = pwrite(1, nil, 1, -3);
149         if (rc != -1)
150                 perror_msg_and_fail("pwrite64: expected -1, returned %ld", rc);
151         tprintf("pwrite64(1, \"\\0\", 1, -3) = -1 EINVAL (%m)\n");
152         dump_str(nil, 1);
153
154         rc = pwrite(1, w, w_len, 0);
155         if (rc != (int) w_len)
156                 perror_msg_and_fail("pwrite64: expected %u, returned %ld",
157                                     w_len, rc);
158         tprintf("pwrite64(1, \"%s\", %u, 0) = %ld\n"
159                 " | 00000 %-49s  %-16s |\n",
160                 w_c, w_len, rc, w_d, w_c);
161         close(1);
162
163         rc = pread(0, r0, 0, 0);
164         if (rc)
165                 perror_msg_and_fail("pread64: expected 0, returned %ld", rc);
166         tprintf("pread64(0, \"\", 0, 0) = 0\n");
167
168         rc = pread(0, efault, 1, 0);
169         if (rc != -1)
170                 perror_msg_and_fail("pread64: expected -1, returned %ld", rc);
171         tprintf("pread64(0, %p, 1, 0) = -1 EFAULT (%m)\n", efault);
172
173         rc = pread(0, efault, 2, -7);
174         if (rc != -1)
175                 perror_msg_and_fail("pread64: expected -1, returned %ld", rc);
176         tprintf("pread64(0, %p, 2, -7) = -1 EINVAL (%m)\n", efault);
177
178         rc = pread(0, r0, r0_len, 0);
179         if (rc != (int) r0_len)
180                 perror_msg_and_fail("pread64: expected %u, returned %ld",
181                                     r0_len, rc);
182         tprintf("pread64(0, \"%s\", %u, 0) = %ld\n"
183                 " | 00000 %-49s  %-16s |\n",
184                 r0_c, r0_len, rc, r0_d, r0_c);
185
186         rc = pread(0, r1, w_len, r0_len);
187         if (rc != (int) r1_len)
188                 perror_msg_and_fail("pread64: expected %u, returned %ld",
189                                     r1_len, rc);
190         tprintf("pread64(0, \"%s\", %u, %u) = %ld\n"
191                 " | 00000 %-49s  %-16s |\n",
192                 r1_c, w_len, r0_len, rc, r1_d, r1_c);
193         close(0);
194
195         if (open("/dev/zero", O_RDONLY))
196                 perror_msg_and_fail("open");
197
198         if (open("/dev/null", O_WRONLY) != 1)
199                 perror_msg_and_fail("open");
200
201         unsigned int i;
202         for (i = 0; i <= 32; ++i)
203                 test_dump(i);
204
205         tprintf("+++ exited with 0 +++\n");
206         return 0;
207 }