diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:57:31 +0000 |
commit | dc0db358abe19481e475e10c32149b53370f1a1c (patch) | |
tree | ab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/tokio/src/fs | |
parent | Releasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff) | |
download | rustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip |
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/tokio/src/fs')
-rw-r--r-- | vendor/tokio/src/fs/create_dir.rs | 2 | ||||
-rw-r--r-- | vendor/tokio/src/fs/dir_builder.rs | 2 | ||||
-rw-r--r-- | vendor/tokio/src/fs/file.rs | 120 | ||||
-rw-r--r-- | vendor/tokio/src/fs/file/tests.rs | 31 | ||||
-rw-r--r-- | vendor/tokio/src/fs/mocks.rs | 17 | ||||
-rw-r--r-- | vendor/tokio/src/fs/mod.rs | 25 | ||||
-rw-r--r-- | vendor/tokio/src/fs/open_options.rs | 21 | ||||
-rw-r--r-- | vendor/tokio/src/fs/open_options/mock_open_options.rs | 1 | ||||
-rw-r--r-- | vendor/tokio/src/fs/read.rs | 4 | ||||
-rw-r--r-- | vendor/tokio/src/fs/read_dir.rs | 119 | ||||
-rw-r--r-- | vendor/tokio/src/fs/read_to_string.rs | 4 | ||||
-rw-r--r-- | vendor/tokio/src/fs/symlink_dir.rs | 2 | ||||
-rw-r--r-- | vendor/tokio/src/fs/symlink_file.rs | 2 | ||||
-rw-r--r-- | vendor/tokio/src/fs/try_exists.rs | 34 | ||||
-rw-r--r-- | vendor/tokio/src/fs/write.rs | 4 |
15 files changed, 303 insertions, 85 deletions
diff --git a/vendor/tokio/src/fs/create_dir.rs b/vendor/tokio/src/fs/create_dir.rs index e03b04dc4..411969500 100644 --- a/vendor/tokio/src/fs/create_dir.rs +++ b/vendor/tokio/src/fs/create_dir.rs @@ -3,7 +3,7 @@ use crate::fs::asyncify; use std::io; use std::path::Path; -/// Creates a new, empty directory at the provided path +/// Creates a new, empty directory at the provided path. /// /// This is an async version of [`std::fs::create_dir`][std] /// diff --git a/vendor/tokio/src/fs/dir_builder.rs b/vendor/tokio/src/fs/dir_builder.rs index b1849344b..97168bff7 100644 --- a/vendor/tokio/src/fs/dir_builder.rs +++ b/vendor/tokio/src/fs/dir_builder.rs @@ -14,7 +14,7 @@ pub struct DirBuilder { /// Indicates whether to create parent directories if they are missing. recursive: bool, - /// Set the Unix mode for newly created directories. + /// Sets the Unix mode for newly created directories. #[cfg(unix)] pub(super) mode: Option<u32>, } diff --git a/vendor/tokio/src/fs/file.rs b/vendor/tokio/src/fs/file.rs index 5286e6c5c..74f91958d 100644 --- a/vendor/tokio/src/fs/file.rs +++ b/vendor/tokio/src/fs/file.rs @@ -20,16 +20,16 @@ use std::task::Poll; use std::task::Poll::*; #[cfg(test)] -use super::mocks::spawn_blocking; -#[cfg(test)] use super::mocks::JoinHandle; #[cfg(test)] use super::mocks::MockFile as StdFile; -#[cfg(not(test))] -use crate::blocking::spawn_blocking; +#[cfg(test)] +use super::mocks::{spawn_blocking, spawn_mandatory_blocking}; #[cfg(not(test))] use crate::blocking::JoinHandle; #[cfg(not(test))] +use crate::blocking::{spawn_blocking, spawn_mandatory_blocking}; +#[cfg(not(test))] use std::fs::File as StdFile; /// A reference to an open file on the filesystem. @@ -74,7 +74,7 @@ use std::fs::File as StdFile; /// # } /// ``` /// -/// Read the contents of a file into a buffer +/// Read the contents of a file into a buffer: /// /// ```no_run /// use tokio::fs::File; @@ -383,7 +383,7 @@ impl File { asyncify(move || std.metadata()).await } - /// Create a new `File` instance that shares the same underlying file handle + /// Creates a new `File` instance that shares the same underlying file handle /// as the existing `File` instance. Reads, writes, and seeks will affect both /// File instances simultaneously. /// @@ -399,6 +399,7 @@ impl File { /// # } /// ``` pub async fn try_clone(&self) -> io::Result<File> { + self.inner.lock().await.complete_inflight().await; let std = self.std.clone(); let std_file = asyncify(move || std.try_clone()).await?; Ok(File::from_std(std_file)) @@ -498,6 +499,7 @@ impl AsyncRead for File { cx: &mut Context<'_>, dst: &mut ReadBuf<'_>, ) -> Poll<io::Result<()>> { + ready!(crate::trace::trace_leaf(cx)); let me = self.get_mut(); let inner = me.inner.get_mut(); @@ -565,34 +567,36 @@ impl AsyncSeek for File { let me = self.get_mut(); let inner = me.inner.get_mut(); - loop { - match inner.state { - Busy(_) => panic!("must wait for poll_complete before calling start_seek"), - Idle(ref mut buf_cell) => { - let mut buf = buf_cell.take().unwrap(); + match inner.state { + Busy(_) => Err(io::Error::new( + io::ErrorKind::Other, + "other file operation is pending, call poll_complete before start_seek", + )), + Idle(ref mut buf_cell) => { + let mut buf = buf_cell.take().unwrap(); - // Factor in any unread data from the buf - if !buf.is_empty() { - let n = buf.discard_read(); + // Factor in any unread data from the buf + if !buf.is_empty() { + let n = buf.discard_read(); - if let SeekFrom::Current(ref mut offset) = pos { - *offset += n; - } + if let SeekFrom::Current(ref mut offset) = pos { + *offset += n; } + } - let std = me.std.clone(); + let std = me.std.clone(); - inner.state = Busy(spawn_blocking(move || { - let res = (&*std).seek(pos); - (Operation::Seek(res), buf) - })); - return Ok(()); - } + inner.state = Busy(spawn_blocking(move || { + let res = (&*std).seek(pos); + (Operation::Seek(res), buf) + })); + Ok(()) } } } fn poll_complete(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> { + ready!(crate::trace::trace_leaf(cx)); let inner = self.inner.get_mut(); loop { @@ -628,6 +632,7 @@ impl AsyncWrite for File { cx: &mut Context<'_>, src: &[u8], ) -> Poll<io::Result<usize>> { + ready!(crate::trace::trace_leaf(cx)); let me = self.get_mut(); let inner = me.inner.get_mut(); @@ -649,7 +654,7 @@ impl AsyncWrite for File { let n = buf.copy_from(src); let std = me.std.clone(); - inner.state = Busy(spawn_blocking(move || { + let blocking_task_join_handle = spawn_mandatory_blocking(move || { let res = if let Some(seek) = seek { (&*std).seek(seek).and_then(|_| buf.write_to(&mut &*std)) } else { @@ -657,7 +662,12 @@ impl AsyncWrite for File { }; (Operation::Write(res), buf) - })); + }) + .ok_or_else(|| { + io::Error::new(io::ErrorKind::Other, "background task failed") + })?; + + inner.state = Busy(blocking_task_join_handle); return Ready(Ok(n)); } @@ -689,11 +699,13 @@ impl AsyncWrite for File { } fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { + ready!(crate::trace::trace_leaf(cx)); let inner = self.inner.get_mut(); inner.poll_flush(cx) } fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { + ready!(crate::trace::trace_leaf(cx)); self.poll_flush(cx) } } @@ -719,6 +731,15 @@ impl std::os::unix::io::AsRawFd for File { } } +#[cfg(all(unix, not(tokio_no_as_fd)))] +impl std::os::unix::io::AsFd for File { + fn as_fd(&self) -> std::os::unix::io::BorrowedFd<'_> { + unsafe { + std::os::unix::io::BorrowedFd::borrow_raw(std::os::unix::io::AsRawFd::as_raw_fd(self)) + } + } +} + #[cfg(unix)] impl std::os::unix::io::FromRawFd for File { unsafe fn from_raw_fd(fd: std::os::unix::io::RawFd) -> Self { @@ -726,17 +747,32 @@ impl std::os::unix::io::FromRawFd for File { } } -#[cfg(windows)] -impl std::os::windows::io::AsRawHandle for File { - fn as_raw_handle(&self) -> std::os::windows::io::RawHandle { - self.std.as_raw_handle() +cfg_windows! { + use crate::os::windows::io::{AsRawHandle, FromRawHandle, RawHandle}; + #[cfg(not(tokio_no_as_fd))] + use crate::os::windows::io::{AsHandle, BorrowedHandle}; + + impl AsRawHandle for File { + fn as_raw_handle(&self) -> RawHandle { + self.std.as_raw_handle() + } } -} -#[cfg(windows)] -impl std::os::windows::io::FromRawHandle for File { - unsafe fn from_raw_handle(handle: std::os::windows::io::RawHandle) -> Self { - StdFile::from_raw_handle(handle).into() + #[cfg(not(tokio_no_as_fd))] + impl AsHandle for File { + fn as_handle(&self) -> BorrowedHandle<'_> { + unsafe { + BorrowedHandle::borrow_raw( + AsRawHandle::as_raw_handle(self), + ) + } + } + } + + impl FromRawHandle for File { + unsafe fn from_raw_handle(handle: RawHandle) -> Self { + StdFile::from_raw_handle(handle).into() + } } } @@ -744,8 +780,18 @@ impl Inner { async fn complete_inflight(&mut self) { use crate::future::poll_fn; - if let Err(e) = poll_fn(|cx| Pin::new(&mut *self).poll_flush(cx)).await { - self.last_write_err = Some(e.kind()); + poll_fn(|cx| self.poll_complete_inflight(cx)).await + } + + fn poll_complete_inflight(&mut self, cx: &mut Context<'_>) -> Poll<()> { + ready!(crate::trace::trace_leaf(cx)); + match self.poll_flush(cx) { + Poll::Ready(Err(e)) => { + self.last_write_err = Some(e.kind()); + Poll::Ready(()) + } + Poll::Ready(Ok(())) => Poll::Ready(()), + Poll::Pending => Poll::Pending, } } diff --git a/vendor/tokio/src/fs/file/tests.rs b/vendor/tokio/src/fs/file/tests.rs index 28b5ffe77..7c61b3c4b 100644 --- a/vendor/tokio/src/fs/file/tests.rs +++ b/vendor/tokio/src/fs/file/tests.rs @@ -228,14 +228,15 @@ fn flush_while_idle() { } #[test] +#[cfg_attr(miri, ignore)] // takes a really long time with miri fn read_with_buffer_larger_than_max() { // Chunks - let chunk_a = 16 * 1024; + let chunk_a = crate::io::blocking::MAX_BUF; let chunk_b = chunk_a * 2; let chunk_c = chunk_a * 3; let chunk_d = chunk_a * 4; - assert_eq!(chunk_d / 1024, 64); + assert_eq!(chunk_d / 1024 / 1024, 8); let mut data = vec![]; for i in 0..(chunk_d - 1) { @@ -299,14 +300,15 @@ fn read_with_buffer_larger_than_max() { } #[test] +#[cfg_attr(miri, ignore)] // takes a really long time with miri fn write_with_buffer_larger_than_max() { // Chunks - let chunk_a = 16 * 1024; + let chunk_a = crate::io::blocking::MAX_BUF; let chunk_b = chunk_a * 2; let chunk_c = chunk_a * 3; let chunk_d = chunk_a * 4; - assert_eq!(chunk_d / 1024, 64); + assert_eq!(chunk_d / 1024 / 1024, 8); let mut data = vec![]; for i in 0..(chunk_d - 1) { @@ -953,3 +955,24 @@ fn partial_read_set_len_ok() { assert_eq!(n, FOO.len()); assert_eq!(&buf[..n], FOO); } + +#[test] +fn busy_file_seek_error() { + let mut file = MockFile::default(); + let mut seq = Sequence::new(); + file.expect_inner_write() + .once() + .in_sequence(&mut seq) + .returning(|_| Err(io::ErrorKind::Other.into())); + + let mut file = crate::io::BufReader::new(File::from_std(file)); + { + let mut t = task::spawn(file.write(HELLO)); + assert_ready_ok!(t.poll()); + } + + pool::run_one(); + + let mut t = task::spawn(file.seek(SeekFrom::Start(0))); + assert_ready_err!(t.poll()); +} diff --git a/vendor/tokio/src/fs/mocks.rs b/vendor/tokio/src/fs/mocks.rs index 68ef4f3a7..aa01e2471 100644 --- a/vendor/tokio/src/fs/mocks.rs +++ b/vendor/tokio/src/fs/mocks.rs @@ -81,7 +81,7 @@ impl Write for &'_ MockFile { } } -thread_local! { +tokio_thread_local! { static QUEUE: RefCell<VecDeque<Box<dyn FnOnce() + Send>>> = RefCell::new(VecDeque::new()) } @@ -105,6 +105,21 @@ where JoinHandle { rx } } +pub(super) fn spawn_mandatory_blocking<F, R>(f: F) -> Option<JoinHandle<R>> +where + F: FnOnce() -> R + Send + 'static, + R: Send + 'static, +{ + let (tx, rx) = oneshot::channel(); + let task = Box::new(move || { + let _ = tx.send(f()); + }); + + QUEUE.with(|cell| cell.borrow_mut().push_back(task)); + + Some(JoinHandle { rx }) +} + impl<T> Future for JoinHandle<T> { type Output = Result<T, io::Error>; diff --git a/vendor/tokio/src/fs/mod.rs b/vendor/tokio/src/fs/mod.rs index ca0264b36..f6d9605fe 100644 --- a/vendor/tokio/src/fs/mod.rs +++ b/vendor/tokio/src/fs/mod.rs @@ -22,6 +22,24 @@ //! `std::io::ErrorKind::WouldBlock` if a *worker* thread can not be converted //! to a *backup* thread immediately. //! +//! **Warning**: These adapters may create a large number of temporary tasks, +//! especially when reading large files. When performing a lot of operations +//! in one batch, it may be significantly faster to use [`spawn_blocking`] +//! directly: +//! +//! ``` +//! use tokio::fs::File; +//! use std::io::{BufReader, BufRead}; +//! async fn count_lines(file: File) -> Result<usize, std::io::Error> { +//! let file = file.into_std().await; +//! tokio::task::spawn_blocking(move || { +//! let line_count = BufReader::new(file).lines().count(); +//! Ok(line_count) +//! }).await? +//! } +//! ``` +//! +//! [`spawn_blocking`]: fn@crate::task::spawn_blocking //! [`AsyncRead`]: trait@crate::io::AsyncRead mod canonicalize; @@ -84,6 +102,9 @@ pub use self::write::write; mod copy; pub use self::copy::copy; +mod try_exists; +pub use self::try_exists::try_exists; + #[cfg(test)] mod mocks; @@ -94,9 +115,7 @@ feature! { pub use self::symlink::symlink; } -feature! { - #![windows] - +cfg_windows! { mod symlink_dir; pub use self::symlink_dir::symlink_dir; diff --git a/vendor/tokio/src/fs/open_options.rs b/vendor/tokio/src/fs/open_options.rs index 3e73529ec..103510250 100644 --- a/vendor/tokio/src/fs/open_options.rs +++ b/vendor/tokio/src/fs/open_options.rs @@ -10,6 +10,11 @@ use mock_open_options::MockOpenOptions as StdOpenOptions; #[cfg(not(test))] use std::fs::OpenOptions as StdOpenOptions; +#[cfg(unix)] +use std::os::unix::fs::OpenOptionsExt; +#[cfg(windows)] +use std::os::windows::fs::OpenOptionsExt; + /// Options and flags which can be used to configure how a file is opened. /// /// This builder exposes the ability to configure how a [`File`] is opened and @@ -399,8 +404,6 @@ impl OpenOptions { feature! { #![unix] - use std::os::unix::fs::OpenOptionsExt; - impl OpenOptions { /// Sets the mode bits that a new file will be created with. /// @@ -430,7 +433,7 @@ feature! { self } - /// Pass custom flags to the `flags` argument of `open`. + /// Passes custom flags to the `flags` argument of `open`. /// /// The bits that define the access mode are masked out with `O_ACCMODE`, to /// ensure they do not interfere with the access mode set by Rusts options. @@ -464,11 +467,7 @@ feature! { } } -feature! { - #![windows] - - use std::os::windows::fs::OpenOptionsExt; - +cfg_windows! { impl OpenOptions { /// Overrides the `dwDesiredAccess` argument to the call to [`CreateFile`] /// with the specified value. @@ -542,7 +541,7 @@ feature! { /// # Examples /// /// ```no_run - /// use winapi::um::winbase::FILE_FLAG_DELETE_ON_CLOSE; + /// use windows_sys::Win32::Storage::FileSystem::FILE_FLAG_DELETE_ON_CLOSE; /// use tokio::fs::OpenOptions; /// /// # #[tokio::main] @@ -581,7 +580,7 @@ feature! { /// # Examples /// /// ```no_run - /// use winapi::um::winnt::FILE_ATTRIBUTE_HIDDEN; + /// use windows_sys::Win32::Storage::FileSystem::FILE_ATTRIBUTE_HIDDEN; /// use tokio::fs::OpenOptions; /// /// # #[tokio::main] @@ -624,7 +623,7 @@ feature! { /// # Examples /// /// ```no_run - /// use winapi::um::winbase::SECURITY_IDENTIFICATION; + /// use windows_sys::Win32::Storage::FileSystem::SECURITY_IDENTIFICATION; /// use tokio::fs::OpenOptions; /// /// # #[tokio::main] diff --git a/vendor/tokio/src/fs/open_options/mock_open_options.rs b/vendor/tokio/src/fs/open_options/mock_open_options.rs index cbbda0ec2..17b4a4864 100644 --- a/vendor/tokio/src/fs/open_options/mock_open_options.rs +++ b/vendor/tokio/src/fs/open_options/mock_open_options.rs @@ -1,3 +1,4 @@ +#![allow(unreachable_pub)] //! Mock version of std::fs::OpenOptions; use mockall::mock; diff --git a/vendor/tokio/src/fs/read.rs b/vendor/tokio/src/fs/read.rs index 2d80eb5bd..ada5ba391 100644 --- a/vendor/tokio/src/fs/read.rs +++ b/vendor/tokio/src/fs/read.rs @@ -13,8 +13,12 @@ use std::{io, path::Path}; /// buffer based on the file size when available, so it is generally faster than /// reading into a vector created with `Vec::new()`. /// +/// This operation is implemented by running the equivalent blocking operation +/// on a separate thread pool using [`spawn_blocking`]. +/// /// [`File::open`]: super::File::open /// [`read_to_end`]: crate::io::AsyncReadExt::read_to_end +/// [`spawn_blocking`]: crate::task::spawn_blocking /// /// # Errors /// diff --git a/vendor/tokio/src/fs/read_dir.rs b/vendor/tokio/src/fs/read_dir.rs index c1cb665de..def735b3c 100644 --- a/vendor/tokio/src/fs/read_dir.rs +++ b/vendor/tokio/src/fs/read_dir.rs @@ -1,5 +1,6 @@ use crate::fs::asyncify; +use std::collections::VecDeque; use std::ffi::OsString; use std::fs::{FileType, Metadata}; use std::future::Future; @@ -19,17 +20,29 @@ use crate::blocking::spawn_blocking; #[cfg(not(test))] use crate::blocking::JoinHandle; +const CHUNK_SIZE: usize = 32; + /// Returns a stream over the entries within a directory. /// /// This is an async version of [`std::fs::read_dir`](std::fs::read_dir) +/// +/// This operation is implemented by running the equivalent blocking +/// operation on a separate thread pool using [`spawn_blocking`]. +/// +/// [`spawn_blocking`]: crate::task::spawn_blocking pub async fn read_dir(path: impl AsRef<Path>) -> io::Result<ReadDir> { let path = path.as_ref().to_owned(); - let std = asyncify(|| std::fs::read_dir(path)).await?; + asyncify(|| -> io::Result<ReadDir> { + let mut std = std::fs::read_dir(path)?; + let mut buf = VecDeque::with_capacity(CHUNK_SIZE); + let remain = ReadDir::next_chunk(&mut buf, &mut std); - Ok(ReadDir(State::Idle(Some(std)))) + Ok(ReadDir(State::Idle(Some((buf, std, remain))))) + }) + .await } -/// Read the the entries in a directory. +/// Reads the entries in a directory. /// /// This struct is returned from the [`read_dir`] function of this module and /// will yield instances of [`DirEntry`]. Through a [`DirEntry`] information @@ -53,12 +66,16 @@ pub struct ReadDir(State); #[derive(Debug)] enum State { - Idle(Option<std::fs::ReadDir>), - Pending(JoinHandle<(Option<io::Result<std::fs::DirEntry>>, std::fs::ReadDir)>), + Idle(Option<(VecDeque<io::Result<DirEntry>>, std::fs::ReadDir, bool)>), + Pending(JoinHandle<(VecDeque<io::Result<DirEntry>>, std::fs::ReadDir, bool)>), } impl ReadDir { /// Returns the next entry in the directory stream. + /// + /// # Cancel safety + /// + /// This method is cancellation safe. pub async fn next_entry(&mut self) -> io::Result<Option<DirEntry>> { use crate::future::poll_fn; poll_fn(|cx| self.poll_next_entry(cx)).await @@ -85,28 +102,57 @@ impl ReadDir { pub fn poll_next_entry(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<Option<DirEntry>>> { loop { match self.0 { - State::Idle(ref mut std) => { - let mut std = std.take().unwrap(); + State::Idle(ref mut data) => { + let (buf, _, ref remain) = data.as_mut().unwrap(); + + if let Some(ent) = buf.pop_front() { + return Poll::Ready(ent.map(Some)); + } else if !remain { + return Poll::Ready(Ok(None)); + } + + let (mut buf, mut std, _) = data.take().unwrap(); self.0 = State::Pending(spawn_blocking(move || { - let ret = std.next(); - (ret, std) + let remain = ReadDir::next_chunk(&mut buf, &mut std); + (buf, std, remain) })); } State::Pending(ref mut rx) => { - let (ret, std) = ready!(Pin::new(rx).poll(cx))?; - self.0 = State::Idle(Some(std)); + self.0 = State::Idle(Some(ready!(Pin::new(rx).poll(cx))?)); + } + } + } + } - let ret = match ret { - Some(Ok(std)) => Ok(Some(DirEntry(Arc::new(std)))), - Some(Err(e)) => Err(e), - None => Ok(None), - }; + fn next_chunk(buf: &mut VecDeque<io::Result<DirEntry>>, std: &mut std::fs::ReadDir) -> bool { + for _ in 0..CHUNK_SIZE { + let ret = match std.next() { + Some(ret) => ret, + None => return false, + }; - return Poll::Ready(ret); - } + let success = ret.is_ok(); + + buf.push_back(ret.map(|std| DirEntry { + #[cfg(not(any( + target_os = "solaris", + target_os = "illumos", + target_os = "haiku", + target_os = "vxworks", + target_os = "nto", + target_os = "vita", + )))] + file_type: std.file_type().ok(), + std: Arc::new(std), + })); + + if !success { + break; } } + + true } } @@ -151,7 +197,18 @@ feature! { /// filesystem. Each entry can be inspected via methods to learn about the full /// path or possibly other metadata through per-platform extension traits. #[derive(Debug)] -pub struct DirEntry(Arc<std::fs::DirEntry>); +pub struct DirEntry { + #[cfg(not(any( + target_os = "solaris", + target_os = "illumos", + target_os = "haiku", + target_os = "vxworks", + target_os = "nto", + target_os = "vita", + )))] + file_type: Option<FileType>, + std: Arc<std::fs::DirEntry>, +} impl DirEntry { /// Returns the full path to the file that this entry represents. @@ -184,7 +241,7 @@ impl DirEntry { /// /// The exact text, of course, depends on what files you have in `.`. pub fn path(&self) -> PathBuf { - self.0.path() + self.std.path() } /// Returns the bare file name of this directory entry without any other @@ -205,7 +262,7 @@ impl DirEntry { /// # } /// ``` pub fn file_name(&self) -> OsString { - self.0.file_name() + self.std.file_name() } /// Returns the metadata for the file that this entry points at. @@ -239,7 +296,7 @@ impl DirEntry { /// # } /// ``` pub async fn metadata(&self) -> io::Result<Metadata> { - let std = self.0.clone(); + let std = self.std.clone(); asyncify(move || std.metadata()).await } @@ -274,13 +331,25 @@ impl DirEntry { /// # } /// ``` pub async fn file_type(&self) -> io::Result<FileType> { - let std = self.0.clone(); + #[cfg(not(any( + target_os = "solaris", + target_os = "illumos", + target_os = "haiku", + target_os = "vxworks", + target_os = "nto", + target_os = "vita", + )))] + if let Some(file_type) = self.file_type { + return Ok(file_type); + } + + let std = self.std.clone(); asyncify(move || std.file_type()).await } - /// Returns a reference to the underlying `std::fs::DirEntry` + /// Returns a reference to the underlying `std::fs::DirEntry`. #[cfg(unix)] pub(super) fn as_inner(&self) -> &std::fs::DirEntry { - &self.0 + &self.std } } diff --git a/vendor/tokio/src/fs/read_to_string.rs b/vendor/tokio/src/fs/read_to_string.rs index 4f37986d6..26228d98c 100644 --- a/vendor/tokio/src/fs/read_to_string.rs +++ b/vendor/tokio/src/fs/read_to_string.rs @@ -7,6 +7,10 @@ use std::{io, path::Path}; /// /// This is the async equivalent of [`std::fs::read_to_string`][std]. /// +/// This operation is implemented by running the equivalent blocking operation +/// on a separate thread pool using [`spawn_blocking`]. +/// +/// [`spawn_blocking`]: crate::task::spawn_blocking /// [std]: fn@std::fs::read_to_string /// /// # Examples diff --git a/vendor/tokio/src/fs/symlink_dir.rs b/vendor/tokio/src/fs/symlink_dir.rs index 736e762b4..6753c25eb 100644 --- a/vendor/tokio/src/fs/symlink_dir.rs +++ b/vendor/tokio/src/fs/symlink_dir.rs @@ -10,7 +10,7 @@ use std::path::Path; /// /// This is an async version of [`std::os::windows::fs::symlink_dir`][std] /// -/// [std]: std::os::windows::fs::symlink_dir +/// [std]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_dir.html pub async fn symlink_dir(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> { let src = src.as_ref().to_owned(); let dst = dst.as_ref().to_owned(); diff --git a/vendor/tokio/src/fs/symlink_file.rs b/vendor/tokio/src/fs/symlink_file.rs index 07d8e6041..623352a1b 100644 --- a/vendor/tokio/src/fs/symlink_file.rs +++ b/vendor/tokio/src/fs/symlink_file.rs @@ -10,7 +10,7 @@ use std::path::Path; /// /// This is an async version of [`std::os::windows::fs::symlink_file`][std] /// -/// [std]: std::os::windows::fs::symlink_file +/// [std]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_file.html pub async fn symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> { let src = src.as_ref().to_owned(); let dst = dst.as_ref().to_owned(); diff --git a/vendor/tokio/src/fs/try_exists.rs b/vendor/tokio/src/fs/try_exists.rs new file mode 100644 index 000000000..069518bf9 --- /dev/null +++ b/vendor/tokio/src/fs/try_exists.rs @@ -0,0 +1,34 @@ +use crate::fs::asyncify; + +use std::io; +use std::path::Path; + +/// Returns `Ok(true)` if the path points at an existing entity. +/// +/// This function will traverse symbolic links to query information about the +/// destination file. In case of broken symbolic links this will return `Ok(false)`. +/// +/// This is the async equivalent of [`std::path::Path::try_exists`][std]. +/// +/// [std]: fn@std::path::Path::try_exists +/// +/// # Examples +/// +/// ```no_run +/// use tokio::fs; +/// +/// # async fn dox() -> std::io::Result<()> { +/// fs::try_exists("foo.txt").await?; +/// # Ok(()) +/// # } +/// ``` +pub async fn try_exists(path: impl AsRef<Path>) -> io::Result<bool> { + let path = path.as_ref().to_owned(); + // std's Path::try_exists is not available for current Rust min supported version. + // Current implementation is based on its internal implementation instead. + match asyncify(move || std::fs::metadata(path)).await { + Ok(_) => Ok(true), + Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(false), + Err(error) => Err(error), + } +} diff --git a/vendor/tokio/src/fs/write.rs b/vendor/tokio/src/fs/write.rs index 0ed908271..28606fb36 100644 --- a/vendor/tokio/src/fs/write.rs +++ b/vendor/tokio/src/fs/write.rs @@ -7,6 +7,10 @@ use std::{io, path::Path}; /// /// This is the async equivalent of [`std::fs::write`][std]. /// +/// This operation is implemented by running the equivalent blocking operation +/// on a separate thread pool using [`spawn_blocking`]. +/// +/// [`spawn_blocking`]: crate::task::spawn_blocking /// [std]: fn@std::fs::write /// /// # Examples |