1 //! Functions which duplicate file descriptors.
2 
3 use crate::fd::OwnedFd;
4 use crate::{backend, io};
5 use backend::fd::AsFd;
6 
7 #[cfg(not(target_os = "wasi"))]
8 pub use backend::io::types::DupFlags;
9 
10 /// `dup(fd)`—Creates a new `OwnedFd` instance that shares the same
11 /// underlying [file description] as `fd`.
12 ///
13 /// This function does not set the `O_CLOEXEC` flag. To do a `dup` that does
14 /// set `O_CLOEXEC`, use [`fcntl_dupfd_cloexec`].
15 ///
16 /// POSIX guarantees that `dup` will use the lowest unused file descriptor,
17 /// however it is not safe in general to rely on this, as file descriptors may
18 /// be unexpectedly allocated on other threads or in libraries.
19 ///
20 /// # References
21 ///  - [POSIX]
22 ///  - [Linux]
23 ///  - [Apple]
24 ///  - [FreeBSD]
25 ///  - [NetBSD]
26 ///  - [OpenBSD]
27 ///  - [DragonFly BSD]
28 ///  - [illumos]
29 ///  - [glibc]
30 ///
31 /// [file description]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_258
32 /// [`fcntl_dupfd_cloexec`]: crate::io::fcntl_dupfd_cloexec
33 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html
34 /// [Linux]: https://man7.org/linux/man-pages/man2/dup.2.html
35 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/dup.2.html
36 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=dup&sektion=2
37 /// [NetBSD]: https://man.netbsd.org/dup.2
38 /// [OpenBSD]: https://man.openbsd.org/dup.2
39 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=dup&section=2
40 /// [illumos]: https://illumos.org/man/2/dup
41 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Duplicating-Descriptors.html
42 #[cfg(not(target_os = "wasi"))]
43 #[inline]
dup<Fd: AsFd>(fd: Fd) -> io::Result<OwnedFd>44 pub fn dup<Fd: AsFd>(fd: Fd) -> io::Result<OwnedFd> {
45     backend::io::syscalls::dup(fd.as_fd())
46 }
47 
48 /// `dup2(fd, new)`—Changes the [file description] of a file descriptor.
49 ///
50 /// `dup2` conceptually closes `new` and then sets the file description for
51 /// `new` to be the same as the one for `fd`. This is a very unusual operation,
52 /// and should only be used on file descriptors where you know how `new` will
53 /// be subsequently used.
54 ///
55 /// This function does not set the `O_CLOEXEC` flag. To do a `dup2` that does
56 /// set `O_CLOEXEC`, use [`dup3`] with [`DupFlags::CLOEXEC`] on platforms which
57 /// support it, or [`fcntl_dupfd_cloexec`]
58 ///
59 /// For `dup2` to stdin, stdout, and stderr, see [`stdio::dup2_stdin`],
60 /// [`stdio::dup2_stdout`], and [`stdio::dup2_stderr`].
61 ///
62 /// # References
63 ///  - [POSIX]
64 ///  - [Linux]
65 ///  - [Apple]
66 ///  - [FreeBSD]
67 ///  - [NetBSD]
68 ///  - [OpenBSD]
69 ///  - [DragonFly BSD]
70 ///  - [illumos]
71 ///  - [glibc]
72 ///
73 /// [file description]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_258
74 /// [`fcntl_dupfd_cloexec`]: crate::io::fcntl_dupfd_cloexec
75 /// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup2.html
76 /// [Linux]: https://man7.org/linux/man-pages/man2/dup2.2.html
77 /// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/dup2.2.html
78 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=dup2&sektion=2
79 /// [NetBSD]: https://man.netbsd.org/dup2.2
80 /// [OpenBSD]: https://man.openbsd.org/dup2.2
81 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=dup2&section=2
82 /// [illumos]: https://illumos.org/man/2/dup
83 /// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Duplicating-Descriptors.html
84 /// [`stdio::dup2_stdin`]: https://docs.rs/rustix/*/rustix/stdio/fn.dup2_stdin.html
85 /// [`stdio::dup2_stdout`]: https://docs.rs/rustix/*/rustix/stdio/fn.dup2_stdout.html
86 /// [`stdio::dup2_stderr`]: https://docs.rs/rustix/*/rustix/stdio/fn.dup2_stderr.html
87 #[cfg(not(target_os = "wasi"))]
88 #[inline]
dup2<Fd: AsFd>(fd: Fd, new: &mut OwnedFd) -> io::Result<()>89 pub fn dup2<Fd: AsFd>(fd: Fd, new: &mut OwnedFd) -> io::Result<()> {
90     backend::io::syscalls::dup2(fd.as_fd(), new)
91 }
92 
93 /// `dup3(fd, new, flags)`—Changes the [file description] of a file
94 /// descriptor, with flags.
95 ///
96 /// `dup3` is the same as [`dup2`] but adds an additional flags operand, and it
97 /// fails in the case that `fd` and `new` have the same file descriptor value.
98 /// This additional difference is the reason this function isn't named
99 /// `dup2_with`.
100 ///
101 /// # References
102 ///  - [Linux]
103 ///  - [FreeBSD]
104 ///  - [NetBSD]
105 ///  - [OpenBSD]
106 ///  - [DragonFly BSD]
107 ///
108 /// [file description]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_258
109 /// [Linux]: https://man7.org/linux/man-pages/man2/dup3.2.html
110 /// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=dup3&sektion=3
111 /// [NetBSD]: https://man.netbsd.org/dup3.2
112 /// [OpenBSD]: https://man.openbsd.org/dup3.2
113 /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=dup3&section=3
114 #[cfg(not(any(
115     target_os = "aix",
116     target_os = "espidf",
117     target_os = "nto",
118     target_os = "vita",
119     target_os = "wasi"
120 )))]
121 #[inline]
dup3<Fd: AsFd>(fd: Fd, new: &mut OwnedFd, flags: DupFlags) -> io::Result<()>122 pub fn dup3<Fd: AsFd>(fd: Fd, new: &mut OwnedFd, flags: DupFlags) -> io::Result<()> {
123     backend::io::syscalls::dup3(fd.as_fd(), new, flags)
124 }
125