1 /* $NetBSD: t_dup.c,v 1.8 2012/03/18 07:00:51 jruoho Exp $ */
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: t_dup.c,v 1.8 2012/03/18 07:00:51 jruoho Exp $");
34 #include <sys/resource.h>
48 static char path
[] = "dup";
49 static void check_mode(bool, bool, bool);
52 check_mode(bool _dup
, bool _dup2
, bool _dup3
)
54 int mode
[3] = { O_RDONLY
, O_WRONLY
, O_RDWR
};
55 int perm
[5] = { 0700, 0400, 0600, 0444, 0666 };
61 * Check that a duplicated descriptor
62 * retains the mode of the original file.
64 for (i
= 0; i
< __arraycount(mode
); i
++) {
66 for (j
= 0; j
< __arraycount(perm
); j
++) {
68 fd1
= open(path
, mode
[i
] | O_CREAT
, perm
[j
]);
69 fd2
= open("/etc/passwd", O_RDONLY
);
71 ATF_REQUIRE(fd1
>= 0);
72 ATF_REQUIRE(fd2
>= 0);
76 else if (_dup2
!= false)
78 else if (_dup3
!= false)
79 fd
= dup3(fd1
, fd2
, O_CLOEXEC
);
86 (void)memset(&st
, 0, sizeof(struct stat
));
87 (void)memset(&st1
, 0, sizeof(struct stat
));
89 ATF_REQUIRE(fstat(fd
, &st
) == 0);
90 ATF_REQUIRE(fstat(fd1
, &st1
) == 0);
92 if (st
.st_mode
!= st1
.st_mode
)
93 atf_tc_fail("invalid mode");
104 ATF_TC_HEAD(dup2_basic
, tc
)
106 atf_tc_set_md_var(tc
, "descr", "A basic test of dup2(2)");
109 ATF_TC_BODY(dup2_basic
, tc
)
113 fd1
= open("/etc/passwd", O_RDONLY
);
114 fd2
= open("/etc/passwd", O_RDONLY
);
116 ATF_REQUIRE(fd1
>= 0);
117 ATF_REQUIRE(fd2
>= 0);
120 ATF_REQUIRE(fd
>= 0);
123 atf_tc_fail("invalid descriptor");
128 ATF_REQUIRE(close(fd2
) != 0);
132 ATF_TC_HEAD(dup2_err
, tc
)
134 atf_tc_set_md_var(tc
, "descr", "Test error conditions of dup2(2)");
137 ATF_TC_BODY(dup2_err
, tc
)
141 fd
= open("/etc/passwd", O_RDONLY
);
142 ATF_REQUIRE(fd
>= 0);
145 ATF_REQUIRE_ERRNO(EBADF
, dup2(-1, -1) == -1);
148 ATF_REQUIRE_ERRNO(EBADF
, dup2(fd
, -1) == -1);
151 ATF_REQUIRE_ERRNO(EBADF
, dup2(-1, fd
) == -1);
154 * Note that this should not fail with EINVAL.
156 ATF_REQUIRE(dup2(fd
, fd
) != -1);
162 ATF_TC_HEAD(dup2_max
, tc
)
164 atf_tc_set_md_var(tc
, "descr", "Test dup2(2) against limits");
167 ATF_TC_BODY(dup2_max
, tc
)
171 (void)memset(&res
, 0, sizeof(struct rlimit
));
172 (void)getrlimit(RLIMIT_NOFILE
, &res
);
175 ATF_REQUIRE_ERRNO(EBADF
, dup2(STDERR_FILENO
, res
.rlim_cur
+ 1) == -1);
178 ATF_TC_WITH_CLEANUP(dup2_mode
);
179 ATF_TC_HEAD(dup2_mode
, tc
)
181 atf_tc_set_md_var(tc
, "descr", "A basic test of dup2(2)");
184 ATF_TC_BODY(dup2_mode
, tc
)
186 check_mode(false, true, false);
189 ATF_TC_CLEANUP(dup2_mode
, tc
)
196 ATF_TC_HEAD(dup3_err
, tc
)
198 atf_tc_set_md_var(tc
, "descr",
199 "Test error conditions of dup3(2) (PR lib/45148)");
202 ATF_TC_BODY(dup3_err
, tc
)
206 fd
= open("/etc/passwd", O_RDONLY
);
207 ATF_REQUIRE(fd
>= 0);
210 ATF_REQUIRE(dup3(fd
, fd
, O_CLOEXEC
) != -1);
213 ATF_REQUIRE_ERRNO(EBADF
, dup3(-1, -1, O_CLOEXEC
) == -1);
216 ATF_REQUIRE_ERRNO(EBADF
, dup3(fd
, -1, O_CLOEXEC
) == -1);
219 ATF_REQUIRE_ERRNO(EBADF
, dup3(-1, fd
, O_CLOEXEC
) == -1);
222 ATF_REQUIRE_ERRNO(EINVAL
, dup3(fd
, 1, O_NOFOLLOW
) == -1);
228 ATF_TC_HEAD(dup3_max
, tc
)
230 atf_tc_set_md_var(tc
, "descr", "Test dup3(2) against limits");
233 ATF_TC_BODY(dup3_max
, tc
)
237 (void)memset(&res
, 0, sizeof(struct rlimit
));
238 (void)getrlimit(RLIMIT_NOFILE
, &res
);
241 ATF_REQUIRE_ERRNO(EBADF
, dup3(STDERR_FILENO
,
242 res
.rlim_cur
+ 1, O_CLOEXEC
) == -1);
245 ATF_TC_WITH_CLEANUP(dup3_mode
);
246 ATF_TC_HEAD(dup3_mode
, tc
)
248 atf_tc_set_md_var(tc
, "descr", "A basic test of dup3(2)");
251 ATF_TC_BODY(dup3_mode
, tc
)
253 check_mode(false, false, true);
256 ATF_TC_CLEANUP(dup3_mode
, tc
)
262 ATF_TC_HEAD(dup_err
, tc
)
264 atf_tc_set_md_var(tc
, "descr", "Test error conditions of dup(2)");
267 ATF_TC_BODY(dup_err
, tc
)
271 ATF_REQUIRE_ERRNO(EBADF
, dup(-1) == -1);
274 ATF_TC_WITH_CLEANUP(dup_max
);
275 ATF_TC_HEAD(dup_max
, tc
)
277 atf_tc_set_md_var(tc
, "descr", "Test dup(2) against limits");
280 ATF_TC_BODY(dup_max
, tc
)
288 ATF_REQUIRE(pid
>= 0);
293 * Open a temporary file until the
294 * maximum number of open files is
295 * reached. Ater that dup(2) family
296 * should fail with EMFILE.
299 (void)memset(&res
, 0, sizeof(struct rlimit
));
302 res
.rlim_cur
= res
.rlim_max
= n
;
303 if (setrlimit(RLIMIT_NOFILE
, &res
) != 0)
306 buf
= calloc(n
, sizeof(int));
311 buf
[0] = mkstemp(path
);
316 for (i
= 1; i
< n
; i
++) {
318 buf
[i
] = open(path
, O_RDONLY
);
327 if (fd
!= -1 || errno
!= EMFILE
)
335 if (WIFEXITED(sta
) == 0 || WEXITSTATUS(sta
) != EXIT_SUCCESS
) {
337 if (WEXITSTATUS(sta
) == EX_OSERR
)
338 atf_tc_fail("system call error");
340 if (WEXITSTATUS(sta
) == EX_DATAERR
)
341 atf_tc_fail("dup(2) dupped more than RLIMIT_NOFILE");
343 atf_tc_fail("unknown error");
349 ATF_TC_CLEANUP(dup_max
, tc
)
354 ATF_TC_WITH_CLEANUP(dup_mode
);
355 ATF_TC_HEAD(dup_mode
, tc
)
357 atf_tc_set_md_var(tc
, "descr", "A basic test of dup(2)");
360 ATF_TC_BODY(dup_mode
, tc
)
362 check_mode(true, false, false);
365 ATF_TC_CLEANUP(dup_mode
, tc
)
373 ATF_TP_ADD_TC(tp
, dup2_basic
);
374 ATF_TP_ADD_TC(tp
, dup2_err
);
375 ATF_TP_ADD_TC(tp
, dup2_max
);
376 ATF_TP_ADD_TC(tp
, dup2_mode
);
377 ATF_TP_ADD_TC(tp
, dup3_err
);
378 ATF_TP_ADD_TC(tp
, dup3_max
);
379 ATF_TP_ADD_TC(tp
, dup3_mode
);
380 ATF_TP_ADD_TC(tp
, dup_err
);
381 ATF_TP_ADD_TC(tp
, dup_max
);
382 ATF_TP_ADD_TC(tp
, dup_mode
);
384 return atf_no_error();