summaryrefslogtreecommitdiffstats
path: root/vendor/tokio/src/fs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/tokio/src/fs
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-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.rs2
-rw-r--r--vendor/tokio/src/fs/dir_builder.rs2
-rw-r--r--vendor/tokio/src/fs/file.rs120
-rw-r--r--vendor/tokio/src/fs/file/tests.rs31
-rw-r--r--vendor/tokio/src/fs/mocks.rs17
-rw-r--r--vendor/tokio/src/fs/mod.rs25
-rw-r--r--vendor/tokio/src/fs/open_options.rs21
-rw-r--r--vendor/tokio/src/fs/open_options/mock_open_options.rs1
-rw-r--r--vendor/tokio/src/fs/read.rs4
-rw-r--r--vendor/tokio/src/fs/read_dir.rs119
-rw-r--r--vendor/tokio/src/fs/read_to_string.rs4
-rw-r--r--vendor/tokio/src/fs/symlink_dir.rs2
-rw-r--r--vendor/tokio/src/fs/symlink_file.rs2
-rw-r--r--vendor/tokio/src/fs/try_exists.rs34
-rw-r--r--vendor/tokio/src/fs/write.rs4
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