summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/sys/t_dup.c
diff options
context:
space:
mode:
authorbluhm <>2019-11-19 19:57:04 +0000
committerbluhm <>2019-11-19 19:57:04 +0000
commit9185f840eda265016178aeb0dcdba964f8f6f3e2 (patch)
treeda100b3712514c566fe948116f7926ad7f725401 /src/regress/lib/libc/sys/t_dup.c
parent6a6fe688152b422f3d65c970dad56e7d9d28b1ee (diff)
downloadopenbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.tar.gz
openbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.tar.bz2
openbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.zip
Import NetBSD system call regression tests. They were written with
ATF (Automated Testing Framework), so we use a small wrapper to map it to our bsd.regress.mk framework. Only half of the 80 NetBSD tests have been taken, the others need more work to adapt. Of them 34 syscall tests pass. Moritz Buhl ported the tests to OpenBSD.
Diffstat (limited to 'src/regress/lib/libc/sys/t_dup.c')
-rw-r--r--src/regress/lib/libc/sys/t_dup.c395
1 files changed, 395 insertions, 0 deletions
diff --git a/src/regress/lib/libc/sys/t_dup.c b/src/regress/lib/libc/sys/t_dup.c
new file mode 100644
index 0000000000..4021a4f6e4
--- /dev/null
+++ b/src/regress/lib/libc/sys/t_dup.c
@@ -0,0 +1,395 @@
1/* $OpenBSD: t_dup.c,v 1.1.1.1 2019/11/19 19:57:03 bluhm Exp $ */
2/* $NetBSD: t_dup.c,v 1.9 2017/01/13 20:31:53 christos Exp $ */
3
4/*-
5 * Copyright (c) 2011 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jukka Ruohonen.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include "macros.h"
34
35#include <sys/cdefs.h>
36__RCSID("$NetBSD: t_dup.c,v 1.9 2017/01/13 20:31:53 christos Exp $");
37
38#include <sys/resource.h>
39#include <sys/stat.h>
40#include <sys/wait.h>
41
42#include "atf-c.h"
43#include <errno.h>
44#include <fcntl.h>
45#include <limits.h>
46#include <stdbool.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <unistd.h>
51#include <sysexits.h>
52
53static char path[] = "dup";
54static void check_mode(bool, bool, bool);
55
56static void
57check_mode(bool _dup, bool _dup2, bool _dup3)
58{
59 int mode[3] = { O_RDONLY, O_WRONLY, O_RDWR };
60 int perm[5] = { 0700, 0400, 0600, 0444, 0666 };
61 struct stat st, st1;
62 int fd, fd1, fd2;
63 size_t i, j;
64
65 /*
66 * Check that a duplicated descriptor
67 * retains the mode of the original file.
68 */
69 for (i = 0; i < __arraycount(mode); i++) {
70
71 for (j = 0; j < __arraycount(perm); j++) {
72
73 fd1 = open(path, mode[i] | O_CREAT, perm[j]);
74 fd2 = open("/etc/passwd", O_RDONLY);
75
76 ATF_REQUIRE(fd1 >= 0);
77 ATF_REQUIRE(fd2 >= 0);
78
79 if (_dup != false)
80 fd = dup(fd1);
81 else if (_dup2 != false)
82 fd = dup2(fd1, fd2);
83 else if (_dup3 != false)
84 fd = dup3(fd1, fd2, O_CLOEXEC);
85 else {
86 fd = -1;
87 }
88
89 ATF_REQUIRE(fd >= 0);
90
91 (void)memset(&st, 0, sizeof(struct stat));
92 (void)memset(&st1, 0, sizeof(struct stat));
93
94 ATF_REQUIRE(fstat(fd, &st) == 0);
95 ATF_REQUIRE(fstat(fd1, &st1) == 0);
96
97 if (st.st_mode != st1.st_mode)
98 atf_tc_fail("invalid mode");
99
100 (void)close(fd);
101 (void)close(fd1);
102 (void)close(fd2);
103 (void)unlink(path);
104 }
105 }
106}
107
108ATF_TC(dup2_basic);
109ATF_TC_HEAD(dup2_basic, tc)
110{
111 atf_tc_set_md_var(tc, "descr", "A basic test of dup2(2)");
112}
113
114ATF_TC_BODY(dup2_basic, tc)
115{
116 int fd, fd1, fd2;
117
118 fd1 = open("/etc/passwd", O_RDONLY);
119 fd2 = open("/etc/passwd", O_RDONLY);
120
121 ATF_REQUIRE(fd1 >= 0);
122 ATF_REQUIRE(fd2 >= 0);
123
124 fd = dup2(fd1, fd2);
125 ATF_REQUIRE(fd >= 0);
126
127 if (fd != fd2)
128 atf_tc_fail("invalid descriptor");
129
130 (void)close(fd);
131 (void)close(fd1);
132
133 ATF_REQUIRE(close(fd2) != 0);
134}
135
136ATF_TC(dup2_err);
137ATF_TC_HEAD(dup2_err, tc)
138{
139 atf_tc_set_md_var(tc, "descr", "Test error conditions of dup2(2)");
140}
141
142ATF_TC_BODY(dup2_err, tc)
143{
144 int fd;
145
146 fd = open("/etc/passwd", O_RDONLY);
147 ATF_REQUIRE(fd >= 0);
148
149 errno = 0;
150 ATF_REQUIRE_ERRNO(EBADF, dup2(-1, -1) == -1);
151
152 errno = 0;
153 ATF_REQUIRE_ERRNO(EBADF, dup2(fd, -1) == -1);
154
155 errno = 0;
156 ATF_REQUIRE_ERRNO(EBADF, dup2(-1, fd) == -1);
157
158 /*
159 * Note that this should not fail with EINVAL.
160 */
161 ATF_REQUIRE(dup2(fd, fd) != -1);
162
163 (void)close(fd);
164}
165
166ATF_TC(dup2_max);
167ATF_TC_HEAD(dup2_max, tc)
168{
169 atf_tc_set_md_var(tc, "descr", "Test dup2(2) against limits");
170}
171
172ATF_TC_BODY(dup2_max, tc)
173{
174 struct rlimit res;
175
176 (void)memset(&res, 0, sizeof(struct rlimit));
177 (void)getrlimit(RLIMIT_NOFILE, &res);
178
179 errno = 0;
180 ATF_REQUIRE_ERRNO(EBADF, dup2(STDERR_FILENO, res.rlim_cur + 1) == -1);
181}
182
183ATF_TC_WITH_CLEANUP(dup2_mode);
184ATF_TC_HEAD(dup2_mode, tc)
185{
186 atf_tc_set_md_var(tc, "descr", "A basic test of dup2(2)");
187}
188
189ATF_TC_BODY(dup2_mode, tc)
190{
191 check_mode(false, true, false);
192}
193
194ATF_TC_CLEANUP(dup2_mode, tc)
195{
196 (void)unlink(path);
197}
198
199
200ATF_TC(dup3_err);
201ATF_TC_HEAD(dup3_err, tc)
202{
203 atf_tc_set_md_var(tc, "descr",
204 "Test error conditions of dup3(2) (PR lib/45148)");
205}
206
207ATF_TC_BODY(dup3_err, tc)
208{
209 int fd;
210
211 fd = open("/etc/passwd", O_RDONLY);
212 ATF_REQUIRE(fd >= 0);
213
214 errno = 0;
215 /* Adjusted for OpenBSD, initially != -1 */
216 ATF_REQUIRE(dup3(fd, fd, O_CLOEXEC) == -1);
217
218 errno = 0;
219 /* Adjusted for OpenBSD, initially EBADF */
220 ATF_REQUIRE_ERRNO(EINVAL, dup3(-1, -1, O_CLOEXEC) == -1);
221
222 errno = 0;
223 ATF_REQUIRE_ERRNO(EBADF, dup3(fd, -1, O_CLOEXEC) == -1);
224
225 errno = 0;
226 ATF_REQUIRE_ERRNO(EBADF, dup3(-1, fd, O_CLOEXEC) == -1);
227
228 errno = 0;
229 ATF_REQUIRE_ERRNO(EINVAL, dup3(fd, 1, O_NOFOLLOW) == -1);
230
231 (void)close(fd);
232}
233
234ATF_TC(dup3_max);
235ATF_TC_HEAD(dup3_max, tc)
236{
237 atf_tc_set_md_var(tc, "descr", "Test dup3(2) against limits");
238}
239
240ATF_TC_BODY(dup3_max, tc)
241{
242 struct rlimit res;
243
244 (void)memset(&res, 0, sizeof(struct rlimit));
245 (void)getrlimit(RLIMIT_NOFILE, &res);
246
247 errno = 0;
248 ATF_REQUIRE_ERRNO(EBADF, dup3(STDERR_FILENO,
249 res.rlim_cur + 1, O_CLOEXEC) == -1);
250}
251
252ATF_TC_WITH_CLEANUP(dup3_mode);
253ATF_TC_HEAD(dup3_mode, tc)
254{
255 atf_tc_set_md_var(tc, "descr", "A basic test of dup3(2)");
256}
257
258ATF_TC_BODY(dup3_mode, tc)
259{
260 check_mode(false, false, true);
261}
262
263ATF_TC_CLEANUP(dup3_mode, tc)
264{
265 (void)unlink(path);
266}
267
268ATF_TC(dup_err);
269ATF_TC_HEAD(dup_err, tc)
270{
271 atf_tc_set_md_var(tc, "descr", "Test error conditions of dup(2)");
272}
273
274ATF_TC_BODY(dup_err, tc)
275{
276
277 errno = 0;
278 ATF_REQUIRE_ERRNO(EBADF, dup(-1) == -1);
279}
280
281ATF_TC_WITH_CLEANUP(dup_max);
282ATF_TC_HEAD(dup_max, tc)
283{
284 atf_tc_set_md_var(tc, "descr", "Test dup(2) against limits");
285}
286
287ATF_TC_BODY(dup_max, tc)
288{
289 struct rlimit res;
290 int *buf, fd, sta;
291 size_t i, n;
292 pid_t pid;
293
294 pid = fork();
295 ATF_REQUIRE(pid >= 0);
296
297 if (pid == 0) {
298
299 /*
300 * Open a temporary file until the
301 * maximum number of open files is
302 * reached. Ater that dup(2) family
303 * should fail with EMFILE.
304 */
305 /* Adjusted for OpenBSD, initially 0 */
306 (void)closefrom(STDERR_FILENO + 1);
307 (void)memset(&res, 0, sizeof(struct rlimit));
308
309 n = 10;
310 res.rlim_cur = res.rlim_max = n;
311 if (setrlimit(RLIMIT_NOFILE, &res) != 0)
312 _exit(EX_OSERR);
313
314 buf = calloc(n, sizeof(int));
315
316 if (buf == NULL)
317 _exit(EX_OSERR);
318
319 /* Adjusted for OpenBSD, initially mkstemp(path) */
320 buf[0] = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
321
322 if (buf[0] < 0)
323 _exit(EX_OSERR);
324
325 /* Adjusted for OpenBSD, initially i < n */
326 for (i = 1; i < n - (STDERR_FILENO + 1); i++) {
327
328 buf[i] = open(path, O_RDONLY);
329
330 if (buf[i] < 0)
331 _exit(EX_OSERR);
332 }
333
334 errno = 0;
335 fd = dup(buf[0]);
336
337 if (fd != -1 || errno != EMFILE)
338 _exit(EX_DATAERR);
339
340 _exit(EXIT_SUCCESS);
341 }
342
343 (void)wait(&sta);
344
345 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) {
346
347 if (WEXITSTATUS(sta) == EX_OSERR)
348 atf_tc_fail("system call error");
349
350 if (WEXITSTATUS(sta) == EX_DATAERR)
351 atf_tc_fail("dup(2) dupped more than RLIMIT_NOFILE");
352
353 atf_tc_fail("unknown error");
354 }
355
356 (void)unlink(path);
357}
358
359ATF_TC_CLEANUP(dup_max, tc)
360{
361 (void)unlink(path);
362}
363
364ATF_TC_WITH_CLEANUP(dup_mode);
365ATF_TC_HEAD(dup_mode, tc)
366{
367 atf_tc_set_md_var(tc, "descr", "A basic test of dup(2)");
368}
369
370ATF_TC_BODY(dup_mode, tc)
371{
372 check_mode(true, false, false);
373}
374
375ATF_TC_CLEANUP(dup_mode, tc)
376{
377 (void)unlink(path);
378}
379
380ATF_TP_ADD_TCS(tp)
381{
382
383 ATF_TP_ADD_TC(tp, dup2_basic);
384 ATF_TP_ADD_TC(tp, dup2_err);
385 ATF_TP_ADD_TC(tp, dup2_max);
386 ATF_TP_ADD_TC(tp, dup2_mode);
387 ATF_TP_ADD_TC(tp, dup3_err);
388 ATF_TP_ADD_TC(tp, dup3_max);
389 ATF_TP_ADD_TC(tp, dup3_mode);
390 ATF_TP_ADD_TC(tp, dup_err);
391 ATF_TP_ADD_TC(tp, dup_max);
392 ATF_TP_ADD_TC(tp, dup_mode);
393
394 return atf_no_error();
395}