mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-15 00:00:15 +02:00
fs: add fs::try_exists (#4299)
This commit is contained in:
@@ -102,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;
|
||||
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![cfg(all(feature = "full", not(tokio_wasi)))] // Wasi does not support file operations
|
||||
|
||||
use tempfile::tempdir;
|
||||
use tokio::fs;
|
||||
|
||||
#[tokio::test]
|
||||
async fn try_exists() {
|
||||
let dir = tempdir().unwrap();
|
||||
|
||||
let existing_path = dir.path().join("foo.txt");
|
||||
fs::write(&existing_path, b"Hello File!").await.unwrap();
|
||||
let nonexisting_path = dir.path().join("bar.txt");
|
||||
|
||||
assert!(fs::try_exists(existing_path).await.unwrap());
|
||||
assert!(!fs::try_exists(nonexisting_path).await.unwrap());
|
||||
// FreeBSD root user always has permission to stat.
|
||||
#[cfg(all(unix, not(target_os = "freebsd")))]
|
||||
{
|
||||
use std::os::unix::prelude::PermissionsExt;
|
||||
let permission_denied_directory_path = dir.path().join("baz");
|
||||
fs::create_dir(&permission_denied_directory_path)
|
||||
.await
|
||||
.unwrap();
|
||||
let permission_denied_file_path = permission_denied_directory_path.join("baz.txt");
|
||||
fs::write(&permission_denied_file_path, b"Hello File!")
|
||||
.await
|
||||
.unwrap();
|
||||
let mut perms = tokio::fs::metadata(&permission_denied_directory_path)
|
||||
.await
|
||||
.unwrap()
|
||||
.permissions();
|
||||
|
||||
perms.set_mode(0o244);
|
||||
fs::set_permissions(&permission_denied_directory_path, perms)
|
||||
.await
|
||||
.unwrap();
|
||||
let permission_denied_result = fs::try_exists(permission_denied_file_path).await;
|
||||
assert_eq!(
|
||||
permission_denied_result.err().unwrap().kind(),
|
||||
std::io::ErrorKind::PermissionDenied
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user