-.\" Hey Emacs! This file is -*- nroff -*- source.
-.\"
.\" This manpage is Copyright (C) 1992 Drew Eckhardt;
.\" and Copyright (C) 1993 Michael Haardt, Ian Jackson.
.\" and Copyright (C) 2005, 2008 Michael Kerrisk <mtk.manpages@gmail.com>
+.\" and Copyright (C) 2014 Michael Kerrisk <mtk.manpages@gmail.com>
.\"
+.\" %%%LICENSE_START(VERBATIM)
.\" Permission is granted to make and distribute verbatim copies of this
.\" manual provided the copyright notice and this permission notice are
.\" preserved on all copies.
.\"
.\" Formatted or processed versions of this manual, if unaccompanied by
.\" the source, must acknowledge the copyright and authors of this work.
+.\" %%%LICENSE_END
.\"
.\" Modified 1993-07-21, Rik Faith <faith@cs.unc.edu>
.\" Modified 1994-08-21, Michael Chastain <mec@shell.portal.com>:
.\" details for dup2().
.\" 2008-10-09, mtk: add description of dup3()
.\"
-.TH DUP 2 2012-02-14 "Linux" "Linux Programmer's Manual"
+.TH DUP 2 2015-01-22 "Linux" "Linux Programmer's Manual"
.SH NAME
dup, dup2, dup3 \- duplicate a file descriptor
.SH SYNOPSIS
.BI "int dup3(int " oldfd ", int " newfd ", int " flags );
.fi
.SH DESCRIPTION
-These system calls create a copy of the file descriptor
-.IR oldfd .
-
+The
.BR dup ()
-uses the lowest-numbered unused descriptor for the new descriptor.
+system call creates a copy of the file descriptor
+.IR oldfd ,
+using the lowest-numbered unused descriptor for the new descriptor.
+After a successful return,
+the old and new file descriptors may be used interchangeably.
+They refer to the same open file description (see
+.BR open (2))
+and thus share file offset and file status flags;
+for example, if the file offset is modified by using
+.BR lseek (2)
+on one of the descriptors, the offset is also changed for the other.
+
+The two descriptors do not share file descriptor flags
+(the close-on-exec flag).
+The close-on-exec flag
+.RB ( FD_CLOEXEC ;
+see
+.BR fcntl (2))
+for the duplicate descriptor is off.
+.\"
+.SS dup2()
+The
.BR dup2 ()
-.RI "makes " newfd " be the copy of " oldfd ", closing " newfd
-first if necessary, but note the following:
+system call performs the same task as
+.BR dup (),
+but instead of using the lowest-numbered unused file descriptor,
+it uses the descriptor number specified in
+.IR newfd .
+If the descriptor
+.IR newfd
+was previously open, it is silently closed before being reused.
+
+The steps of closing and reusing the file descriptor
+.IR newfd
+are performed
+.IR atomically .
+This is important, because trying to implement equivalent functionality using
+.BR close (2)
+and
+.BR dup ()
+would be
+subject to race conditions, whereby
+.I newfd
+might be reused between the two steps.
+Such reuse could happen because the main program is interrupted
+by a signal handler that allocates a file descriptor,
+or because a parallel thread allocates a file descriptor.
+
+Note the following points:
.IP * 3
If
.I oldfd
.BR dup2 ()
does nothing, and returns
.IR newfd .
-.PP
-After a successful return from one of these system calls,
-the old and new file descriptors may be used interchangeably.
-They refer to the same open file description (see
-.BR open (2))
-and thus share file offset and file status flags;
-for example, if the file offset is modified by using
-.BR lseek (2)
-on one of the descriptors, the offset is also changed for the other.
-
-The two descriptors do not share file descriptor flags
-(the close-on-exec flag).
-The close-on-exec flag
-.RB ( FD_CLOEXEC ;
-see
-.BR fcntl (2))
-for the duplicate descriptor is off.
-
+.\"
+.SS dup3()
.BR dup3 ()
is the same as
.BR dup2 (),
.BR dup3 ()
fails with the error
.BR EINVAL .
-.SH "RETURN VALUE"
+.SH RETURN VALUE
On success, these system calls
return the new descriptor.
On error, \-1 is returned, and
.TP
.B EBADF
.I oldfd
-isn't an open file descriptor, or
+isn't an open file descriptor.
+.TP
+.B EBADF
.I newfd
-is out of the allowed range for file descriptors.
+is out of the allowed range for file descriptors (see the discussion of
+.BR RLIMIT_NOFILE
+in
+.BR getrlimit (2)).
.TP
.B EBUSY
(Linux only) This may be returned by
.RB ( dup3 ())
.I flags
contain an invalid value.
+.TP
+.B EINVAL
+.RB ( dup3 ())
.\" FIXME . To confirm with Al Viro that this was intended, and its rationale
-Or,
.I oldfd
was equal to
.IR newfd .
.TP
.B EMFILE
The process already has the maximum number of file
-descriptors open and tried to open a new one.
+descriptors open and tried to open a new one (see the discussion of
+.BR RLIMIT_NOFILE
+in
+.BR getrlimit (2)).
.SH VERSIONS
.BR dup3 ()
was added to Linux in version 2.6.27;
glibc support is available starting with
version 2.9.
-.SH "CONFORMING TO"
+.SH CONFORMING TO
.BR dup (),
.BR dup2 ():
SVr4, 4.3BSD, POSIX.1-2001.
when
.I newfd
is out of range.
-On some systems
+On some systems,
.BR dup2 ()
also sometimes returns
.B EINVAL
was open, any errors that would have been reported at
.BR close (2)
time are lost.
-A careful programmer will not use
-.BR dup2 ()
-or
-.BR dup3 ()
-without closing
+If this is of concern,
+then\(emunless the program is single-threaded and does not allocate
+file descriptors in signal handlers\(emthe correct approach is
+.I not
+to close
.I newfd
-first.
-.SH "SEE ALSO"
+before calling
+.BR dup2 (),
+because of the race condition described above.
+Instead, code something like the following could be used:
+
+.nf
+ /* Obtain a duplicate of 'newfd' that can subsequently
+ be used to check for close() errors; an EBADF error
+ means that 'newfd' was not open. */
+
+ tmpfd = dup(newfd);
+ if (tmpfd == \-1 && errno != EBADF) {
+ /* Handle unexpected dup() error */
+ }
+
+ /* Atomically duplicate 'oldfd' on 'newfd' */
+
+ if (dup2(oldfd, newfd) == \-1) {
+ /* Handle dup2() error */
+ }
+
+ /* Now check for close() errors on the file originally
+ referred to by 'newfd' */
+
+ if (tmpfd != \-1) {
+ if (close(tmpfd) == \-1) {
+ /* Handle errors from close */
+ }
+ }
+.fi
+.SH SEE ALSO
.BR close (2),
.BR fcntl (2),
.BR open (2)
+.SH COLOPHON
+This page is part of release 3.79 of the Linux
+.I man-pages
+project.
+A description of the project,
+information about reporting bugs,
+and the latest version of this page,
+can be found at
+\%http://www.kernel.org/doc/man\-pages/.