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