Skip to main content

std/os/fd/
raw.rs

1//! Raw Unix-like file descriptors.
2
3#![stable(feature = "rust1", since = "1.0.0")]
4
5#[cfg(target_os = "hermit")]
6use hermit_abi as libc;
7#[cfg(target_os = "motor")]
8use moto_rt::libc;
9
10#[cfg(target_os = "motor")]
11use super::owned::OwnedFd;
12use crate::alloc::Allocator;
13#[cfg(not(target_os = "trusty"))]
14use crate::fs;
15use crate::io;
16#[cfg(target_os = "hermit")]
17use crate::os::hermit::io::OwnedFd;
18#[cfg(all(not(target_os = "hermit"), not(target_os = "motor")))]
19use crate::os::raw;
20#[cfg(all(doc, not(any(target_arch = "wasm32", target_env = "sgx", target_os = "l4re"))))]
21use crate::os::unix::io::AsFd;
22#[cfg(unix)]
23use crate::os::unix::io::OwnedFd;
24#[cfg(target_os = "wasi")]
25use crate::os::wasi::io::OwnedFd;
26#[cfg(not(target_os = "trusty"))]
27use crate::sys::{AsInner, FromInner, IntoInner};
28
29/// Raw file descriptors.
30#[stable(feature = "rust1", since = "1.0.0")]
31#[cfg(all(not(target_os = "hermit"), not(target_os = "motor")))]
32pub type RawFd = raw::c_int;
33#[stable(feature = "rust1", since = "1.0.0")]
34#[cfg(any(target_os = "hermit", target_os = "motor"))]
35pub type RawFd = i32;
36
37/// A trait to extract the raw file descriptor from an underlying object.
38///
39/// This is only available on unix and WASI platforms and must be imported in
40/// order to call the method. Windows platforms have a corresponding
41/// `AsRawHandle` and `AsRawSocket` set of traits.
42#[stable(feature = "rust1", since = "1.0.0")]
43pub trait AsRawFd {
44    /// Extracts the raw file descriptor.
45    ///
46    /// This function is typically used to **borrow** an owned file descriptor.
47    /// When used in this way, this method does **not** pass ownership of the
48    /// raw file descriptor to the caller, and the file descriptor is only
49    /// guaranteed to be valid while the original object has not yet been
50    /// destroyed.
51    ///
52    /// However, borrowing is not strictly required. See [`AsFd::as_fd`]
53    /// for an API which strictly borrows a file descriptor.
54    ///
55    /// # Example
56    ///
57    /// ```no_run
58    /// use std::fs::File;
59    /// # use std::io;
60    /// #[cfg(any(unix, target_os = "wasi"))]
61    /// use std::os::fd::{AsRawFd, RawFd};
62    ///
63    /// let mut f = File::open("foo.txt")?;
64    /// // Note that `raw_fd` is only valid as long as `f` exists.
65    /// #[cfg(any(unix, target_os = "wasi"))]
66    /// let raw_fd: RawFd = f.as_raw_fd();
67    /// # Ok::<(), io::Error>(())
68    /// ```
69    #[stable(feature = "rust1", since = "1.0.0")]
70    fn as_raw_fd(&self) -> RawFd;
71}
72
73/// A trait to express the ability to construct an object from a raw file
74/// descriptor.
75#[stable(feature = "from_raw_os", since = "1.1.0")]
76pub trait FromRawFd {
77    /// Constructs a new instance of `Self` from the given raw file
78    /// descriptor.
79    ///
80    /// This function is typically used to **consume ownership** of the
81    /// specified file descriptor. When used in this way, the returned object
82    /// will take responsibility for closing it when the object goes out of
83    /// scope.
84    ///
85    /// However, consuming ownership is not strictly required. Use a
86    /// [`From<OwnedFd>::from`] implementation for an API which strictly
87    /// consumes ownership.
88    ///
89    /// # Safety
90    ///
91    /// The `fd` passed in must be an [owned file descriptor][io-safety];
92    /// in particular, it must be open.
93    ///
94    /// [io-safety]: io#io-safety
95    ///
96    /// # Example
97    ///
98    /// ```no_run
99    /// use std::fs::File;
100    /// # use std::io;
101    /// #[cfg(any(unix, target_os = "wasi"))]
102    /// use std::os::fd::{FromRawFd, IntoRawFd, RawFd};
103    ///
104    /// let f = File::open("foo.txt")?;
105    /// # #[cfg(any(unix, target_os = "wasi"))]
106    /// let raw_fd: RawFd = f.into_raw_fd();
107    /// // SAFETY: no other functions should call `from_raw_fd`, so there
108    /// // is only one owner for the file descriptor.
109    /// # #[cfg(any(unix, target_os = "wasi"))]
110    /// let f = unsafe { File::from_raw_fd(raw_fd) };
111    /// # Ok::<(), io::Error>(())
112    /// ```
113    #[stable(feature = "from_raw_os", since = "1.1.0")]
114    unsafe fn from_raw_fd(fd: RawFd) -> Self;
115}
116
117/// A trait to express the ability to consume an object and acquire ownership of
118/// its raw file descriptor.
119#[stable(feature = "into_raw_os", since = "1.4.0")]
120pub trait IntoRawFd {
121    /// Consumes this object, returning the raw underlying file descriptor.
122    ///
123    /// This function is typically used to **transfer ownership** of the underlying
124    /// file descriptor to the caller. When used in this way, callers are then the unique
125    /// owners of the file descriptor and must close it once it's no longer needed.
126    ///
127    /// However, transferring ownership is not strictly required. Use a
128    /// [`Into<OwnedFd>::into`] implementation for an API which strictly
129    /// transfers ownership.
130    ///
131    /// # Example
132    ///
133    /// ```no_run
134    /// use std::fs::File;
135    /// # use std::io;
136    /// #[cfg(any(unix, target_os = "wasi"))]
137    /// use std::os::fd::{IntoRawFd, RawFd};
138    ///
139    /// let f = File::open("foo.txt")?;
140    /// #[cfg(any(unix, target_os = "wasi"))]
141    /// let raw_fd: RawFd = f.into_raw_fd();
142    /// # Ok::<(), io::Error>(())
143    /// ```
144    #[must_use = "losing the raw file descriptor may leak resources"]
145    #[stable(feature = "into_raw_os", since = "1.4.0")]
146    fn into_raw_fd(self) -> RawFd;
147}
148
149#[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")]
150impl AsRawFd for RawFd {
151    #[inline]
152    fn as_raw_fd(&self) -> RawFd {
153        *self
154    }
155}
156#[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")]
157impl IntoRawFd for RawFd {
158    #[inline]
159    fn into_raw_fd(self) -> RawFd {
160        self
161    }
162}
163#[stable(feature = "raw_fd_reflexive_traits", since = "1.48.0")]
164impl FromRawFd for RawFd {
165    #[inline]
166    unsafe fn from_raw_fd(fd: RawFd) -> RawFd {
167        fd
168    }
169}
170
171#[stable(feature = "rust1", since = "1.0.0")]
172#[cfg(not(target_os = "trusty"))]
173impl AsRawFd for fs::File {
174    #[inline]
175    fn as_raw_fd(&self) -> RawFd {
176        self.as_inner().as_raw_fd()
177    }
178}
179#[stable(feature = "from_raw_os", since = "1.1.0")]
180#[cfg(not(target_os = "trusty"))]
181impl FromRawFd for fs::File {
182    #[inline]
183    unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
184        unsafe { fs::File::from(OwnedFd::from_raw_fd(fd)) }
185    }
186}
187#[stable(feature = "into_raw_os", since = "1.4.0")]
188#[cfg(not(target_os = "trusty"))]
189impl IntoRawFd for fs::File {
190    #[inline]
191    fn into_raw_fd(self) -> RawFd {
192        self.into_inner().into_inner().into_raw_fd()
193    }
194}
195
196#[stable(feature = "asraw_stdio", since = "1.21.0")]
197#[cfg(not(target_os = "trusty"))]
198impl AsRawFd for io::Stdin {
199    #[inline]
200    fn as_raw_fd(&self) -> RawFd {
201        libc::STDIN_FILENO
202    }
203}
204
205#[stable(feature = "asraw_stdio", since = "1.21.0")]
206impl AsRawFd for io::Stdout {
207    #[inline]
208    fn as_raw_fd(&self) -> RawFd {
209        libc::STDOUT_FILENO
210    }
211}
212
213#[stable(feature = "asraw_stdio", since = "1.21.0")]
214impl AsRawFd for io::Stderr {
215    #[inline]
216    fn as_raw_fd(&self) -> RawFd {
217        libc::STDERR_FILENO
218    }
219}
220
221#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
222#[cfg(not(target_os = "trusty"))]
223impl<'a> AsRawFd for io::StdinLock<'a> {
224    #[inline]
225    fn as_raw_fd(&self) -> RawFd {
226        libc::STDIN_FILENO
227    }
228}
229
230#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
231impl<'a> AsRawFd for io::StdoutLock<'a> {
232    #[inline]
233    fn as_raw_fd(&self) -> RawFd {
234        libc::STDOUT_FILENO
235    }
236}
237
238#[stable(feature = "asraw_stdio_locks", since = "1.35.0")]
239impl<'a> AsRawFd for io::StderrLock<'a> {
240    #[inline]
241    fn as_raw_fd(&self) -> RawFd {
242        libc::STDERR_FILENO
243    }
244}
245
246/// This impl allows implementing traits that require `AsRawFd` on Arc.
247/// ```
248/// # #[cfg(any(unix, target_os = "wasi"))] mod group_cfg {
249/// # #[cfg(target_os = "wasi")]
250/// # use std::os::wasi::io::AsRawFd;
251/// # #[cfg(unix)]
252/// # use std::os::unix::io::AsRawFd;
253/// use std::net::UdpSocket;
254/// use std::sync::Arc;
255/// trait MyTrait: AsRawFd {
256/// }
257/// impl MyTrait for Arc<UdpSocket> {}
258/// impl MyTrait for Box<UdpSocket> {}
259/// # }
260/// ```
261#[stable(feature = "asrawfd_ptrs", since = "1.63.0")]
262impl<T: AsRawFd> AsRawFd for crate::sync::Arc<T> {
263    #[inline]
264    fn as_raw_fd(&self) -> RawFd {
265        (**self).as_raw_fd()
266    }
267}
268
269#[stable(feature = "asfd_rc", since = "1.69.0")]
270impl<T: AsRawFd> AsRawFd for crate::rc::Rc<T> {
271    #[inline]
272    fn as_raw_fd(&self) -> RawFd {
273        (**self).as_raw_fd()
274    }
275}
276
277#[unstable(feature = "unique_rc_arc", issue = "112566")]
278impl<T: AsRawFd + ?Sized> AsRawFd for crate::rc::UniqueRc<T> {
279    #[inline]
280    fn as_raw_fd(&self) -> RawFd {
281        (**self).as_raw_fd()
282    }
283}
284
285#[stable(feature = "asrawfd_ptrs", since = "1.63.0")]
286impl<T: AsRawFd, A: Allocator> AsRawFd for Box<T, A> {
287    #[inline]
288    fn as_raw_fd(&self) -> RawFd {
289        (**self).as_raw_fd()
290    }
291}
292
293#[stable(feature = "anonymous_pipe", since = "1.87.0")]
294#[cfg(not(target_os = "trusty"))]
295impl AsRawFd for io::PipeReader {
296    fn as_raw_fd(&self) -> RawFd {
297        self.0.as_raw_fd()
298    }
299}
300
301#[stable(feature = "anonymous_pipe", since = "1.87.0")]
302#[cfg(not(target_os = "trusty"))]
303impl FromRawFd for io::PipeReader {
304    unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
305        Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) })
306    }
307}
308
309#[stable(feature = "anonymous_pipe", since = "1.87.0")]
310#[cfg(not(target_os = "trusty"))]
311impl IntoRawFd for io::PipeReader {
312    fn into_raw_fd(self) -> RawFd {
313        self.0.into_raw_fd()
314    }
315}
316
317#[stable(feature = "anonymous_pipe", since = "1.87.0")]
318#[cfg(not(target_os = "trusty"))]
319impl AsRawFd for io::PipeWriter {
320    fn as_raw_fd(&self) -> RawFd {
321        self.0.as_raw_fd()
322    }
323}
324
325#[stable(feature = "anonymous_pipe", since = "1.87.0")]
326#[cfg(not(target_os = "trusty"))]
327impl FromRawFd for io::PipeWriter {
328    unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
329        Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) })
330    }
331}
332
333#[stable(feature = "anonymous_pipe", since = "1.87.0")]
334#[cfg(not(target_os = "trusty"))]
335impl IntoRawFd for io::PipeWriter {
336    fn into_raw_fd(self) -> RawFd {
337        self.0.into_raw_fd()
338    }
339}