]> git.proxmox.com Git - rustc.git/blame - library/std/src/os/fd/owned.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / library / std / src / os / fd / owned.rs
CommitLineData
94222f64
XL
1//! Owned and borrowed Unix-like file descriptors.
2
923072b8 3#![stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
4#![deny(unsafe_op_in_unsafe_fn)]
5
6use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
7use crate::fmt;
8use crate::fs;
9use crate::marker::PhantomData;
10use crate::mem::forget;
04454e1e 11#[cfg(not(any(target_arch = "wasm32", target_env = "sgx")))]
5099ac24 12use crate::sys::cvt;
94222f64
XL
13use crate::sys_common::{AsInner, FromInner, IntoInner};
14
15/// A borrowed file descriptor.
16///
17/// This has a lifetime parameter to tie it to the lifetime of something that
18/// owns the file descriptor.
19///
20/// This uses `repr(transparent)` and has the representation of a host file
21/// descriptor, so it can be used in FFI in places where a file descriptor is
22/// passed as an argument, it is not captured or consumed, and it never has the
23/// value `-1`.
5e7ed085
FG
24///
25/// This type's `.to_owned()` implementation returns another `BorrowedFd`
26/// rather than an `OwnedFd`. It just makes a trivial copy of the raw file
27/// descriptor, which is then borrowed under the same lifetime.
94222f64
XL
28#[derive(Copy, Clone)]
29#[repr(transparent)]
30#[rustc_layout_scalar_valid_range_start(0)]
31// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
32// 32-bit c_int. Below is -2, in two's complement, but that only works out
33// because c_int is 32 bits.
34#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
923072b8
FG
35#[rustc_nonnull_optimization_guaranteed]
36#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
37pub struct BorrowedFd<'fd> {
38 fd: RawFd,
39 _phantom: PhantomData<&'fd OwnedFd>,
40}
41
42/// An owned file descriptor.
43///
44/// This closes the file descriptor on drop.
45///
46/// This uses `repr(transparent)` and has the representation of a host file
47/// descriptor, so it can be used in FFI in places where a file descriptor is
48/// passed as a consumed argument or returned as an owned value, and it never
49/// has the value `-1`.
50#[repr(transparent)]
51#[rustc_layout_scalar_valid_range_start(0)]
52// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
53// 32-bit c_int. Below is -2, in two's complement, but that only works out
54// because c_int is 32 bits.
55#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
923072b8
FG
56#[rustc_nonnull_optimization_guaranteed]
57#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
58pub struct OwnedFd {
59 fd: RawFd,
60}
61
62impl BorrowedFd<'_> {
63 /// Return a `BorrowedFd` holding the given raw file descriptor.
64 ///
65 /// # Safety
66 ///
67 /// The resource pointed to by `fd` must remain open for the duration of
68 /// the returned `BorrowedFd`, and it must not have the value `-1`.
69 #[inline]
923072b8
FG
70 #[rustc_const_stable(feature = "io_safety", since = "1.63.0")]
71 #[stable(feature = "io_safety", since = "1.63.0")]
04454e1e
FG
72 pub const unsafe fn borrow_raw(fd: RawFd) -> Self {
73 assert!(fd != u32::MAX as RawFd);
94222f64
XL
74 // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
75 unsafe { Self { fd, _phantom: PhantomData } }
76 }
77}
78
5099ac24 79impl OwnedFd {
923072b8
FG
80 /// Creates a new `OwnedFd` instance that shares the same underlying file
81 /// description as the existing `OwnedFd` instance.
82 #[stable(feature = "io_safety", since = "1.63.0")]
5099ac24 83 pub fn try_clone(&self) -> crate::io::Result<Self> {
923072b8
FG
84 self.as_fd().try_clone_to_owned()
85 }
86}
87
88impl BorrowedFd<'_> {
89 /// Creates a new `OwnedFd` instance that shares the same underlying file
90 /// description as the existing `BorrowedFd` instance.
91 #[cfg(not(target_arch = "wasm32"))]
92 #[stable(feature = "io_safety", since = "1.63.0")]
93 pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
5099ac24
FG
94 // We want to atomically duplicate this file descriptor and set the
95 // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
96 // is a POSIX flag that was added to Linux in 2.6.24.
97 #[cfg(not(target_os = "espidf"))]
98 let cmd = libc::F_DUPFD_CLOEXEC;
99
100 // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics
101 // will never be supported, as this is a bare metal framework with
102 // no capabilities for multi-process execution. While F_DUPFD is also
103 // not supported yet, it might be (currently it returns ENOSYS).
104 #[cfg(target_os = "espidf")]
105 let cmd = libc::F_DUPFD;
106
107 let fd = cvt(unsafe { libc::fcntl(self.as_raw_fd(), cmd, 0) })?;
923072b8 108 Ok(unsafe { OwnedFd::from_raw_fd(fd) })
5099ac24
FG
109 }
110
923072b8
FG
111 /// Creates a new `OwnedFd` instance that shares the same underlying file
112 /// description as the existing `BorrowedFd` instance.
04454e1e 113 #[cfg(target_arch = "wasm32")]
923072b8
FG
114 #[stable(feature = "io_safety", since = "1.63.0")]
115 pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
5099ac24
FG
116 Err(crate::io::const_io_error!(
117 crate::io::ErrorKind::Unsupported,
118 "operation not supported on WASI yet",
119 ))
120 }
121}
122
923072b8 123#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
124impl AsRawFd for BorrowedFd<'_> {
125 #[inline]
126 fn as_raw_fd(&self) -> RawFd {
127 self.fd
128 }
129}
130
923072b8 131#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
132impl AsRawFd for OwnedFd {
133 #[inline]
134 fn as_raw_fd(&self) -> RawFd {
135 self.fd
136 }
137}
138
923072b8 139#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
140impl IntoRawFd for OwnedFd {
141 #[inline]
142 fn into_raw_fd(self) -> RawFd {
143 let fd = self.fd;
144 forget(self);
145 fd
146 }
147}
148
923072b8 149#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
150impl FromRawFd for OwnedFd {
151 /// Constructs a new instance of `Self` from the given raw file descriptor.
152 ///
153 /// # Safety
154 ///
155 /// The resource pointed to by `fd` must be open and suitable for assuming
156 /// ownership. The resource must not require any cleanup other than `close`.
157 #[inline]
158 unsafe fn from_raw_fd(fd: RawFd) -> Self {
159 assert_ne!(fd, u32::MAX as RawFd);
160 // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
161 unsafe { Self { fd } }
162 }
163}
164
923072b8 165#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
166impl Drop for OwnedFd {
167 #[inline]
168 fn drop(&mut self) {
169 unsafe {
170 // Note that errors are ignored when closing a file descriptor. The
171 // reason for this is that if an error occurs we don't actually know if
172 // the file descriptor was closed or not, and if we retried (for
173 // something like EINTR), we might close another valid file descriptor
174 // opened after we closed ours.
175 let _ = libc::close(self.fd);
176 }
177 }
178}
179
923072b8 180#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
181impl fmt::Debug for BorrowedFd<'_> {
182 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183 f.debug_struct("BorrowedFd").field("fd", &self.fd).finish()
184 }
185}
186
923072b8 187#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
188impl fmt::Debug for OwnedFd {
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 f.debug_struct("OwnedFd").field("fd", &self.fd).finish()
191 }
192}
193
194/// A trait to borrow the file descriptor from an underlying object.
195///
196/// This is only available on unix platforms and must be imported in order to
197/// call the method. Windows platforms have a corresponding `AsHandle` and
198/// `AsSocket` set of traits.
923072b8 199#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
200pub trait AsFd {
201 /// Borrows the file descriptor.
202 ///
203 /// # Example
204 ///
205 /// ```rust,no_run
94222f64
XL
206 /// use std::fs::File;
207 /// # use std::io;
208 /// # #[cfg(target_os = "wasi")]
209 /// # use std::os::wasi::io::{AsFd, BorrowedFd};
210 /// # #[cfg(unix)]
211 /// # use std::os::unix::io::{AsFd, BorrowedFd};
212 ///
213 /// let mut f = File::open("foo.txt")?;
214 /// # #[cfg(any(unix, target_os = "wasi"))]
215 /// let borrowed_fd: BorrowedFd<'_> = f.as_fd();
216 /// # Ok::<(), io::Error>(())
217 /// ```
923072b8 218 #[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
219 fn as_fd(&self) -> BorrowedFd<'_>;
220}
221
923072b8 222#[stable(feature = "io_safety", since = "1.63.0")]
5099ac24
FG
223impl<T: AsFd> AsFd for &T {
224 #[inline]
225 fn as_fd(&self) -> BorrowedFd<'_> {
226 T::as_fd(self)
227 }
228}
229
923072b8 230#[stable(feature = "io_safety", since = "1.63.0")]
5099ac24
FG
231impl<T: AsFd> AsFd for &mut T {
232 #[inline]
233 fn as_fd(&self) -> BorrowedFd<'_> {
234 T::as_fd(self)
235 }
236}
237
923072b8 238#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
239impl AsFd for BorrowedFd<'_> {
240 #[inline]
241 fn as_fd(&self) -> BorrowedFd<'_> {
242 *self
243 }
244}
245
923072b8 246#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
247impl AsFd for OwnedFd {
248 #[inline]
249 fn as_fd(&self) -> BorrowedFd<'_> {
250 // Safety: `OwnedFd` and `BorrowedFd` have the same validity
251 // invariants, and the `BorrowdFd` is bounded by the lifetime
252 // of `&self`.
5e7ed085 253 unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
94222f64
XL
254 }
255}
256
923072b8 257#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
258impl AsFd for fs::File {
259 #[inline]
260 fn as_fd(&self) -> BorrowedFd<'_> {
261 self.as_inner().as_fd()
262 }
263}
264
923072b8 265#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
266impl From<fs::File> for OwnedFd {
267 #[inline]
268 fn from(file: fs::File) -> OwnedFd {
269 file.into_inner().into_inner().into_inner()
270 }
271}
272
923072b8 273#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
274impl From<OwnedFd> for fs::File {
275 #[inline]
276 fn from(owned_fd: OwnedFd) -> Self {
277 Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned_fd)))
278 }
279}
280
923072b8 281#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
282impl AsFd for crate::net::TcpStream {
283 #[inline]
284 fn as_fd(&self) -> BorrowedFd<'_> {
285 self.as_inner().socket().as_fd()
286 }
287}
288
923072b8 289#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
290impl From<crate::net::TcpStream> for OwnedFd {
291 #[inline]
292 fn from(tcp_stream: crate::net::TcpStream) -> OwnedFd {
293 tcp_stream.into_inner().into_socket().into_inner().into_inner().into()
294 }
295}
296
923072b8 297#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
298impl From<OwnedFd> for crate::net::TcpStream {
299 #[inline]
300 fn from(owned_fd: OwnedFd) -> Self {
301 Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
302 owned_fd,
303 ))))
304 }
305}
306
923072b8 307#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
308impl AsFd for crate::net::TcpListener {
309 #[inline]
310 fn as_fd(&self) -> BorrowedFd<'_> {
311 self.as_inner().socket().as_fd()
312 }
313}
314
923072b8 315#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
316impl From<crate::net::TcpListener> for OwnedFd {
317 #[inline]
318 fn from(tcp_listener: crate::net::TcpListener) -> OwnedFd {
319 tcp_listener.into_inner().into_socket().into_inner().into_inner().into()
320 }
321}
322
923072b8 323#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
324impl From<OwnedFd> for crate::net::TcpListener {
325 #[inline]
326 fn from(owned_fd: OwnedFd) -> Self {
327 Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
328 owned_fd,
329 ))))
330 }
331}
332
923072b8 333#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
334impl AsFd for crate::net::UdpSocket {
335 #[inline]
336 fn as_fd(&self) -> BorrowedFd<'_> {
337 self.as_inner().socket().as_fd()
338 }
339}
340
923072b8 341#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
342impl From<crate::net::UdpSocket> for OwnedFd {
343 #[inline]
344 fn from(udp_socket: crate::net::UdpSocket) -> OwnedFd {
345 udp_socket.into_inner().into_socket().into_inner().into_inner().into()
346 }
347}
348
923072b8 349#[stable(feature = "io_safety", since = "1.63.0")]
94222f64
XL
350impl From<OwnedFd> for crate::net::UdpSocket {
351 #[inline]
352 fn from(owned_fd: OwnedFd) -> Self {
353 Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
354 owned_fd,
355 ))))
356 }
357}