]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/file/dup_test.c
awk: Merge upstream 2nd Edition Awk Book
[FreeBSD/FreeBSD.git] / tests / sys / file / dup_test.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
9 /*
10  * Test #1:  check if dup(2) works.
11  * Test #2:  check if dup2(2) works.
12  * Test #3:  check if dup2(2) returned a fd we asked for.
13  * Test #4:  check if dup2(2) cleared close-on-exec flag for duped fd.
14  * Test #5:  check if dup2(2) allows to dup fd to itself.
15  * Test #6:  check if dup2(2) returned a fd we asked for.
16  * Test #7:  check if dup2(2) did not clear close-on-exec flag for duped fd.
17  * Test #8:  check if fcntl(F_DUPFD) works.
18  * Test #9:  check if fcntl(F_DUPFD) cleared close-on-exec flag for duped fd.
19  * Test #10: check if dup2() to a fd > current maximum number of open files
20  *           limit work.
21  * Test #11: check if fcntl(F_DUP2FD) works.
22  * Test #12: check if fcntl(F_DUP2FD) returned a fd we asked for.
23  * Test #13: check if fcntl(F_DUP2FD) cleared close-on-exec flag for duped fd.
24  * Test #14: check if fcntl(F_DUP2FD) allows to dup fd to itself.
25  * Test #15: check if fcntl(F_DUP2FD) returned a fd we asked for.
26  * Test #16: check if fcntl(F_DUP2FD) did not clear close-on-exec flag for
27  *           duped fd.
28  * Test #17: check if fcntl(F_DUP2FD) to a fd > current maximum number of open
29  *           files limit work.
30  * Test #18: check if fcntl(F_DUPFD_CLOEXEC) works.
31  * Test #19: check if fcntl(F_DUPFD_CLOEXEC) set close-on-exec flag for duped
32  *           fd.
33  * Test #20: check if fcntl(F_DUP2FD_CLOEXEC) works.
34  * Test #21: check if fcntl(F_DUP2FD_CLOEXEC) returned a fd we asked for.
35  * Test #22: check if fcntl(F_DUP2FD_CLOEXEC) set close-on-exec flag for duped
36  *           fd.
37  * Test #23: check if fcntl(F_DUP2FD_CLOEXEC) to a fd > current maximum number
38  *           of open files limit work.
39  * Test #24: check if dup3(O_CLOEXEC) works.
40  * Test #25: check if dup3(O_CLOEXEC) returned a fd we asked for.
41  * Test #26: check if dup3(O_CLOEXEC) set close-on-exec flag for duped fd.
42  * Test #27: check if dup3(0) works.
43  * Test #28: check if dup3(0) returned a fd we asked for.
44  * Test #29: check if dup3(0) cleared close-on-exec flag for duped fd.
45  * Test #30: check if dup3(O_CLOEXEC) fails if oldfd == newfd.
46  * Test #31: check if dup3(0) fails if oldfd == newfd.
47  * Test #32: check if dup3(O_CLOEXEC) to a fd > current maximum number of
48  *           open files limit work.
49  */
50
51 #include <sys/types.h>
52 #include <sys/time.h>
53 #include <sys/resource.h>
54
55 #include <err.h>
56 #include <fcntl.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <unistd.h>
60
61 static int      getafile(void);
62
63 static int
64 getafile(void)
65 {
66         int fd;
67
68         char temp[] = "/tmp/dup2XXXXXXXXX";
69         if ((fd = mkstemp(temp)) < 0)
70                 err(1, "mkstemp");
71         remove(temp);
72         if (ftruncate(fd, 1024) != 0)
73                 err(1, "ftruncate");
74         return (fd);
75 }
76
77 int
78 main(int __unused argc, char __unused *argv[])
79 {
80         struct rlimit rlp;
81         int orgfd, fd1, fd2, test = 0;
82
83         orgfd = getafile();
84
85         printf("1..32\n");
86
87         /* If dup(2) ever work? */
88         if ((fd1 = dup(orgfd)) < 0)
89                 err(1, "dup");
90         printf("ok %d - dup(2) works\n", ++test);
91
92         /* Set close-on-exec */
93         if (fcntl(fd1, F_SETFD, 1) != 0)
94                 err(1, "fcntl(F_SETFD)");
95
96         /* If dup2(2) ever work? */
97         if ((fd2 = dup2(fd1, fd1 + 1)) < 0)
98                 err(1, "dup2");
99         printf("ok %d - dup2(2) works\n", ++test);
100
101         /* Do we get the right fd? */
102         ++test;
103         if (fd2 != fd1 + 1)
104                 printf("no ok %d - dup2(2) didn't give us the right fd\n",
105                     test);
106         else
107                 printf("ok %d - dup2(2) returned a correct fd\n", test);
108
109         /* Was close-on-exec cleared? */
110         ++test;
111         if (fcntl(fd2, F_GETFD) != 0)
112                 printf("not ok %d - dup2(2) didn't clear close-on-exec\n",
113                     test);
114         else
115                 printf("ok %d - dup2(2) cleared close-on-exec\n", test);
116
117         /*
118          * Dup to itself.
119          *
120          * We're testing a small tweak in dup2 semantics.
121          * Normally dup and dup2 will clear the close-on-exec
122          * flag on the new fd (which appears to be an implementation
123          * mistake from start and not some planned behavior).
124          * In today's implementations of dup and dup2 we have to make
125          * an effort to really clear that flag.  But all tested
126          * implementations of dup2 have another tweak.  If we
127          * dup2(old, new) when old == new, the syscall short-circuits
128          * and returns early (because there is no need to do all the
129          * work (and there is a risk for serious mistakes)).
130          * So although the docs say that dup2 should "take 'old',
131          * close 'new' perform a dup(2) of 'old' into 'new'"
132          * the docs are not really followed because close-on-exec
133          * is not cleared on 'new'.
134          *
135          * Since everyone has this bug, we pretend that this is
136          * the way it is supposed to be and test here that it really
137          * works that way.
138          *
139          * This is a fine example on where two separate implementation
140          * fuckups take out each other and make the end-result the way
141          * it was meant to be.
142          */
143         if ((fd2 = dup2(fd1, fd1)) < 0)
144                 err(1, "dup2");
145         printf("ok %d - dup2(2) to itself works\n", ++test);
146
147         /* Do we get the right fd? */
148         ++test;
149         if (fd2 != fd1)
150                 printf("not ok %d - dup2(2) didn't give us the right fd\n",
151                     test);
152         else
153                 printf("ok %d - dup2(2) to itself returned a correct fd\n",
154                     test);
155
156         /* Was close-on-exec cleared? */
157         ++test;
158         if (fcntl(fd2, F_GETFD) == 0)
159                 printf("not ok %d - dup2(2) cleared close-on-exec\n", test);
160         else
161                 printf("ok %d - dup2(2) didn't clear close-on-exec\n", test);
162
163         /* Does fcntl(F_DUPFD) work? */
164         if ((fd2 = fcntl(fd1, F_DUPFD, 10)) < 0)
165                 err(1, "fcntl(F_DUPFD)");
166         if (fd2 < 10)
167                 printf("not ok %d - fcntl(F_DUPFD) returned wrong fd %d\n",
168                     ++test, fd2);
169         else
170                 printf("ok %d - fcntl(F_DUPFD) works\n", ++test);
171
172         /* Was close-on-exec cleared? */
173         ++test;
174         if (fcntl(fd2, F_GETFD) != 0)
175                 printf(
176                     "not ok %d - fcntl(F_DUPFD) didn't clear close-on-exec\n",
177                     test);
178         else
179                 printf("ok %d - fcntl(F_DUPFD) cleared close-on-exec\n", test);
180
181         ++test;
182         if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
183                 err(1, "getrlimit");
184         if ((fd2 = dup2(fd1, rlp.rlim_cur + 1)) >= 0)
185                 printf("not ok %d - dup2(2) bypassed NOFILE limit\n", test);
186         else
187                 printf("ok %d - dup2(2) didn't bypass NOFILE limit\n", test);
188
189         /* If fcntl(F_DUP2FD) ever work? */
190         if ((fd2 = fcntl(fd1, F_DUP2FD, fd1 + 1)) < 0)
191                 err(1, "fcntl(F_DUP2FD)");
192         printf("ok %d - fcntl(F_DUP2FD) works\n", ++test);
193
194         /* Do we get the right fd? */
195         ++test;
196         if (fd2 != fd1 + 1)
197                 printf(
198                     "no ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n",
199                     test);
200         else
201                 printf("ok %d - fcntl(F_DUP2FD) returned a correct fd\n",
202                     test);
203
204         /* Was close-on-exec cleared? */
205         ++test;
206         if (fcntl(fd2, F_GETFD) != 0)
207                 printf(
208                     "not ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n",
209                     test);
210         else
211                 printf("ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n",
212                     test);
213
214         /* Dup to itself */
215         if ((fd2 = fcntl(fd1, F_DUP2FD, fd1)) < 0)
216                 err(1, "fcntl(F_DUP2FD)");
217         printf("ok %d - fcntl(F_DUP2FD) to itself works\n", ++test);
218
219         /* Do we get the right fd? */
220         ++test;
221         if (fd2 != fd1)
222                 printf(
223                     "not ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n",
224                     test);
225         else
226                 printf(
227                     "ok %d - fcntl(F_DUP2FD) to itself returned a correct fd\n",
228                     test);
229
230         /* Was close-on-exec cleared? */
231         ++test;
232         if (fcntl(fd2, F_GETFD) == 0)
233                 printf("not ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n",
234                     test);
235         else
236                 printf("ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n",
237                     test);
238
239         ++test;
240         if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
241                 err(1, "getrlimit");
242         if ((fd2 = fcntl(fd1, F_DUP2FD, rlp.rlim_cur + 1)) >= 0)
243                 printf("not ok %d - fcntl(F_DUP2FD) bypassed NOFILE limit\n",
244                     test);
245         else
246                 printf("ok %d - fcntl(F_DUP2FD) didn't bypass NOFILE limit\n",
247                     test);
248
249         /* Does fcntl(F_DUPFD_CLOEXEC) work? */
250         if ((fd2 = fcntl(fd1, F_DUPFD_CLOEXEC, 10)) < 0)
251                 err(1, "fcntl(F_DUPFD_CLOEXEC)");
252         if (fd2 < 10)
253                 printf("not ok %d - fcntl(F_DUPFD_CLOEXEC) returned wrong fd %d\n",
254                     ++test, fd2);
255         else
256                 printf("ok %d - fcntl(F_DUPFD_CLOEXEC) works\n", ++test);
257
258         /* Was close-on-exec cleared? */
259         ++test;
260         if (fcntl(fd2, F_GETFD) != 1)
261                 printf(
262                     "not ok %d - fcntl(F_DUPFD_CLOEXEC) didn't set close-on-exec\n",
263                     test);
264         else
265                 printf("ok %d - fcntl(F_DUPFD_CLOEXEC) set close-on-exec\n",
266                     test);
267
268         /* If fcntl(F_DUP2FD_CLOEXEC) ever work? */
269         if ((fd2 = fcntl(fd1, F_DUP2FD_CLOEXEC, fd1 + 1)) < 0)
270                 err(1, "fcntl(F_DUP2FD_CLOEXEC)");
271         printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) works\n", ++test);
272
273         /* Do we get the right fd? */
274         ++test;
275         if (fd2 != fd1 + 1)
276                 printf(
277                     "no ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't give us the right fd\n",
278                     test);
279         else
280                 printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) returned a correct fd\n",
281                     test);
282
283         /* Was close-on-exec set? */
284         ++test;
285         if (fcntl(fd2, F_GETFD) != FD_CLOEXEC)
286                 printf(
287                     "not ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't set close-on-exec\n",
288                     test);
289         else
290                 printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) set close-on-exec\n",
291                     test);
292
293         /*
294          * It is unclear what F_DUP2FD_CLOEXEC should do when duplicating a
295          * file descriptor onto itself.
296          */
297
298         ++test;
299         if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
300                 err(1, "getrlimit");
301         if ((fd2 = fcntl(fd1, F_DUP2FD_CLOEXEC, rlp.rlim_cur + 1)) >= 0)
302                 printf("not ok %d - fcntl(F_DUP2FD_CLOEXEC) bypassed NOFILE limit\n",
303                     test);
304         else
305                 printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't bypass NOFILE limit\n",
306                     test);
307
308         /* Does dup3(O_CLOEXEC) ever work? */
309         if ((fd2 = dup3(fd1, fd1 + 1, O_CLOEXEC)) < 0)
310                 err(1, "dup3(O_CLOEXEC)");
311         printf("ok %d - dup3(O_CLOEXEC) works\n", ++test);
312
313         /* Do we get the right fd? */
314         ++test;
315         if (fd2 != fd1 + 1)
316                 printf(
317                     "no ok %d - dup3(O_CLOEXEC) didn't give us the right fd\n",
318                     test);
319         else
320                 printf("ok %d - dup3(O_CLOEXEC) returned a correct fd\n",
321                     test);
322
323         /* Was close-on-exec set? */
324         ++test;
325         if (fcntl(fd2, F_GETFD) != FD_CLOEXEC)
326                 printf(
327                     "not ok %d - dup3(O_CLOEXEC) didn't set close-on-exec\n",
328                     test);
329         else
330                 printf("ok %d - dup3(O_CLOEXEC) set close-on-exec\n",
331                     test);
332
333         /* Does dup3(0) ever work? */
334         if ((fd2 = dup3(fd1, fd1 + 1, 0)) < 0)
335                 err(1, "dup3(0)");
336         printf("ok %d - dup3(0) works\n", ++test);
337
338         /* Do we get the right fd? */
339         ++test;
340         if (fd2 != fd1 + 1)
341                 printf(
342                     "no ok %d - dup3(0) didn't give us the right fd\n",
343                     test);
344         else
345                 printf("ok %d - dup3(0) returned a correct fd\n",
346                     test);
347
348         /* Was close-on-exec cleared? */
349         ++test;
350         if (fcntl(fd2, F_GETFD) != 0)
351                 printf(
352                     "not ok %d - dup3(0) didn't clear close-on-exec\n",
353                     test);
354         else
355                 printf("ok %d - dup3(0) cleared close-on-exec\n",
356                     test);
357
358         /* dup3() does not allow duplicating to the same fd */
359         ++test;
360         if (dup3(fd1, fd1, O_CLOEXEC) != -1)
361                 printf(
362                     "not ok %d - dup3(fd1, fd1, O_CLOEXEC) succeeded\n", test);
363         else
364                 printf("ok %d - dup3(fd1, fd1, O_CLOEXEC) failed\n", test);
365
366         ++test;
367         if (dup3(fd1, fd1, 0) != -1)
368                 printf(
369                     "not ok %d - dup3(fd1, fd1, 0) succeeded\n", test);
370         else
371                 printf("ok %d - dup3(fd1, fd1, 0) failed\n", test);
372
373         ++test;
374         if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
375                 err(1, "getrlimit");
376         if ((fd2 = dup3(fd1, rlp.rlim_cur + 1, O_CLOEXEC)) >= 0)
377                 printf("not ok %d - dup3(O_CLOEXEC) bypassed NOFILE limit\n",
378                     test);
379         else
380                 printf("ok %d - dup3(O_CLOEXEC) didn't bypass NOFILE limit\n",
381                     test);
382
383         return (0);
384 }