1 | #![unstable (reason = "not public" , issue = "none" , feature = "fd" )] |
2 | |
3 | #[cfg (test)] |
4 | mod tests; |
5 | |
6 | #[cfg (not(any( |
7 | target_os = "linux" , |
8 | target_os = "l4re" , |
9 | target_os = "android" , |
10 | target_os = "hurd" , |
11 | )))] |
12 | use libc::off_t as off64_t; |
13 | #[cfg (any( |
14 | target_os = "android" , |
15 | target_os = "linux" , |
16 | target_os = "l4re" , |
17 | target_os = "hurd" , |
18 | ))] |
19 | use libc::off64_t; |
20 | |
21 | use crate::cmp; |
22 | use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read}; |
23 | use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; |
24 | use crate::sys::cvt; |
25 | use crate::sys_common::{AsInner, FromInner, IntoInner}; |
26 | |
27 | #[derive (Debug)] |
28 | pub struct FileDesc(OwnedFd); |
29 | |
30 | // The maximum read limit on most POSIX-like systems is `SSIZE_MAX`, |
31 | // with the man page quoting that if the count of bytes to read is |
32 | // greater than `SSIZE_MAX` the result is "unspecified". |
33 | // |
34 | // On Apple targets however, apparently the 64-bit libc is either buggy or |
35 | // intentionally showing odd behavior by rejecting any read with a size |
36 | // larger than or equal to INT_MAX. To handle both of these the read |
37 | // size is capped on both platforms. |
38 | const READ_LIMIT: usize = if cfg!(target_vendor = "apple" ) { |
39 | libc::c_int::MAX as usize - 1 |
40 | } else { |
41 | libc::ssize_t::MAX as usize |
42 | }; |
43 | |
44 | #[cfg (any( |
45 | target_os = "dragonfly" , |
46 | target_os = "freebsd" , |
47 | target_os = "netbsd" , |
48 | target_os = "openbsd" , |
49 | target_vendor = "apple" , |
50 | target_os = "cygwin" , |
51 | ))] |
52 | const fn max_iov() -> usize { |
53 | libc::IOV_MAX as usize |
54 | } |
55 | |
56 | #[cfg (any( |
57 | target_os = "android" , |
58 | target_os = "emscripten" , |
59 | target_os = "linux" , |
60 | target_os = "nto" , |
61 | ))] |
62 | const fn max_iov() -> usize { |
63 | libc::UIO_MAXIOV as usize |
64 | } |
65 | |
66 | #[cfg (not(any( |
67 | target_os = "android" , |
68 | target_os = "dragonfly" , |
69 | target_os = "emscripten" , |
70 | target_os = "freebsd" , |
71 | target_os = "linux" , |
72 | target_os = "netbsd" , |
73 | target_os = "nto" , |
74 | target_os = "openbsd" , |
75 | target_os = "horizon" , |
76 | target_os = "vita" , |
77 | target_vendor = "apple" , |
78 | target_os = "cygwin" , |
79 | )))] |
80 | const fn max_iov() -> usize { |
81 | 16 // The minimum value required by POSIX. |
82 | } |
83 | |
84 | impl FileDesc { |
85 | #[inline ] |
86 | pub fn try_clone(&self) -> io::Result<Self> { |
87 | self.duplicate() |
88 | } |
89 | |
90 | pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { |
91 | let ret = cvt(unsafe { |
92 | libc::read( |
93 | self.as_raw_fd(), |
94 | buf.as_mut_ptr() as *mut libc::c_void, |
95 | cmp::min(buf.len(), READ_LIMIT), |
96 | ) |
97 | })?; |
98 | Ok(ret as usize) |
99 | } |
100 | |
101 | #[cfg (not(any( |
102 | target_os = "espidf" , |
103 | target_os = "horizon" , |
104 | target_os = "vita" , |
105 | target_os = "nuttx" |
106 | )))] |
107 | pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
108 | let ret = cvt(unsafe { |
109 | libc::readv( |
110 | self.as_raw_fd(), |
111 | bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, |
112 | cmp::min(bufs.len(), max_iov()) as libc::c_int, |
113 | ) |
114 | })?; |
115 | Ok(ret as usize) |
116 | } |
117 | |
118 | #[cfg (any( |
119 | target_os = "espidf" , |
120 | target_os = "horizon" , |
121 | target_os = "vita" , |
122 | target_os = "nuttx" |
123 | ))] |
124 | pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
125 | io::default_read_vectored(|b| self.read(b), bufs) |
126 | } |
127 | |
128 | #[inline ] |
129 | pub fn is_read_vectored(&self) -> bool { |
130 | cfg!(not(any( |
131 | target_os = "espidf" , |
132 | target_os = "horizon" , |
133 | target_os = "vita" , |
134 | target_os = "nuttx" |
135 | ))) |
136 | } |
137 | |
138 | pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> { |
139 | let mut me = self; |
140 | (&mut me).read_to_end(buf) |
141 | } |
142 | |
143 | #[cfg_attr (target_os = "vxworks" , allow(unused_unsafe))] |
144 | pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> { |
145 | #[cfg (not(any( |
146 | all(target_os = "linux" , not(target_env = "musl" )), |
147 | target_os = "android" , |
148 | target_os = "hurd" |
149 | )))] |
150 | use libc::pread as pread64; |
151 | #[cfg (any( |
152 | all(target_os = "linux" , not(target_env = "musl" )), |
153 | target_os = "android" , |
154 | target_os = "hurd" |
155 | ))] |
156 | use libc::pread64; |
157 | |
158 | unsafe { |
159 | cvt(pread64( |
160 | self.as_raw_fd(), |
161 | buf.as_mut_ptr() as *mut libc::c_void, |
162 | cmp::min(buf.len(), READ_LIMIT), |
163 | offset as off64_t, |
164 | )) |
165 | .map(|n| n as usize) |
166 | } |
167 | } |
168 | |
169 | pub fn read_buf(&self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { |
170 | let ret = cvt(unsafe { |
171 | libc::read( |
172 | self.as_raw_fd(), |
173 | cursor.as_mut().as_mut_ptr() as *mut libc::c_void, |
174 | cmp::min(cursor.capacity(), READ_LIMIT), |
175 | ) |
176 | })?; |
177 | |
178 | // Safety: `ret` bytes were written to the initialized portion of the buffer |
179 | unsafe { |
180 | cursor.advance_unchecked(ret as usize); |
181 | } |
182 | Ok(()) |
183 | } |
184 | |
185 | #[cfg (any( |
186 | target_os = "aix" , |
187 | target_os = "dragonfly" , // DragonFly 1.5 |
188 | target_os = "emscripten" , |
189 | target_os = "freebsd" , |
190 | target_os = "fuchsia" , |
191 | target_os = "hurd" , |
192 | target_os = "illumos" , |
193 | target_os = "linux" , |
194 | target_os = "netbsd" , |
195 | target_os = "openbsd" , // OpenBSD 2.7 |
196 | ))] |
197 | pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { |
198 | let ret = cvt(unsafe { |
199 | libc::preadv( |
200 | self.as_raw_fd(), |
201 | bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, |
202 | cmp::min(bufs.len(), max_iov()) as libc::c_int, |
203 | offset as _, |
204 | ) |
205 | })?; |
206 | Ok(ret as usize) |
207 | } |
208 | |
209 | #[cfg (not(any( |
210 | target_os = "aix" , |
211 | target_os = "android" , |
212 | target_os = "dragonfly" , |
213 | target_os = "emscripten" , |
214 | target_os = "freebsd" , |
215 | target_os = "fuchsia" , |
216 | target_os = "hurd" , |
217 | target_os = "illumos" , |
218 | target_os = "linux" , |
219 | target_os = "netbsd" , |
220 | target_os = "openbsd" , |
221 | target_vendor = "apple" , |
222 | )))] |
223 | pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { |
224 | io::default_read_vectored(|b| self.read_at(b, offset), bufs) |
225 | } |
226 | |
227 | // We support some old Android versions that do not have `preadv` in libc, |
228 | // so we use weak linkage and fallback to a direct syscall if not available. |
229 | // |
230 | // On 32-bit targets, we don't want to deal with weird ABI issues around |
231 | // passing 64-bits parameters to syscalls, so we fallback to the default |
232 | // implementation if `preadv` is not available. |
233 | #[cfg (all(target_os = "android" , target_pointer_width = "64" ))] |
234 | pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { |
235 | super::weak::syscall! { |
236 | fn preadv( |
237 | fd: libc::c_int, |
238 | iovec: *const libc::iovec, |
239 | n_iovec: libc::c_int, |
240 | offset: off64_t |
241 | ) -> isize |
242 | } |
243 | |
244 | let ret = cvt(unsafe { |
245 | preadv( |
246 | self.as_raw_fd(), |
247 | bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, |
248 | cmp::min(bufs.len(), max_iov()) as libc::c_int, |
249 | offset as _, |
250 | ) |
251 | })?; |
252 | Ok(ret as usize) |
253 | } |
254 | |
255 | #[cfg (all(target_os = "android" , target_pointer_width = "32" ))] |
256 | // FIXME(#115199): Rust currently omits weak function definitions |
257 | // and its metadata from LLVM IR. |
258 | #[no_sanitize (cfi)] |
259 | pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { |
260 | super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); |
261 | |
262 | match preadv64.get() { |
263 | Some(preadv) => { |
264 | let ret = cvt(unsafe { |
265 | preadv( |
266 | self.as_raw_fd(), |
267 | bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, |
268 | cmp::min(bufs.len(), max_iov()) as libc::c_int, |
269 | offset as _, |
270 | ) |
271 | })?; |
272 | Ok(ret as usize) |
273 | } |
274 | None => io::default_read_vectored(|b| self.read_at(b, offset), bufs), |
275 | } |
276 | } |
277 | |
278 | // We support old MacOS, iOS, watchOS, tvOS and visionOS. `preadv` was added in the following |
279 | // Apple OS versions: |
280 | // ios 14.0 |
281 | // tvos 14.0 |
282 | // macos 11.0 |
283 | // watchos 7.0 |
284 | // |
285 | // These versions may be newer than the minimum supported versions of OS's we support so we must |
286 | // use "weak" linking. |
287 | #[cfg (target_vendor = "apple" )] |
288 | pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> { |
289 | super::weak::weak!(fn preadv(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); |
290 | |
291 | match preadv.get() { |
292 | Some(preadv) => { |
293 | let ret = cvt(unsafe { |
294 | preadv( |
295 | self.as_raw_fd(), |
296 | bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec, |
297 | cmp::min(bufs.len(), max_iov()) as libc::c_int, |
298 | offset as _, |
299 | ) |
300 | })?; |
301 | Ok(ret as usize) |
302 | } |
303 | None => io::default_read_vectored(|b| self.read_at(b, offset), bufs), |
304 | } |
305 | } |
306 | |
307 | pub fn write(&self, buf: &[u8]) -> io::Result<usize> { |
308 | let ret = cvt(unsafe { |
309 | libc::write( |
310 | self.as_raw_fd(), |
311 | buf.as_ptr() as *const libc::c_void, |
312 | cmp::min(buf.len(), READ_LIMIT), |
313 | ) |
314 | })?; |
315 | Ok(ret as usize) |
316 | } |
317 | |
318 | #[cfg (not(any( |
319 | target_os = "espidf" , |
320 | target_os = "horizon" , |
321 | target_os = "vita" , |
322 | target_os = "nuttx" |
323 | )))] |
324 | pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
325 | let ret = cvt(unsafe { |
326 | libc::writev( |
327 | self.as_raw_fd(), |
328 | bufs.as_ptr() as *const libc::iovec, |
329 | cmp::min(bufs.len(), max_iov()) as libc::c_int, |
330 | ) |
331 | })?; |
332 | Ok(ret as usize) |
333 | } |
334 | |
335 | #[cfg (any( |
336 | target_os = "espidf" , |
337 | target_os = "horizon" , |
338 | target_os = "vita" , |
339 | target_os = "nuttx" |
340 | ))] |
341 | pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { |
342 | io::default_write_vectored(|b| self.write(b), bufs) |
343 | } |
344 | |
345 | #[inline ] |
346 | pub fn is_write_vectored(&self) -> bool { |
347 | cfg!(not(any( |
348 | target_os = "espidf" , |
349 | target_os = "horizon" , |
350 | target_os = "vita" , |
351 | target_os = "nuttx" |
352 | ))) |
353 | } |
354 | |
355 | #[cfg_attr (target_os = "vxworks" , allow(unused_unsafe))] |
356 | pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> { |
357 | #[cfg (not(any( |
358 | all(target_os = "linux" , not(target_env = "musl" )), |
359 | target_os = "android" , |
360 | target_os = "hurd" |
361 | )))] |
362 | use libc::pwrite as pwrite64; |
363 | #[cfg (any( |
364 | all(target_os = "linux" , not(target_env = "musl" )), |
365 | target_os = "android" , |
366 | target_os = "hurd" |
367 | ))] |
368 | use libc::pwrite64; |
369 | |
370 | unsafe { |
371 | cvt(pwrite64( |
372 | self.as_raw_fd(), |
373 | buf.as_ptr() as *const libc::c_void, |
374 | cmp::min(buf.len(), READ_LIMIT), |
375 | offset as off64_t, |
376 | )) |
377 | .map(|n| n as usize) |
378 | } |
379 | } |
380 | |
381 | #[cfg (any( |
382 | target_os = "aix" , |
383 | target_os = "dragonfly" , // DragonFly 1.5 |
384 | target_os = "emscripten" , |
385 | target_os = "freebsd" , |
386 | target_os = "fuchsia" , |
387 | target_os = "hurd" , |
388 | target_os = "illumos" , |
389 | target_os = "linux" , |
390 | target_os = "netbsd" , |
391 | target_os = "openbsd" , // OpenBSD 2.7 |
392 | ))] |
393 | pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { |
394 | let ret = cvt(unsafe { |
395 | libc::pwritev( |
396 | self.as_raw_fd(), |
397 | bufs.as_ptr() as *const libc::iovec, |
398 | cmp::min(bufs.len(), max_iov()) as libc::c_int, |
399 | offset as _, |
400 | ) |
401 | })?; |
402 | Ok(ret as usize) |
403 | } |
404 | |
405 | #[cfg (not(any( |
406 | target_os = "aix" , |
407 | target_os = "android" , |
408 | target_os = "dragonfly" , |
409 | target_os = "emscripten" , |
410 | target_os = "freebsd" , |
411 | target_os = "fuchsia" , |
412 | target_os = "hurd" , |
413 | target_os = "illumos" , |
414 | target_os = "linux" , |
415 | target_os = "netbsd" , |
416 | target_os = "openbsd" , |
417 | target_vendor = "apple" , |
418 | )))] |
419 | pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { |
420 | io::default_write_vectored(|b| self.write_at(b, offset), bufs) |
421 | } |
422 | |
423 | // We support some old Android versions that do not have `pwritev` in libc, |
424 | // so we use weak linkage and fallback to a direct syscall if not available. |
425 | // |
426 | // On 32-bit targets, we don't want to deal with weird ABI issues around |
427 | // passing 64-bits parameters to syscalls, so we fallback to the default |
428 | // implementation if `pwritev` is not available. |
429 | #[cfg (all(target_os = "android" , target_pointer_width = "64" ))] |
430 | pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { |
431 | super::weak::syscall! { |
432 | fn pwritev( |
433 | fd: libc::c_int, |
434 | iovec: *const libc::iovec, |
435 | n_iovec: libc::c_int, |
436 | offset: off64_t |
437 | ) -> isize |
438 | } |
439 | |
440 | let ret = cvt(unsafe { |
441 | pwritev( |
442 | self.as_raw_fd(), |
443 | bufs.as_ptr() as *const libc::iovec, |
444 | cmp::min(bufs.len(), max_iov()) as libc::c_int, |
445 | offset as _, |
446 | ) |
447 | })?; |
448 | Ok(ret as usize) |
449 | } |
450 | |
451 | #[cfg (all(target_os = "android" , target_pointer_width = "32" ))] |
452 | pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { |
453 | super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); |
454 | |
455 | match pwritev64.get() { |
456 | Some(pwritev) => { |
457 | let ret = cvt(unsafe { |
458 | pwritev( |
459 | self.as_raw_fd(), |
460 | bufs.as_ptr() as *const libc::iovec, |
461 | cmp::min(bufs.len(), max_iov()) as libc::c_int, |
462 | offset as _, |
463 | ) |
464 | })?; |
465 | Ok(ret as usize) |
466 | } |
467 | None => io::default_write_vectored(|b| self.write_at(b, offset), bufs), |
468 | } |
469 | } |
470 | |
471 | // We support old MacOS, iOS, watchOS, tvOS and visionOS. `pwritev` was added in the following |
472 | // Apple OS versions: |
473 | // ios 14.0 |
474 | // tvos 14.0 |
475 | // macos 11.0 |
476 | // watchos 7.0 |
477 | // |
478 | // These versions may be newer than the minimum supported versions of OS's we support so we must |
479 | // use "weak" linking. |
480 | #[cfg (target_vendor = "apple" )] |
481 | pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> { |
482 | super::weak::weak!(fn pwritev(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize); |
483 | |
484 | match pwritev.get() { |
485 | Some(pwritev) => { |
486 | let ret = cvt(unsafe { |
487 | pwritev( |
488 | self.as_raw_fd(), |
489 | bufs.as_ptr() as *const libc::iovec, |
490 | cmp::min(bufs.len(), max_iov()) as libc::c_int, |
491 | offset as _, |
492 | ) |
493 | })?; |
494 | Ok(ret as usize) |
495 | } |
496 | None => io::default_write_vectored(|b| self.write_at(b, offset), bufs), |
497 | } |
498 | } |
499 | |
500 | #[cfg (not(any( |
501 | target_env = "newlib" , |
502 | target_os = "solaris" , |
503 | target_os = "illumos" , |
504 | target_os = "emscripten" , |
505 | target_os = "fuchsia" , |
506 | target_os = "l4re" , |
507 | target_os = "linux" , |
508 | target_os = "cygwin" , |
509 | target_os = "haiku" , |
510 | target_os = "redox" , |
511 | target_os = "vxworks" , |
512 | target_os = "nto" , |
513 | )))] |
514 | pub fn set_cloexec(&self) -> io::Result<()> { |
515 | unsafe { |
516 | cvt(libc::ioctl(self.as_raw_fd(), libc::FIOCLEX))?; |
517 | Ok(()) |
518 | } |
519 | } |
520 | #[cfg (any( |
521 | all( |
522 | target_env = "newlib" , |
523 | not(any(target_os = "espidf" , target_os = "horizon" , target_os = "vita" )) |
524 | ), |
525 | target_os = "solaris" , |
526 | target_os = "illumos" , |
527 | target_os = "emscripten" , |
528 | target_os = "fuchsia" , |
529 | target_os = "l4re" , |
530 | target_os = "linux" , |
531 | target_os = "cygwin" , |
532 | target_os = "haiku" , |
533 | target_os = "redox" , |
534 | target_os = "vxworks" , |
535 | target_os = "nto" , |
536 | ))] |
537 | pub fn set_cloexec(&self) -> io::Result<()> { |
538 | unsafe { |
539 | let previous = cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFD))?; |
540 | let new = previous | libc::FD_CLOEXEC; |
541 | if new != previous { |
542 | cvt(libc::fcntl(self.as_raw_fd(), libc::F_SETFD, new))?; |
543 | } |
544 | Ok(()) |
545 | } |
546 | } |
547 | #[cfg (any(target_os = "espidf" , target_os = "horizon" , target_os = "vita" ))] |
548 | pub fn set_cloexec(&self) -> io::Result<()> { |
549 | // FD_CLOEXEC is not supported in ESP-IDF, Horizon OS and Vita but there's no need to, |
550 | // because none of them supports spawning processes. |
551 | Ok(()) |
552 | } |
553 | |
554 | #[cfg (target_os = "linux" )] |
555 | pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { |
556 | unsafe { |
557 | let v = nonblocking as libc::c_int; |
558 | cvt(libc::ioctl(self.as_raw_fd(), libc::FIONBIO, &v))?; |
559 | Ok(()) |
560 | } |
561 | } |
562 | |
563 | #[cfg (not(target_os = "linux" ))] |
564 | pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { |
565 | unsafe { |
566 | let previous = cvt(libc::fcntl(self.as_raw_fd(), libc::F_GETFL))?; |
567 | let new = if nonblocking { |
568 | previous | libc::O_NONBLOCK |
569 | } else { |
570 | previous & !libc::O_NONBLOCK |
571 | }; |
572 | if new != previous { |
573 | cvt(libc::fcntl(self.as_raw_fd(), libc::F_SETFL, new))?; |
574 | } |
575 | Ok(()) |
576 | } |
577 | } |
578 | |
579 | #[inline ] |
580 | pub fn duplicate(&self) -> io::Result<FileDesc> { |
581 | Ok(Self(self.0.try_clone()?)) |
582 | } |
583 | } |
584 | |
585 | impl<'a> Read for &'a FileDesc { |
586 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { |
587 | (**self).read(buf) |
588 | } |
589 | |
590 | fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { |
591 | (**self).read_buf(cursor) |
592 | } |
593 | |
594 | fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { |
595 | (**self).read_vectored(bufs) |
596 | } |
597 | |
598 | #[inline ] |
599 | fn is_read_vectored(&self) -> bool { |
600 | (**self).is_read_vectored() |
601 | } |
602 | } |
603 | |
604 | impl AsInner<OwnedFd> for FileDesc { |
605 | #[inline ] |
606 | fn as_inner(&self) -> &OwnedFd { |
607 | &self.0 |
608 | } |
609 | } |
610 | |
611 | impl IntoInner<OwnedFd> for FileDesc { |
612 | fn into_inner(self) -> OwnedFd { |
613 | self.0 |
614 | } |
615 | } |
616 | |
617 | impl FromInner<OwnedFd> for FileDesc { |
618 | fn from_inner(owned_fd: OwnedFd) -> Self { |
619 | Self(owned_fd) |
620 | } |
621 | } |
622 | |
623 | impl AsFd for FileDesc { |
624 | fn as_fd(&self) -> BorrowedFd<'_> { |
625 | self.0.as_fd() |
626 | } |
627 | } |
628 | |
629 | impl AsRawFd for FileDesc { |
630 | #[inline ] |
631 | fn as_raw_fd(&self) -> RawFd { |
632 | self.0.as_raw_fd() |
633 | } |
634 | } |
635 | |
636 | impl IntoRawFd for FileDesc { |
637 | fn into_raw_fd(self) -> RawFd { |
638 | self.0.into_raw_fd() |
639 | } |
640 | } |
641 | |
642 | impl FromRawFd for FileDesc { |
643 | unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { |
644 | Self(FromRawFd::from_raw_fd(raw_fd)) |
645 | } |
646 | } |
647 | |