Date: Sun, 3 Feb 2008 07:12:37 GMT From: Jukka Ukkonen <jau@iki.fi> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/120233: FreeBSD is missing fcntl() operation F_DUP2FD Message-ID: <200802030712.m137CbA1032766@www.freebsd.org> Resent-Message-ID: <200802030720.m137K0vX081416@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 120233 >Category: kern >Synopsis: FreeBSD is missing fcntl() operation F_DUP2FD >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sun Feb 03 07:20:00 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Jukka Ukkonen >Release: FreeBSD 6.3-STABLE >Organization: private person >Environment: FreeBSD mjolnir 6.3-STABLE FreeBSD 6.3-STABLE #0: Sat Feb 2 12:48:48 EET 2008 root@mjolnir:/usr/obj/usr/src/sys/Mjolnir i386 >Description: This is a compatibility issue. At least SunOS/Solaris and AIX both have an fcntl() operation F_DUP2FD which is to dup2() as F_DUPFD is to dup(). Having support to this fcntl() operation would improve software portability between FreeBSD and other UNIX style systems. Additionally it would allow both dup() and dup2() be implemented as library functions narrowing down the system call API. This PR supersedes the 3.5 years old kern/70798 which provided the same feature for FreeBSD-4.10. The old ticket is still in the state open and nobody has cared as much as to say a simple "no" since its introduction. This PR contains an upgraded patch against FreeBSD-6.3 sources implementing the F_DUP2FD operation and a test program to show F_DUP2FD in action, if it is supported. I have had this modification in my own environments for some 4 years starting from FreeBSD-4.x with no ill effects. In fact in my own C library I have both dup() and dup2() only as wrappers for fcntl() and everything works just fine. >How-To-Repeat: Try the test program shown below before and after applying the patch and notice the difference in its output. #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <stdio.h> #include <errno.h> static void dumpstat (st) struct stat *st; { printf ("st_dev = %ld\n", (long) st->st_dev); printf ("st_ino = %ld\n", (long) st->st_ino); printf ("st_nlink = %ld\n", (long) st->st_nlink); printf ("st_uid = %ld\n", (long) st->st_uid); printf ("st_gid = %ld\n", (long) st->st_gid); printf ("st_rdev = %ld\n", (long) st->st_rdev); } static void viewfdstat (fd) int fd; { struct stat st1; if (fstat (fd, &st1) < 0) { fprintf (stderr, "fstat(%d): %s\n", fd, strerror (errno)); } else { printf ("fstat(%d):\n", fd); dumpstat (&st1); } } int main (ac, av) int ac; char *av[]; { int fd; viewfdstat (0); fd = open ("/dev/null", O_RDWR, 0); viewfdstat (fd); #ifndef F_DUP2FD #define F_DUP2FD F_DUPFD #warning This system does not support F_DUP2FD. #endif if (fcntl (fd, F_DUP2FD, 0) < 0) { fprintf (stderr, "fcntl(%d, F_DUP2FD, 0): %s\n", fd, strerror (errno)); } viewfdstat (0); return (0); } >Fix: Apply the attached patch. Patch attached with submission follows: --- sys/sys/fcntl.h.orig 2008-02-02 07:45:25.000000000 +0200 +++ sys/sys/fcntl.h 2008-02-02 07:47:21.000000000 +0200 @@ -176,6 +176,7 @@ #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, fixed */ /* file descriptor flags (F_GETFD, F_SETFD) */ #define FD_CLOEXEC 1 /* close-on-exec flag */ --- sys/kern/kern_descrip.c.orig 2008-02-02 07:39:50.000000000 +0200 +++ sys/kern/kern_descrip.c 2008-02-02 07:41:31.000000000 +0200 @@ -365,6 +365,7 @@ */ switch (cmd) { case F_DUPFD: + case F_DUP2FD: case F_GETFD: case F_SETFD: case F_GETFL: @@ -405,6 +406,21 @@ error = do_dup(td, DUP_VARIABLE, fd, newmin, td->td_retval); break; + case F_DUP2FD: + /* mtx_assert(&Giant, MA_NOTOWNED); */ + FILEDESC_UNLOCK(fdp); + newmin = arg; + PROC_LOCK(p); + if (newmin >= lim_cur(p, RLIMIT_NOFILE) || + newmin >= maxfilesperproc) { + PROC_UNLOCK(p); + error = EINVAL; + break; + } + PROC_UNLOCK(p); + error = do_dup(td, DUP_FIXED, fd, newmin, td->td_retval); + break; + case F_GETFD: /* mtx_assert(&Giant, MA_NOTOWNED); */ td->td_retval[0] = (*pop & UF_EXCLOSE) ? FD_CLOEXEC : 0; >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200802030712.m137CbA1032766>