1 //! Types for working with [`File`].
2 //!
3 //! [`File`]: File
4 
5 use self::State::*;
6 use crate::fs::{asyncify, sys};
7 use crate::io::blocking::Buf;
8 use crate::io::{AsyncRead, AsyncSeek, AsyncWrite};
9 
10 use std::fmt;
11 use std::fs::{Metadata, Permissions};
12 use std::future::Future;
13 use std::io::{self, Seek, SeekFrom};
14 use std::path::Path;
15 use std::pin::Pin;
16 use std::sync::Arc;
17 use std::task::Context;
18 use std::task::Poll;
19 use std::task::Poll::*;
20 
21 /// A reference to an open file on the filesystem.
22 ///
23 /// This is a specialized version of [`std::fs::File`][std] for usage from the
24 /// Tokio runtime.
25 ///
26 /// An instance of a `File` can be read and/or written depending on what options
27 /// it was opened with. Files also implement [`AsyncSeek`] to alter the logical
28 /// cursor that the file contains internally.
29 ///
30 /// A file will not be closed immediately when it goes out of scope if there
31 /// are any IO operations that have not yet completed. To ensure that a file is
32 /// closed immediately when it is dropped, you should call [`flush`] before
33 /// dropping it. Note that this does not ensure that the file has been fully
34 /// written to disk; the operating system might keep the changes around in an
35 /// in-memory buffer. See the [`sync_all`] method for telling the OS to write
36 /// the data to disk.
37 ///
38 /// Reading and writing to a `File` is usually done using the convenience
39 /// methods found on the [`AsyncReadExt`] and [`AsyncWriteExt`] traits. Examples
40 /// import these traits through [the prelude].
41 ///
42 /// [std]: struct@std::fs::File
43 /// [`AsyncSeek`]: trait@crate::io::AsyncSeek
44 /// [`flush`]: fn@crate::io::AsyncWriteExt::flush
45 /// [`sync_all`]: fn@crate::fs::File::sync_all
46 /// [`AsyncReadExt`]: trait@crate::io::AsyncReadExt
47 /// [`AsyncWriteExt`]: trait@crate::io::AsyncWriteExt
48 /// [the prelude]: crate::prelude
49 ///
50 /// # Examples
51 ///
52 /// Create a new file and asynchronously write bytes to it:
53 ///
54 /// ```no_run
55 /// use tokio::fs::File;
56 /// use tokio::prelude::*; // for write_all()
57 ///
58 /// # async fn dox() -> std::io::Result<()> {
59 /// let mut file = File::create("foo.txt").await?;
60 /// file.write_all(b"hello, world!").await?;
61 /// # Ok(())
62 /// # }
63 /// ```
64 ///
65 /// Read the contents of a file into a buffer
66 ///
67 /// ```no_run
68 /// use tokio::fs::File;
69 /// use tokio::prelude::*; // for read_to_end()
70 ///
71 /// # async fn dox() -> std::io::Result<()> {
72 /// let mut file = File::open("foo.txt").await?;
73 ///
74 /// let mut contents = vec![];
75 /// file.read_to_end(&mut contents).await?;
76 ///
77 /// println!("len = {}", contents.len());
78 /// # Ok(())
79 /// # }
80 /// ```
81 pub struct File {
82     std: Arc<sys::File>,
83     state: State,
84 
85     /// Errors from writes/flushes are returned in write/flush calls. If a write
86     /// error is observed while performing a read, it is saved until the next
87     /// write / flush call.
88     last_write_err: Option<io::ErrorKind>,
89 }
90 
91 #[derive(Debug)]
92 enum State {
93     Idle(Option<Buf>),
94     Busy(sys::Blocking<(Operation, Buf)>),
95 }
96 
97 #[derive(Debug)]
98 enum Operation {
99     Read(io::Result<usize>),
100     Write(io::Result<()>),
101     Seek(io::Result<u64>),
102 }
103 
104 impl File {
105     /// Attempts to open a file in read-only mode.
106     ///
107     /// See [`OpenOptions`] for more details.
108     ///
109     /// [`OpenOptions`]: super::OpenOptions
110     ///
111     /// # Errors
112     ///
113     /// This function will return an error if called from outside of the Tokio
114     /// runtime or if path does not already exist. Other errors may also be
115     /// returned according to OpenOptions::open.
116     ///
117     /// # Examples
118     ///
119     /// ```no_run
120     /// use tokio::fs::File;
121     /// use tokio::prelude::*;
122     ///
123     /// # async fn dox() -> std::io::Result<()> {
124     /// let mut file = File::open("foo.txt").await?;
125     ///
126     /// let mut contents = vec![];
127     /// file.read_to_end(&mut contents).await?;
128     ///
129     /// println!("len = {}", contents.len());
130     /// # Ok(())
131     /// # }
132     /// ```
133     ///
134     /// The [`read_to_end`] method is defined on the [`AsyncReadExt`] trait.
135     ///
136     /// [`read_to_end`]: fn@crate::io::AsyncReadExt::read_to_end
137     /// [`AsyncReadExt`]: trait@crate::io::AsyncReadExt
open(path: impl AsRef<Path>) -> io::Result<File>138     pub async fn open(path: impl AsRef<Path>) -> io::Result<File> {
139         let path = path.as_ref().to_owned();
140         let std = asyncify(|| sys::File::open(path)).await?;
141 
142         Ok(File::from_std(std))
143     }
144 
145     /// Opens a file in write-only mode.
146     ///
147     /// This function will create a file if it does not exist, and will truncate
148     /// it if it does.
149     ///
150     /// See [`OpenOptions`] for more details.
151     ///
152     /// [`OpenOptions`]: super::OpenOptions
153     ///
154     /// # Errors
155     ///
156     /// Results in an error if called from outside of the Tokio runtime or if
157     /// the underlying [`create`] call results in an error.
158     ///
159     /// [`create`]: std::fs::File::create
160     ///
161     /// # Examples
162     ///
163     /// ```no_run
164     /// use tokio::fs::File;
165     /// use tokio::prelude::*;
166     ///
167     /// # async fn dox() -> std::io::Result<()> {
168     /// let mut file = File::create("foo.txt").await?;
169     /// file.write_all(b"hello, world!").await?;
170     /// # Ok(())
171     /// # }
172     /// ```
173     ///
174     /// The [`write_all`] method is defined on the [`AsyncWriteExt`] trait.
175     ///
176     /// [`write_all`]: fn@crate::io::AsyncWriteExt::write_all
177     /// [`AsyncWriteExt`]: trait@crate::io::AsyncWriteExt
create(path: impl AsRef<Path>) -> io::Result<File>178     pub async fn create(path: impl AsRef<Path>) -> io::Result<File> {
179         let path = path.as_ref().to_owned();
180         let std_file = asyncify(move || sys::File::create(path)).await?;
181         Ok(File::from_std(std_file))
182     }
183 
184     /// Converts a [`std::fs::File`][std] to a [`tokio::fs::File`][file].
185     ///
186     /// [std]: std::fs::File
187     /// [file]: File
188     ///
189     /// # Examples
190     ///
191     /// ```no_run
192     /// // This line could block. It is not recommended to do this on the Tokio
193     /// // runtime.
194     /// let std_file = std::fs::File::open("foo.txt").unwrap();
195     /// let file = tokio::fs::File::from_std(std_file);
196     /// ```
from_std(std: sys::File) -> File197     pub fn from_std(std: sys::File) -> File {
198         File {
199             std: Arc::new(std),
200             state: State::Idle(Some(Buf::with_capacity(0))),
201             last_write_err: None,
202         }
203     }
204 
205     /// Seeks to an offset, in bytes, in a stream.
206     ///
207     /// # Examples
208     ///
209     /// ```no_run
210     /// use tokio::fs::File;
211     /// use tokio::prelude::*;
212     ///
213     /// use std::io::SeekFrom;
214     ///
215     /// # async fn dox() -> std::io::Result<()> {
216     /// let mut file = File::open("foo.txt").await?;
217     /// file.seek(SeekFrom::Start(6)).await?;
218     ///
219     /// let mut contents = vec![0u8; 10];
220     /// file.read_exact(&mut contents).await?;
221     /// # Ok(())
222     /// # }
223     /// ```
224     ///
225     /// The [`read_exact`] method is defined on the [`AsyncReadExt`] trait.
226     ///
227     /// [`read_exact`]: fn@crate::io::AsyncReadExt::read_exact
228     /// [`AsyncReadExt`]: trait@crate::io::AsyncReadExt
seek(&mut self, mut pos: SeekFrom) -> io::Result<u64>229     pub async fn seek(&mut self, mut pos: SeekFrom) -> io::Result<u64> {
230         self.complete_inflight().await;
231 
232         let mut buf = match self.state {
233             Idle(ref mut buf_cell) => buf_cell.take().unwrap(),
234             _ => unreachable!(),
235         };
236 
237         // Factor in any unread data from the buf
238         if !buf.is_empty() {
239             let n = buf.discard_read();
240 
241             if let SeekFrom::Current(ref mut offset) = pos {
242                 *offset += n;
243             }
244         }
245 
246         let std = self.std.clone();
247 
248         // Start the operation
249         self.state = Busy(sys::run(move || {
250             let res = (&*std).seek(pos);
251             (Operation::Seek(res), buf)
252         }));
253 
254         let (op, buf) = match self.state {
255             Idle(_) => unreachable!(),
256             Busy(ref mut rx) => rx.await.unwrap(),
257         };
258 
259         self.state = Idle(Some(buf));
260 
261         match op {
262             Operation::Seek(res) => res,
263             _ => unreachable!(),
264         }
265     }
266 
267     /// Attempts to sync all OS-internal metadata to disk.
268     ///
269     /// This function will attempt to ensure that all in-core data reaches the
270     /// filesystem before returning.
271     ///
272     /// # Examples
273     ///
274     /// ```no_run
275     /// use tokio::fs::File;
276     /// use tokio::prelude::*;
277     ///
278     /// # async fn dox() -> std::io::Result<()> {
279     /// let mut file = File::create("foo.txt").await?;
280     /// file.write_all(b"hello, world!").await?;
281     /// file.sync_all().await?;
282     /// # Ok(())
283     /// # }
284     /// ```
285     ///
286     /// The [`write_all`] method is defined on the [`AsyncWriteExt`] trait.
287     ///
288     /// [`write_all`]: fn@crate::io::AsyncWriteExt::write_all
289     /// [`AsyncWriteExt`]: trait@crate::io::AsyncWriteExt
sync_all(&mut self) -> io::Result<()>290     pub async fn sync_all(&mut self) -> io::Result<()> {
291         self.complete_inflight().await;
292 
293         let std = self.std.clone();
294         asyncify(move || std.sync_all()).await
295     }
296 
297     /// This function is similar to `sync_all`, except that it may not
298     /// synchronize file metadata to the filesystem.
299     ///
300     /// This is intended for use cases that must synchronize content, but don't
301     /// need the metadata on disk. The goal of this method is to reduce disk
302     /// operations.
303     ///
304     /// Note that some platforms may simply implement this in terms of `sync_all`.
305     ///
306     /// # Examples
307     ///
308     /// ```no_run
309     /// use tokio::fs::File;
310     /// use tokio::prelude::*;
311     ///
312     /// # async fn dox() -> std::io::Result<()> {
313     /// let mut file = File::create("foo.txt").await?;
314     /// file.write_all(b"hello, world!").await?;
315     /// file.sync_data().await?;
316     /// # Ok(())
317     /// # }
318     /// ```
319     ///
320     /// The [`write_all`] method is defined on the [`AsyncWriteExt`] trait.
321     ///
322     /// [`write_all`]: fn@crate::io::AsyncWriteExt::write_all
323     /// [`AsyncWriteExt`]: trait@crate::io::AsyncWriteExt
sync_data(&mut self) -> io::Result<()>324     pub async fn sync_data(&mut self) -> io::Result<()> {
325         self.complete_inflight().await;
326 
327         let std = self.std.clone();
328         asyncify(move || std.sync_data()).await
329     }
330 
331     /// Truncates or extends the underlying file, updating the size of this file to become size.
332     ///
333     /// If the size is less than the current file's size, then the file will be
334     /// shrunk. If it is greater than the current file's size, then the file
335     /// will be extended to size and have all of the intermediate data filled in
336     /// with 0s.
337     ///
338     /// # Errors
339     ///
340     /// This function will return an error if the file is not opened for
341     /// writing.
342     ///
343     /// # Examples
344     ///
345     /// ```no_run
346     /// use tokio::fs::File;
347     /// use tokio::prelude::*;
348     ///
349     /// # async fn dox() -> std::io::Result<()> {
350     /// let mut file = File::create("foo.txt").await?;
351     /// file.write_all(b"hello, world!").await?;
352     /// file.set_len(10).await?;
353     /// # Ok(())
354     /// # }
355     /// ```
356     ///
357     /// The [`write_all`] method is defined on the [`AsyncWriteExt`] trait.
358     ///
359     /// [`write_all`]: fn@crate::io::AsyncWriteExt::write_all
360     /// [`AsyncWriteExt`]: trait@crate::io::AsyncWriteExt
set_len(&mut self, size: u64) -> io::Result<()>361     pub async fn set_len(&mut self, size: u64) -> io::Result<()> {
362         self.complete_inflight().await;
363 
364         let mut buf = match self.state {
365             Idle(ref mut buf_cell) => buf_cell.take().unwrap(),
366             _ => unreachable!(),
367         };
368 
369         let seek = if !buf.is_empty() {
370             Some(SeekFrom::Current(buf.discard_read()))
371         } else {
372             None
373         };
374 
375         let std = self.std.clone();
376 
377         self.state = Busy(sys::run(move || {
378             let res = if let Some(seek) = seek {
379                 (&*std).seek(seek).and_then(|_| std.set_len(size))
380             } else {
381                 std.set_len(size)
382             }
383             .map(|_| 0); // the value is discarded later
384 
385             // Return the result as a seek
386             (Operation::Seek(res), buf)
387         }));
388 
389         let (op, buf) = match self.state {
390             Idle(_) => unreachable!(),
391             Busy(ref mut rx) => rx.await?,
392         };
393 
394         self.state = Idle(Some(buf));
395 
396         match op {
397             Operation::Seek(res) => res.map(|_| ()),
398             _ => unreachable!(),
399         }
400     }
401 
402     /// Queries metadata about the underlying file.
403     ///
404     /// # Examples
405     ///
406     /// ```no_run
407     /// use tokio::fs::File;
408     ///
409     /// # async fn dox() -> std::io::Result<()> {
410     /// let file = File::open("foo.txt").await?;
411     /// let metadata = file.metadata().await?;
412     ///
413     /// println!("{:?}", metadata);
414     /// # Ok(())
415     /// # }
416     /// ```
metadata(&self) -> io::Result<Metadata>417     pub async fn metadata(&self) -> io::Result<Metadata> {
418         let std = self.std.clone();
419         asyncify(move || std.metadata()).await
420     }
421 
422     /// Create a new `File` instance that shares the same underlying file handle
423     /// as the existing `File` instance. Reads, writes, and seeks will affect both
424     /// File instances simultaneously.
425     ///
426     /// # Examples
427     ///
428     /// ```no_run
429     /// use tokio::fs::File;
430     ///
431     /// # async fn dox() -> std::io::Result<()> {
432     /// let file = File::open("foo.txt").await?;
433     /// let file_clone = file.try_clone().await?;
434     /// # Ok(())
435     /// # }
436     /// ```
try_clone(&self) -> io::Result<File>437     pub async fn try_clone(&self) -> io::Result<File> {
438         let std = self.std.clone();
439         let std_file = asyncify(move || std.try_clone()).await?;
440         Ok(File::from_std(std_file))
441     }
442 
443     /// Destructures `File` into a [`std::fs::File`][std]. This function is
444     /// async to allow any in-flight operations to complete.
445     ///
446     /// Use `File::try_into_std` to attempt conversion immediately.
447     ///
448     /// [std]: std::fs::File
449     ///
450     /// # Examples
451     ///
452     /// ```no_run
453     /// use tokio::fs::File;
454     ///
455     /// # async fn dox() -> std::io::Result<()> {
456     /// let tokio_file = File::open("foo.txt").await?;
457     /// let std_file = tokio_file.into_std().await;
458     /// # Ok(())
459     /// # }
460     /// ```
into_std(mut self) -> sys::File461     pub async fn into_std(mut self) -> sys::File {
462         self.complete_inflight().await;
463         Arc::try_unwrap(self.std).expect("Arc::try_unwrap failed")
464     }
465 
466     /// Tries to immediately destructure `File` into a [`std::fs::File`][std].
467     ///
468     /// [std]: std::fs::File
469     ///
470     /// # Errors
471     ///
472     /// This function will return an error containing the file if some
473     /// operation is in-flight.
474     ///
475     /// # Examples
476     ///
477     /// ```no_run
478     /// use tokio::fs::File;
479     ///
480     /// # async fn dox() -> std::io::Result<()> {
481     /// let tokio_file = File::open("foo.txt").await?;
482     /// let std_file = tokio_file.try_into_std().unwrap();
483     /// # Ok(())
484     /// # }
485     /// ```
try_into_std(mut self) -> Result<sys::File, Self>486     pub fn try_into_std(mut self) -> Result<sys::File, Self> {
487         match Arc::try_unwrap(self.std) {
488             Ok(file) => Ok(file),
489             Err(std_file_arc) => {
490                 self.std = std_file_arc;
491                 Err(self)
492             }
493         }
494     }
495 
496     /// Changes the permissions on the underlying file.
497     ///
498     /// # Platform-specific behavior
499     ///
500     /// This function currently corresponds to the `fchmod` function on Unix and
501     /// the `SetFileInformationByHandle` function on Windows. Note that, this
502     /// [may change in the future][changes].
503     ///
504     /// [changes]: https://doc.rust-lang.org/std/io/index.html#platform-specific-behavior
505     ///
506     /// # Errors
507     ///
508     /// This function will return an error if the user lacks permission change
509     /// attributes on the underlying file. It may also return an error in other
510     /// os-specific unspecified cases.
511     ///
512     /// # Examples
513     ///
514     /// ```no_run
515     /// use tokio::fs::File;
516     ///
517     /// # async fn dox() -> std::io::Result<()> {
518     /// let file = File::open("foo.txt").await?;
519     /// let mut perms = file.metadata().await?.permissions();
520     /// perms.set_readonly(true);
521     /// file.set_permissions(perms).await?;
522     /// # Ok(())
523     /// # }
524     /// ```
set_permissions(&self, perm: Permissions) -> io::Result<()>525     pub async fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
526         let std = self.std.clone();
527         asyncify(move || std.set_permissions(perm)).await
528     }
529 
complete_inflight(&mut self)530     async fn complete_inflight(&mut self) {
531         use crate::future::poll_fn;
532 
533         if let Err(e) = poll_fn(|cx| Pin::new(&mut *self).poll_flush(cx)).await {
534             self.last_write_err = Some(e.kind());
535         }
536     }
537 }
538 
539 impl AsyncRead for File {
prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit<u8>]) -> bool540     unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [std::mem::MaybeUninit<u8>]) -> bool {
541         // https://github.com/rust-lang/rust/blob/09c817eeb29e764cfc12d0a8d94841e3ffe34023/src/libstd/fs.rs#L668
542         false
543     }
544 
poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, dst: &mut [u8], ) -> Poll<io::Result<usize>>545     fn poll_read(
546         mut self: Pin<&mut Self>,
547         cx: &mut Context<'_>,
548         dst: &mut [u8],
549     ) -> Poll<io::Result<usize>> {
550         loop {
551             match self.state {
552                 Idle(ref mut buf_cell) => {
553                     let mut buf = buf_cell.take().unwrap();
554 
555                     if !buf.is_empty() {
556                         let n = buf.copy_to(dst);
557                         *buf_cell = Some(buf);
558                         return Ready(Ok(n));
559                     }
560 
561                     buf.ensure_capacity_for(dst);
562                     let std = self.std.clone();
563 
564                     self.state = Busy(sys::run(move || {
565                         let res = buf.read_from(&mut &*std);
566                         (Operation::Read(res), buf)
567                     }));
568                 }
569                 Busy(ref mut rx) => {
570                     let (op, mut buf) = ready!(Pin::new(rx).poll(cx))?;
571 
572                     match op {
573                         Operation::Read(Ok(_)) => {
574                             let n = buf.copy_to(dst);
575                             self.state = Idle(Some(buf));
576                             return Ready(Ok(n));
577                         }
578                         Operation::Read(Err(e)) => {
579                             assert!(buf.is_empty());
580 
581                             self.state = Idle(Some(buf));
582                             return Ready(Err(e));
583                         }
584                         Operation::Write(Ok(_)) => {
585                             assert!(buf.is_empty());
586                             self.state = Idle(Some(buf));
587                             continue;
588                         }
589                         Operation::Write(Err(e)) => {
590                             assert!(self.last_write_err.is_none());
591                             self.last_write_err = Some(e.kind());
592                             self.state = Idle(Some(buf));
593                         }
594                         Operation::Seek(_) => {
595                             assert!(buf.is_empty());
596                             self.state = Idle(Some(buf));
597                             continue;
598                         }
599                     }
600                 }
601             }
602         }
603     }
604 }
605 
606 impl AsyncSeek for File {
start_seek( mut self: Pin<&mut Self>, cx: &mut Context<'_>, mut pos: SeekFrom, ) -> Poll<io::Result<()>>607     fn start_seek(
608         mut self: Pin<&mut Self>,
609         cx: &mut Context<'_>,
610         mut pos: SeekFrom,
611     ) -> Poll<io::Result<()>> {
612         loop {
613             match self.state {
614                 Idle(ref mut buf_cell) => {
615                     let mut buf = buf_cell.take().unwrap();
616 
617                     // Factor in any unread data from the buf
618                     if !buf.is_empty() {
619                         let n = buf.discard_read();
620 
621                         if let SeekFrom::Current(ref mut offset) = pos {
622                             *offset += n;
623                         }
624                     }
625 
626                     let std = self.std.clone();
627 
628                     self.state = Busy(sys::run(move || {
629                         let res = (&*std).seek(pos);
630                         (Operation::Seek(res), buf)
631                     }));
632 
633                     return Ready(Ok(()));
634                 }
635                 Busy(ref mut rx) => {
636                     let (op, buf) = ready!(Pin::new(rx).poll(cx))?;
637                     self.state = Idle(Some(buf));
638 
639                     match op {
640                         Operation::Read(_) => {}
641                         Operation::Write(Err(e)) => {
642                             assert!(self.last_write_err.is_none());
643                             self.last_write_err = Some(e.kind());
644                         }
645                         Operation::Write(_) => {}
646                         Operation::Seek(_) => {}
647                     }
648                 }
649             }
650         }
651     }
652 
poll_complete(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>>653     fn poll_complete(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
654         loop {
655             match self.state {
656                 Idle(_) => panic!("must call start_seek before calling poll_complete"),
657                 Busy(ref mut rx) => {
658                     let (op, buf) = ready!(Pin::new(rx).poll(cx))?;
659                     self.state = Idle(Some(buf));
660 
661                     match op {
662                         Operation::Read(_) => {}
663                         Operation::Write(Err(e)) => {
664                             assert!(self.last_write_err.is_none());
665                             self.last_write_err = Some(e.kind());
666                         }
667                         Operation::Write(_) => {}
668                         Operation::Seek(res) => return Ready(res),
669                     }
670                 }
671             }
672         }
673     }
674 }
675 
676 impl AsyncWrite for File {
poll_write( mut self: Pin<&mut Self>, cx: &mut Context<'_>, src: &[u8], ) -> Poll<io::Result<usize>>677     fn poll_write(
678         mut self: Pin<&mut Self>,
679         cx: &mut Context<'_>,
680         src: &[u8],
681     ) -> Poll<io::Result<usize>> {
682         if let Some(e) = self.last_write_err.take() {
683             return Ready(Err(e.into()));
684         }
685 
686         loop {
687             match self.state {
688                 Idle(ref mut buf_cell) => {
689                     let mut buf = buf_cell.take().unwrap();
690 
691                     let seek = if !buf.is_empty() {
692                         Some(SeekFrom::Current(buf.discard_read()))
693                     } else {
694                         None
695                     };
696 
697                     let n = buf.copy_from(src);
698                     let std = self.std.clone();
699 
700                     self.state = Busy(sys::run(move || {
701                         let res = if let Some(seek) = seek {
702                             (&*std).seek(seek).and_then(|_| buf.write_to(&mut &*std))
703                         } else {
704                             buf.write_to(&mut &*std)
705                         };
706 
707                         (Operation::Write(res), buf)
708                     }));
709 
710                     return Ready(Ok(n));
711                 }
712                 Busy(ref mut rx) => {
713                     let (op, buf) = ready!(Pin::new(rx).poll(cx))?;
714                     self.state = Idle(Some(buf));
715 
716                     match op {
717                         Operation::Read(_) => {
718                             // We don't care about the result here. The fact
719                             // that the cursor has advanced will be reflected in
720                             // the next iteration of the loop
721                             continue;
722                         }
723                         Operation::Write(res) => {
724                             // If the previous write was successful, continue.
725                             // Otherwise, error.
726                             res?;
727                             continue;
728                         }
729                         Operation::Seek(_) => {
730                             // Ignore the seek
731                             continue;
732                         }
733                     }
734                 }
735             }
736         }
737     }
738 
poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>>739     fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
740         if let Some(e) = self.last_write_err.take() {
741             return Ready(Err(e.into()));
742         }
743 
744         let (op, buf) = match self.state {
745             Idle(_) => return Ready(Ok(())),
746             Busy(ref mut rx) => ready!(Pin::new(rx).poll(cx))?,
747         };
748 
749         // The buffer is not used here
750         self.state = Idle(Some(buf));
751 
752         match op {
753             Operation::Read(_) => Ready(Ok(())),
754             Operation::Write(res) => Ready(res),
755             Operation::Seek(_) => Ready(Ok(())),
756         }
757     }
758 
poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>>759     fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
760         Poll::Ready(Ok(()))
761     }
762 }
763 
764 impl From<sys::File> for File {
from(std: sys::File) -> Self765     fn from(std: sys::File) -> Self {
766         Self::from_std(std)
767     }
768 }
769 
770 impl fmt::Debug for File {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result771     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
772         fmt.debug_struct("tokio::fs::File")
773             .field("std", &self.std)
774             .finish()
775     }
776 }
777 
778 #[cfg(unix)]
779 impl std::os::unix::io::AsRawFd for File {
as_raw_fd(&self) -> std::os::unix::io::RawFd780     fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
781         self.std.as_raw_fd()
782     }
783 }
784 
785 #[cfg(windows)]
786 impl std::os::windows::io::AsRawHandle for File {
as_raw_handle(&self) -> std::os::windows::io::RawHandle787     fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
788         self.std.as_raw_handle()
789     }
790 }
791