Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/file/dup_test.c
39536 views
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 <[email protected]> 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
* Tests #33-43 : Same as #18-26, 30 & 32 with O_CLOFORK instead of O_CLOEXEC,
50
* except F_DUP2FD_CLOEXEC.
51
*/
52
53
#include <sys/types.h>
54
#include <sys/time.h>
55
#include <sys/resource.h>
56
57
#include <err.h>
58
#include <fcntl.h>
59
#include <stdio.h>
60
#include <stdlib.h>
61
#include <unistd.h>
62
63
static int getafile(void);
64
65
static int
66
getafile(void)
67
{
68
int fd;
69
70
char temp[] = "/tmp/dup2XXXXXXXXX";
71
if ((fd = mkstemp(temp)) < 0)
72
err(1, "mkstemp");
73
remove(temp);
74
if (ftruncate(fd, 1024) != 0)
75
err(1, "ftruncate");
76
return (fd);
77
}
78
79
int
80
main(int __unused argc, char __unused *argv[])
81
{
82
struct rlimit rlp;
83
int orgfd, fd1, fd2, test = 0;
84
85
orgfd = getafile();
86
87
printf("1..43\n");
88
89
/* If dup(2) ever work? */
90
if ((fd1 = dup(orgfd)) < 0)
91
err(1, "dup");
92
printf("ok %d - dup(2) works\n", ++test);
93
94
/* Set close-on-exec */
95
if (fcntl(fd1, F_SETFD, 1) != 0)
96
err(1, "fcntl(F_SETFD)");
97
98
/* If dup2(2) ever work? */
99
if ((fd2 = dup2(fd1, fd1 + 1)) < 0)
100
err(1, "dup2");
101
printf("ok %d - dup2(2) works\n", ++test);
102
103
/* Do we get the right fd? */
104
++test;
105
if (fd2 != fd1 + 1)
106
printf("no ok %d - dup2(2) didn't give us the right fd\n",
107
test);
108
else
109
printf("ok %d - dup2(2) returned a correct fd\n", test);
110
111
/* Was close-on-exec cleared? */
112
++test;
113
if (fcntl(fd2, F_GETFD) != 0)
114
printf("not ok %d - dup2(2) didn't clear close-on-exec\n",
115
test);
116
else
117
printf("ok %d - dup2(2) cleared close-on-exec\n", test);
118
119
/*
120
* Dup to itself.
121
*
122
* We're testing a small tweak in dup2 semantics.
123
* Normally dup and dup2 will clear the close-on-exec
124
* flag on the new fd (which appears to be an implementation
125
* mistake from start and not some planned behavior).
126
* In today's implementations of dup and dup2 we have to make
127
* an effort to really clear that flag. But all tested
128
* implementations of dup2 have another tweak. If we
129
* dup2(old, new) when old == new, the syscall short-circuits
130
* and returns early (because there is no need to do all the
131
* work (and there is a risk for serious mistakes)).
132
* So although the docs say that dup2 should "take 'old',
133
* close 'new' perform a dup(2) of 'old' into 'new'"
134
* the docs are not really followed because close-on-exec
135
* is not cleared on 'new'.
136
*
137
* Since everyone has this bug, we pretend that this is
138
* the way it is supposed to be and test here that it really
139
* works that way.
140
*
141
* This is a fine example on where two separate implementation
142
* fuckups take out each other and make the end-result the way
143
* it was meant to be.
144
*/
145
if ((fd2 = dup2(fd1, fd1)) < 0)
146
err(1, "dup2");
147
printf("ok %d - dup2(2) to itself works\n", ++test);
148
149
/* Do we get the right fd? */
150
++test;
151
if (fd2 != fd1)
152
printf("not ok %d - dup2(2) didn't give us the right fd\n",
153
test);
154
else
155
printf("ok %d - dup2(2) to itself returned a correct fd\n",
156
test);
157
158
/* Was close-on-exec cleared? */
159
++test;
160
if (fcntl(fd2, F_GETFD) == 0)
161
printf("not ok %d - dup2(2) cleared close-on-exec\n", test);
162
else
163
printf("ok %d - dup2(2) didn't clear close-on-exec\n", test);
164
165
/* Does fcntl(F_DUPFD) work? */
166
if ((fd2 = fcntl(fd1, F_DUPFD, 10)) < 0)
167
err(1, "fcntl(F_DUPFD)");
168
if (fd2 < 10)
169
printf("not ok %d - fcntl(F_DUPFD) returned wrong fd %d\n",
170
++test, fd2);
171
else
172
printf("ok %d - fcntl(F_DUPFD) works\n", ++test);
173
174
/* Was close-on-exec cleared? */
175
++test;
176
if (fcntl(fd2, F_GETFD) != 0)
177
printf(
178
"not ok %d - fcntl(F_DUPFD) didn't clear close-on-exec\n",
179
test);
180
else
181
printf("ok %d - fcntl(F_DUPFD) cleared close-on-exec\n", test);
182
183
++test;
184
if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
185
err(1, "getrlimit");
186
if ((fd2 = dup2(fd1, rlp.rlim_cur + 1)) >= 0)
187
printf("not ok %d - dup2(2) bypassed NOFILE limit\n", test);
188
else
189
printf("ok %d - dup2(2) didn't bypass NOFILE limit\n", test);
190
191
/* If fcntl(F_DUP2FD) ever work? */
192
if ((fd2 = fcntl(fd1, F_DUP2FD, fd1 + 1)) < 0)
193
err(1, "fcntl(F_DUP2FD)");
194
printf("ok %d - fcntl(F_DUP2FD) works\n", ++test);
195
196
/* Do we get the right fd? */
197
++test;
198
if (fd2 != fd1 + 1)
199
printf(
200
"no ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n",
201
test);
202
else
203
printf("ok %d - fcntl(F_DUP2FD) returned a correct fd\n",
204
test);
205
206
/* Was close-on-exec cleared? */
207
++test;
208
if (fcntl(fd2, F_GETFD) != 0)
209
printf(
210
"not ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n",
211
test);
212
else
213
printf("ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n",
214
test);
215
216
/* Dup to itself */
217
if ((fd2 = fcntl(fd1, F_DUP2FD, fd1)) < 0)
218
err(1, "fcntl(F_DUP2FD)");
219
printf("ok %d - fcntl(F_DUP2FD) to itself works\n", ++test);
220
221
/* Do we get the right fd? */
222
++test;
223
if (fd2 != fd1)
224
printf(
225
"not ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n",
226
test);
227
else
228
printf(
229
"ok %d - fcntl(F_DUP2FD) to itself returned a correct fd\n",
230
test);
231
232
/* Was close-on-exec cleared? */
233
++test;
234
if (fcntl(fd2, F_GETFD) == 0)
235
printf("not ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n",
236
test);
237
else
238
printf("ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n",
239
test);
240
241
++test;
242
if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
243
err(1, "getrlimit");
244
if ((fd2 = fcntl(fd1, F_DUP2FD, rlp.rlim_cur + 1)) >= 0)
245
printf("not ok %d - fcntl(F_DUP2FD) bypassed NOFILE limit\n",
246
test);
247
else
248
printf("ok %d - fcntl(F_DUP2FD) didn't bypass NOFILE limit\n",
249
test);
250
251
/* Does fcntl(F_DUPFD_CLOEXEC) work? */
252
if ((fd2 = fcntl(fd1, F_DUPFD_CLOEXEC, 10)) < 0)
253
err(1, "fcntl(F_DUPFD_CLOEXEC)");
254
if (fd2 < 10)
255
printf("not ok %d - fcntl(F_DUPFD_CLOEXEC) returned wrong fd %d\n",
256
++test, fd2);
257
else
258
printf("ok %d - fcntl(F_DUPFD_CLOEXEC) works\n", ++test);
259
260
/* Was close-on-exec cleared? */
261
++test;
262
if (fcntl(fd2, F_GETFD) != 1)
263
printf(
264
"not ok %d - fcntl(F_DUPFD_CLOEXEC) didn't set close-on-exec\n",
265
test);
266
else
267
printf("ok %d - fcntl(F_DUPFD_CLOEXEC) set close-on-exec\n",
268
test);
269
270
/* If fcntl(F_DUP2FD_CLOEXEC) ever work? */
271
if ((fd2 = fcntl(fd1, F_DUP2FD_CLOEXEC, fd1 + 1)) < 0)
272
err(1, "fcntl(F_DUP2FD_CLOEXEC)");
273
printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) works\n", ++test);
274
275
/* Do we get the right fd? */
276
++test;
277
if (fd2 != fd1 + 1)
278
printf(
279
"no ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't give us the right fd\n",
280
test);
281
else
282
printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) returned a correct fd\n",
283
test);
284
285
/* Was close-on-exec set? */
286
++test;
287
if (fcntl(fd2, F_GETFD) != FD_CLOEXEC)
288
printf(
289
"not ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't set close-on-exec\n",
290
test);
291
else
292
printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) set close-on-exec\n",
293
test);
294
295
/*
296
* It is unclear what F_DUP2FD_CLOEXEC should do when duplicating a
297
* file descriptor onto itself.
298
*/
299
300
++test;
301
if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
302
err(1, "getrlimit");
303
if ((fd2 = fcntl(fd1, F_DUP2FD_CLOEXEC, rlp.rlim_cur + 1)) >= 0)
304
printf("not ok %d - fcntl(F_DUP2FD_CLOEXEC) bypassed NOFILE limit\n",
305
test);
306
else
307
printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't bypass NOFILE limit\n",
308
test);
309
310
/* Does dup3(O_CLOEXEC) ever work? */
311
if ((fd2 = dup3(fd1, fd1 + 1, O_CLOEXEC)) < 0)
312
err(1, "dup3(O_CLOEXEC)");
313
printf("ok %d - dup3(O_CLOEXEC) works\n", ++test);
314
315
/* Do we get the right fd? */
316
++test;
317
if (fd2 != fd1 + 1)
318
printf(
319
"no ok %d - dup3(O_CLOEXEC) didn't give us the right fd\n",
320
test);
321
else
322
printf("ok %d - dup3(O_CLOEXEC) returned a correct fd\n",
323
test);
324
325
/* Was close-on-exec set? */
326
++test;
327
if (fcntl(fd2, F_GETFD) != FD_CLOEXEC)
328
printf(
329
"not ok %d - dup3(O_CLOEXEC) didn't set close-on-exec\n",
330
test);
331
else
332
printf("ok %d - dup3(O_CLOEXEC) set close-on-exec\n",
333
test);
334
335
/* Does dup3(0) ever work? */
336
if ((fd2 = dup3(fd1, fd1 + 1, 0)) < 0)
337
err(1, "dup3(0)");
338
printf("ok %d - dup3(0) works\n", ++test);
339
340
/* Do we get the right fd? */
341
++test;
342
if (fd2 != fd1 + 1)
343
printf(
344
"no ok %d - dup3(0) didn't give us the right fd\n",
345
test);
346
else
347
printf("ok %d - dup3(0) returned a correct fd\n",
348
test);
349
350
/* Was close-on-exec cleared? */
351
++test;
352
if (fcntl(fd2, F_GETFD) != 0)
353
printf(
354
"not ok %d - dup3(0) didn't clear close-on-exec\n",
355
test);
356
else
357
printf("ok %d - dup3(0) cleared close-on-exec\n",
358
test);
359
360
/* dup3() does not allow duplicating to the same fd */
361
++test;
362
if (dup3(fd1, fd1, O_CLOEXEC) != -1)
363
printf(
364
"not ok %d - dup3(fd1, fd1, O_CLOEXEC) succeeded\n", test);
365
else
366
printf("ok %d - dup3(fd1, fd1, O_CLOEXEC) failed\n", test);
367
368
++test;
369
if (dup3(fd1, fd1, 0) != -1)
370
printf(
371
"not ok %d - dup3(fd1, fd1, 0) succeeded\n", test);
372
else
373
printf("ok %d - dup3(fd1, fd1, 0) failed\n", test);
374
375
++test;
376
if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
377
err(1, "getrlimit");
378
if ((fd2 = dup3(fd1, rlp.rlim_cur + 1, O_CLOEXEC)) >= 0)
379
printf("not ok %d - dup3(O_CLOEXEC) bypassed NOFILE limit\n",
380
test);
381
else
382
printf("ok %d - dup3(O_CLOEXEC) didn't bypass NOFILE limit\n",
383
test);
384
385
/* Does fcntl(F_DUPFD_CLOFORK) work? */
386
if ((fd2 = fcntl(fd1, F_DUPFD_CLOFORK, 10)) < 0)
387
err(1, "fcntl(F_DUPFD_CLOFORK)");
388
if (fd2 < 10)
389
printf("not ok %d - fcntl(F_DUPFD_CLOFORK) returned wrong fd %d\n",
390
++test, fd2);
391
else
392
printf("ok %d - fcntl(F_DUPFD_CLOFORK) works\n", ++test);
393
394
/* Was close-on-fork cleared? */
395
++test;
396
if (fcntl(fd2, F_GETFD) != FD_CLOFORK)
397
printf(
398
"not ok %d - fcntl(F_DUPFD_CLOFORK) didn't set close-on-fork\n",
399
test);
400
else
401
printf("ok %d - fcntl(F_DUPFD_CLOFORK) set close-on-fork\n",
402
test);
403
404
/* Does dup3(O_CLOFORK) ever work? */
405
if ((fd2 = dup3(fd1, fd1 + 1, O_CLOFORK)) < 0)
406
err(1, "dup3(O_CLOFORK)");
407
printf("ok %d - dup3(O_CLOFORK) works\n", ++test);
408
409
/* Do we get the right fd? */
410
++test;
411
if (fd2 != fd1 + 1)
412
printf(
413
"no ok %d - dup3(O_CLOFORK) didn't give us the right fd\n",
414
test);
415
else
416
printf("ok %d - dup3(O_CLOFORK) returned a correct fd\n",
417
test);
418
419
/* Was close-on-fork set? */
420
++test;
421
if (fcntl(fd2, F_GETFD) != FD_CLOFORK)
422
printf(
423
"not ok %d - dup3(O_CLOFORK) didn't set close-on-fork\n",
424
test);
425
else
426
printf("ok %d - dup3(O_CLOFORK) set close-on-fork\n",
427
test);
428
429
/* Does dup3(0) ever work? */
430
if ((fd2 = dup3(fd1, fd1 + 1, 0)) < 0)
431
err(1, "dup3(0)");
432
printf("ok %d - dup3(0) works\n", ++test);
433
434
/* Do we get the right fd? */
435
++test;
436
if (fd2 != fd1 + 1)
437
printf(
438
"no ok %d - dup3(0) didn't give us the right fd\n",
439
test);
440
else
441
printf("ok %d - dup3(0) returned a correct fd\n",
442
test);
443
444
/* Was close-on-fork cleared? */
445
++test;
446
if (fcntl(fd2, F_GETFD) != 0)
447
printf(
448
"not ok %d - dup3(0) didn't clear close-on-fork\n",
449
test);
450
else
451
printf("ok %d - dup3(0) cleared close-on-fork\n",
452
test);
453
454
/* dup3() does not allow duplicating to the same fd */
455
++test;
456
if (dup3(fd1, fd1, O_CLOFORK) != -1)
457
printf(
458
"not ok %d - dup3(fd1, fd1, O_CLOFORK) succeeded\n", test);
459
else
460
printf("ok %d - dup3(fd1, fd1, O_CLOFORK) failed\n", test);
461
462
++test;
463
if (dup3(fd1, fd1, 0) != -1)
464
printf(
465
"not ok %d - dup3(fd1, fd1, 0) succeeded\n", test);
466
else
467
printf("ok %d - dup3(fd1, fd1, 0) failed\n", test);
468
469
++test;
470
if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
471
err(1, "getrlimit");
472
if ((fd2 = dup3(fd1, rlp.rlim_cur + 1, O_CLOFORK)) >= 0)
473
printf("not ok %d - dup3(O_CLOFORK) bypassed NOFILE limit\n",
474
test);
475
else
476
printf("ok %d - dup3(O_CLOFORK) didn't bypass NOFILE limit\n",
477
test);
478
479
return (0);
480
}
481
482