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