]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/regression/file/dup/dup.c
This commit was generated by cvs2svn to compensate for changes in r171825,
[FreeBSD/FreeBSD.git] / tools / regression / file / dup / dup.c
1 /*
2  * $OpenBSD: dup2test.c,v 1.3 2003/07/31 21:48:08 deraadt Exp $
3  * $OpenBSD: dup2_self.c,v 1.3 2003/07/31 21:48:08 deraadt Exp $
4  * $OpenBSD: fcntl_dup.c,v 1.2 2003/07/31 21:48:08 deraadt Exp $
5  *
6  * Written by Artur Grabowski <art@openbsd.org> 2002 Public Domain.
7  *
8  * $FreeBSD$
9  */
10
11 /*
12  * Test #1:  check if dup(2) works.
13  * Test #2:  check if dup2(2) works.
14  * Test #3:  check if dup2(2) returned a fd we asked for.
15  * Test #4:  check if dup2(2) cleared close-on-exec flag for duped fd.
16  * Test #5:  check if dup2(2) allows to dup fd to itself.
17  * Test #6:  check if dup2(2) returned a fd we asked for.
18  * Test #7:  check if dup2(2) did not clear close-on-exec flag for duped fd.
19  * Test #8:  check if fcntl(F_DUPFD) works.
20  * Test #9:  check if fcntl(F_DUPFD) cleared close-on-exec flag for duped fd.
21  * Test #10: check if dup2() to a fd > current maximum number of open files
22  *           limit work.
23  */
24
25 #include <sys/types.h>
26 #include <sys/time.h>
27 #include <sys/resource.h>
28
29 #include <err.h>
30 #include <fcntl.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34
35 static int      getafile(void);
36
37 static int
38 getafile(void)
39 {
40         int fd;
41
42         char temp[] = "/tmp/dup2XXXXXXXXX";
43         if ((fd = mkstemp(temp)) < 0)
44                 err(1, "mkstemp");
45         remove(temp);
46         if (ftruncate(fd, 1024) != 0)
47                 err(1, "ftruncate");
48         return (fd);
49 }
50
51 int
52 main(int __unused argc, char __unused *argv[])
53 {
54         struct rlimit rlp;
55         int orgfd, fd1, fd2, test = 0;
56
57         orgfd = getafile();
58
59         printf("1..10\n");
60
61         /* If dup(2) ever work? */
62         if ((fd1 = dup(orgfd)) < 0)
63                 err(1, "dup");
64         printf("ok %d - dup(2) works\n", ++test);
65
66         /* Set close-on-exec */
67         if (fcntl(fd1, F_SETFD, 1) != 0)
68                 err(1, "fcntl(F_SETFD)");
69
70         /* If dup2(2) ever work? */
71         if ((fd2 = dup2(fd1, fd1 + 1)) < 0)
72                 err(1, "dup2");
73         printf("ok %d - dup2(2) works\n", ++test);
74
75         /* Do we get the right fd? */
76         ++test;
77         if (fd2 != fd1 + 1)
78                 printf("no ok %d - dup2(2) didn't give us the right fd\n",
79                     test);
80         else
81                 printf("ok %d - dup2(2) returned a correct fd\n", test);
82
83         /* Was close-on-exec cleared? */
84         ++test;
85         if (fcntl(fd2, F_GETFD) != 0)
86                 printf("not ok %d - dup2(2) didn't clear close-on-exec\n",
87                     test);
88         else
89                 printf("ok %d - dup2(2) cleared close-on-exec\n", test);
90
91         /*
92          * Dup to itself.
93          *
94          * We're testing a small tweak in dup2 semantics.
95          * Normally dup and dup2 will clear the close-on-exec
96          * flag on the new fd (which appears to be an implementation
97          * mistake from start and not some planned behavior).
98          * In todays implementations of dup and dup2 we have to make
99          * an effort to really clear that flag.  But all tested
100          * implementations of dup2 have another tweak.  If we
101          * dup2(old, new) when old == new, the syscall short-circuits
102          * and returns early (because there is no need to do all the
103          * work (and there is a risk for serious mistakes)).
104          * So although the docs say that dup2 should "take 'old',
105          * close 'new' perform a dup(2) of 'old' into 'new'"
106          * the docs are not really followed because close-on-exec
107          * is not cleared on 'new'.
108          *
109          * Since everyone has this bug, we pretend that this is
110          * the way it is supposed to be and test here that it really
111          * works that way.
112          *
113          * This is a fine example on where two separate implementation
114          * fuckups take out each other and make the end-result the way
115          * it was meant to be.
116          */
117         if ((fd2 = dup2(fd1, fd1)) < 0)
118                 err(1, "dup2");
119         printf("ok %d - dup2(2) to itself works\n", ++test);
120
121         /* Do we get the right fd? */
122         ++test;
123         if (fd2 != fd1)
124                 printf("not ok %d - dup2(2) didn't give us the right fd\n",
125                     test);
126         else
127                 printf("ok %d - dup2(2) to itself returned a correct fd\n",
128                     test);
129
130         /* Was close-on-exec cleared? */
131         ++test;
132         if (fcntl(fd2, F_GETFD) == 0)
133                 printf("not ok %d - dup2(2) cleared close-on-exec\n", test);
134         else
135                 printf("ok %d - dup2(2) didn't clear close-on-exec\n", test);
136
137         /* Does fcntl(F_DUPFD) work? */
138         if ((fd2 = fcntl(fd1, F_DUPFD)) < 0)
139                 err(1, "fcntl(F_DUPFD)");
140         printf("ok %d - fcntl(F_DUPFD) works\n", ++test);
141
142         /* Was close-on-exec cleared? */
143         ++test;
144         if (fcntl(fd2, F_GETFD) != 0)
145                 printf(
146                     "not ok %d - fcntl(F_DUPFD) didn't clear close-on-exec\n",
147                     test);
148         else
149                 printf("ok %d - fcntl(F_DUPFD) cleared close-on-exec\n", test);
150
151         ++test;
152         if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
153                 err(1, "getrlimit");
154         if ((fd2 = dup2(fd1, rlp.rlim_cur + 1)) == 0)
155                 printf("not ok %d - dup2(2) bypassed NOFILE limit\n", test);
156         else
157                 printf("ok %d - dup2(2) didn't bypass NOFILE limit\n", test);
158
159         return (0);
160 }