]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - tools/regression/file/dup/dup.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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  * Test #11: check if fcntl(F_DUP2FD) works.
24  * Test #12: check if fcntl(F_DUP2FD) returned a fd we asked for.
25  * Test #13: check if fcntl(F_DUP2FD) cleared close-on-exec flag for duped fd.
26  * Test #14: check if fcntl(F_DUP2FD) allows to dup fd to itself.
27  * Test #15: check if fcntl(F_DUP2FD) returned a fd we asked for.
28  * Test #16: check if fcntl(F_DUP2FD) did not clear close-on-exec flag for
29  *           duped fd.
30  * Test #17: check if fcntl(F_DUP2FD) to a fd > current maximum number of open
31  *           files limit work.
32  */
33
34 #include <sys/types.h>
35 #include <sys/time.h>
36 #include <sys/resource.h>
37
38 #include <err.h>
39 #include <fcntl.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43
44 static int      getafile(void);
45
46 static int
47 getafile(void)
48 {
49         int fd;
50
51         char temp[] = "/tmp/dup2XXXXXXXXX";
52         if ((fd = mkstemp(temp)) < 0)
53                 err(1, "mkstemp");
54         remove(temp);
55         if (ftruncate(fd, 1024) != 0)
56                 err(1, "ftruncate");
57         return (fd);
58 }
59
60 int
61 main(int __unused argc, char __unused *argv[])
62 {
63         struct rlimit rlp;
64         int orgfd, fd1, fd2, test = 0;
65
66         orgfd = getafile();
67
68         printf("1..17\n");
69
70         /* If dup(2) ever work? */
71         if ((fd1 = dup(orgfd)) < 0)
72                 err(1, "dup");
73         printf("ok %d - dup(2) works\n", ++test);
74
75         /* Set close-on-exec */
76         if (fcntl(fd1, F_SETFD, 1) != 0)
77                 err(1, "fcntl(F_SETFD)");
78
79         /* If dup2(2) ever work? */
80         if ((fd2 = dup2(fd1, fd1 + 1)) < 0)
81                 err(1, "dup2");
82         printf("ok %d - dup2(2) works\n", ++test);
83
84         /* Do we get the right fd? */
85         ++test;
86         if (fd2 != fd1 + 1)
87                 printf("no ok %d - dup2(2) didn't give us the right fd\n",
88                     test);
89         else
90                 printf("ok %d - dup2(2) returned a correct fd\n", test);
91
92         /* Was close-on-exec cleared? */
93         ++test;
94         if (fcntl(fd2, F_GETFD) != 0)
95                 printf("not ok %d - dup2(2) didn't clear close-on-exec\n",
96                     test);
97         else
98                 printf("ok %d - dup2(2) cleared close-on-exec\n", test);
99
100         /*
101          * Dup to itself.
102          *
103          * We're testing a small tweak in dup2 semantics.
104          * Normally dup and dup2 will clear the close-on-exec
105          * flag on the new fd (which appears to be an implementation
106          * mistake from start and not some planned behavior).
107          * In todays implementations of dup and dup2 we have to make
108          * an effort to really clear that flag.  But all tested
109          * implementations of dup2 have another tweak.  If we
110          * dup2(old, new) when old == new, the syscall short-circuits
111          * and returns early (because there is no need to do all the
112          * work (and there is a risk for serious mistakes)).
113          * So although the docs say that dup2 should "take 'old',
114          * close 'new' perform a dup(2) of 'old' into 'new'"
115          * the docs are not really followed because close-on-exec
116          * is not cleared on 'new'.
117          *
118          * Since everyone has this bug, we pretend that this is
119          * the way it is supposed to be and test here that it really
120          * works that way.
121          *
122          * This is a fine example on where two separate implementation
123          * fuckups take out each other and make the end-result the way
124          * it was meant to be.
125          */
126         if ((fd2 = dup2(fd1, fd1)) < 0)
127                 err(1, "dup2");
128         printf("ok %d - dup2(2) to itself works\n", ++test);
129
130         /* Do we get the right fd? */
131         ++test;
132         if (fd2 != fd1)
133                 printf("not ok %d - dup2(2) didn't give us the right fd\n",
134                     test);
135         else
136                 printf("ok %d - dup2(2) to itself returned a correct fd\n",
137                     test);
138
139         /* Was close-on-exec cleared? */
140         ++test;
141         if (fcntl(fd2, F_GETFD) == 0)
142                 printf("not ok %d - dup2(2) cleared close-on-exec\n", test);
143         else
144                 printf("ok %d - dup2(2) didn't clear close-on-exec\n", test);
145
146         /* Does fcntl(F_DUPFD) work? */
147         if ((fd2 = fcntl(fd1, F_DUPFD)) < 0)
148                 err(1, "fcntl(F_DUPFD)");
149         printf("ok %d - fcntl(F_DUPFD) works\n", ++test);
150
151         /* Was close-on-exec cleared? */
152         ++test;
153         if (fcntl(fd2, F_GETFD) != 0)
154                 printf(
155                     "not ok %d - fcntl(F_DUPFD) didn't clear close-on-exec\n",
156                     test);
157         else
158                 printf("ok %d - fcntl(F_DUPFD) cleared close-on-exec\n", test);
159
160         ++test;
161         if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
162                 err(1, "getrlimit");
163         if ((fd2 = dup2(fd1, rlp.rlim_cur + 1)) >= 0)
164                 printf("not ok %d - dup2(2) bypassed NOFILE limit\n", test);
165         else
166                 printf("ok %d - dup2(2) didn't bypass NOFILE limit\n", test);
167
168         /* If fcntl(F_DUP2FD) ever work? */
169         if ((fd2 = fcntl(fd1, F_DUP2FD, fd1 + 1)) < 0)
170                 err(1, "fcntl(F_DUP2FD)");
171         printf("ok %d - fcntl(F_DUP2FD) works\n", ++test);
172
173         /* Do we get the right fd? */
174         ++test;
175         if (fd2 != fd1 + 1)
176                 printf(
177                     "no ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n",
178                     test);
179         else
180                 printf("ok %d - fcntl(F_DUP2FD) returned a correct fd\n",
181                     test);
182
183         /* Was close-on-exec cleared? */
184         ++test;
185         if (fcntl(fd2, F_GETFD) != 0)
186                 printf(
187                     "not ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n",
188                     test);
189         else
190                 printf("ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n",
191                     test);
192
193         /* Dup to itself */
194         if ((fd2 = fcntl(fd1, F_DUP2FD, fd1)) < 0)
195                 err(1, "fcntl(F_DUP2FD)");
196         printf("ok %d - fcntl(F_DUP2FD) to itself works\n", ++test);
197
198         /* Do we get the right fd? */
199         ++test;
200         if (fd2 != fd1)
201                 printf(
202                     "not ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n",
203                     test);
204         else
205                 printf(
206                     "ok %d - fcntl(F_DUP2FD) to itself returned a correct fd\n",
207                     test);
208
209         /* Was close-on-exec cleared? */
210         ++test;
211         if (fcntl(fd2, F_GETFD) == 0)
212                 printf("not ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n",
213                     test);
214         else
215                 printf("ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n",
216                     test);
217
218         ++test;
219         if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
220                 err(1, "getrlimit");
221         if ((fd2 = fcntl(fd1, F_DUP2FD, rlp.rlim_cur + 1)) >= 0)
222                 printf("not ok %d - fcntl(F_DUP2FD) bypassed NOFILE limit\n",
223                     test);
224         else
225                 printf("ok %d - fcntl(F_DUP2FD) didn't bypass NOFILE limit\n",
226                     test);
227
228         return (0);
229 }