diff options
author | antoine <antoine@FreeBSD.org> | 2008-03-08 22:02:21 +0000 |
---|---|---|
committer | antoine <antoine@FreeBSD.org> | 2008-03-08 22:02:21 +0000 |
commit | 514f31f40ed28fea8fdc190c743417debb0d03b3 (patch) | |
tree | a5c6d546b6b95056f3d9779f9c1afae2cec004f6 | |
parent | 587a314ce88f943ab58c211714655de88ddbdd25 (diff) | |
download | FreeBSD-src-514f31f40ed28fea8fdc190c743417debb0d03b3.zip FreeBSD-src-514f31f40ed28fea8fdc190c743417debb0d03b3.tar.gz |
Introduce a new F_DUP2FD command to fcntl(2), for compatibility with
Solaris and AIX.
fcntl(fd, F_DUP2FD, arg) and dup2(fd, arg) are functionnaly equivalent.
Document it.
Add some regression tests (identical to the dup2(2) regression tests).
PR: 120233
Submitted by: Jukka Ukkonen
Approved by: rwaston (mentor)
MFC after: 1 month
-rw-r--r-- | lib/libc/sys/fcntl.2 | 38 | ||||
-rw-r--r-- | sys/kern/kern_descrip.c | 7 | ||||
-rw-r--r-- | sys/sys/fcntl.h | 1 | ||||
-rw-r--r-- | tools/regression/file/dup/dup.c | 73 |
4 files changed, 115 insertions, 4 deletions
diff --git a/lib/libc/sys/fcntl.2 b/lib/libc/sys/fcntl.2 index a476cff..aef53e2 100644 --- a/lib/libc/sys/fcntl.2 +++ b/lib/libc/sys/fcntl.2 @@ -28,7 +28,7 @@ .\" @(#)fcntl.2 8.2 (Berkeley) 1/12/94 .\" $FreeBSD$ .\" -.Dd January 12, 1994 +.Dd March 8, 2008 .Dt FCNTL 2 .Os .Sh NAME @@ -78,6 +78,18 @@ is set to remain open across .Xr execve 2 system calls. .El +.It Dv F_DUP2FD +It is functionally equivalent to +.Bd -literal -offset indent +dup2(fd, arg) +.Ed +.Pp +The +.Dv F_DUP2FD +constant is not portable, so it should not be used if portability is needed. +Use +.Fn dup2 +instead. .It Dv F_GETFD Get the close-on-exec flag associated with the file descriptor .Fa fd @@ -389,6 +401,9 @@ as follows: .Bl -tag -width F_GETOWNX -offset indent .It Dv F_DUPFD A new file descriptor. +.It Dv F_DUP2FD +A file descriptor equal to +.Fa arg . .It Dv F_GETFD Value of flag (only the low-order bit is defined). .It Dv F_GETFL @@ -432,6 +447,14 @@ is not a valid open file descriptor. The argument .Fa cmd is +.Dv F_DUP2FD , +and +.Fa arg +is not a valid file descriptor. +.Pp +The argument +.Fa cmd +is .Dv F_SETLK or .Dv F_SETLKW , @@ -495,6 +518,8 @@ The argument .Fa cmd is .Dv F_DUPFD +or +.Dv F_DUP2FD and the maximum number of file descriptors permitted for the process are already in use, or no file descriptors greater than or equal to @@ -567,6 +592,7 @@ for the reasons as stated in .Xr tcgetpgrp 3 . .Sh SEE ALSO .Xr close 2 , +.Xr dup2 2 , .Xr execve 2 , .Xr flock 2 , .Xr getdtablesize 2 , @@ -575,8 +601,18 @@ for the reasons as stated in .Xr lockf 3 , .Xr tcgetpgrp 3 , .Xr tcsetpgrp 3 +.Sh STANDARDS +The +.Dv F_DUP2FD +constant is non portable. +It is provided for compatibility with AIX and Solaris. .Sh HISTORY The .Fn fcntl system call appeared in .Bx 4.2 . +.Pp +The +.Dv F_DUP2FD +constant first appeared in +.Fx 7.1 . diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 7025587..5174c15 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -397,6 +397,11 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) error = do_dup(td, DUP_VARIABLE, fd, newmin, td->td_retval); break; + case F_DUP2FD: + tmp = arg; + error = do_dup(td, DUP_FIXED, fd, tmp, td->td_retval); + break; + case F_GETFD: FILEDESC_SLOCK(fdp); if ((fp = fdtofp(fd, fdp)) == NULL) { @@ -633,7 +638,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) } /* - * Common code for dup, dup2, and fcntl(F_DUPFD). + * Common code for dup, dup2, fcntl(F_DUPFD) and fcntl(F_DUP2FD). */ static int do_dup(struct thread *td, enum dup_type type, int old, int new, diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h index 8ec5862..ea8531a 100644 --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -181,6 +181,7 @@ typedef __pid_t pid_t; #define F_GETLK 7 /* get record locking information */ #define F_SETLK 8 /* set record locking information */ #define F_SETLKW 9 /* F_SETLK; wait if blocked */ +#define F_DUP2FD 10 /* duplicate file descriptor to arg */ /* file descriptor flags (F_GETFD, F_SETFD) */ #define FD_CLOEXEC 1 /* close-on-exec flag */ diff --git a/tools/regression/file/dup/dup.c b/tools/regression/file/dup/dup.c index ad1f6df..d6dd0ff 100644 --- a/tools/regression/file/dup/dup.c +++ b/tools/regression/file/dup/dup.c @@ -20,6 +20,15 @@ * Test #9: check if fcntl(F_DUPFD) cleared close-on-exec flag for duped fd. * Test #10: check if dup2() to a fd > current maximum number of open files * limit work. + * Test #11: check if fcntl(F_DUP2FD) works. + * Test #12: check if fcntl(F_DUP2FD) returned a fd we asked for. + * Test #13: check if fcntl(F_DUP2FD) cleared close-on-exec flag for duped fd. + * Test #14: check if fcntl(F_DUP2FD) allows to dup fd to itself. + * Test #15: check if fcntl(F_DUP2FD) returned a fd we asked for. + * Test #16: check if fcntl(F_DUP2FD) did not clear close-on-exec flag for + * duped fd. + * Test #17: check if fcntl(F_DUP2FD) to a fd > current maximum number of open + * files limit work. */ #include <sys/types.h> @@ -56,7 +65,7 @@ main(int __unused argc, char __unused *argv[]) orgfd = getafile(); - printf("1..10\n"); + printf("1..17\n"); /* If dup(2) ever work? */ if ((fd1 = dup(orgfd)) < 0) @@ -151,10 +160,70 @@ main(int __unused argc, char __unused *argv[]) ++test; if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) err(1, "getrlimit"); - if ((fd2 = dup2(fd1, rlp.rlim_cur + 1)) == 0) + if ((fd2 = dup2(fd1, rlp.rlim_cur + 1)) >= 0) printf("not ok %d - dup2(2) bypassed NOFILE limit\n", test); else printf("ok %d - dup2(2) didn't bypass NOFILE limit\n", test); + /* If fcntl(F_DUP2FD) ever work? */ + if ((fd2 = fcntl(fd1, F_DUP2FD, fd1 + 1)) < 0) + err(1, "fcntl(F_DUP2FD)"); + printf("ok %d - fcntl(F_DUP2FD) works\n", ++test); + + /* Do we get the right fd? */ + ++test; + if (fd2 != fd1 + 1) + printf( + "no ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n", + test); + else + printf("ok %d - fcntl(F_DUP2FD) returned a correct fd\n", + test); + + /* Was close-on-exec cleared? */ + ++test; + if (fcntl(fd2, F_GETFD) != 0) + printf( + "not ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n", + test); + else + printf("ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n", + test); + + /* Dup to itself */ + if ((fd2 = fcntl(fd1, F_DUP2FD, fd1)) < 0) + err(1, "fcntl(F_DUP2FD)"); + printf("ok %d - fcntl(F_DUP2FD) to itself works\n", ++test); + + /* Do we get the right fd? */ + ++test; + if (fd2 != fd1) + printf( + "not ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n", + test); + else + printf( + "ok %d - fcntl(F_DUP2FD) to itself returned a correct fd\n", + test); + + /* Was close-on-exec cleared? */ + ++test; + if (fcntl(fd2, F_GETFD) == 0) + printf("not ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n", + test); + else + printf("ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n", + test); + + ++test; + if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) + err(1, "getrlimit"); + if ((fd2 = fcntl(fd1, F_DUP2FD, rlp.rlim_cur + 1)) >= 0) + printf("not ok %d - fcntl(F_DUP2FD) bypassed NOFILE limit\n", + test); + else + printf("ok %d - fcntl(F_DUP2FD) didn't bypass NOFILE limit\n", + test); + return (0); } |