tokio/fs/try_exists.rs
1use crate::fs::asyncify;
2
3use std::io;
4use std::path::Path;
5
6/// Returns `Ok(true)` if the path points at an existing entity.
7///
8/// This function will traverse symbolic links to query information about the
9/// destination file. In case of broken symbolic links this will return `Ok(false)`.
10///
11/// This is the async equivalent of [`std::path::Path::try_exists`][std].
12///
13/// [std]: fn@std::path::Path::try_exists
14///
15/// # Examples
16///
17/// ```no_run
18/// use tokio::fs;
19///
20/// # async fn dox() -> std::io::Result<()> {
21/// fs::try_exists("foo.txt").await?;
22/// # Ok(())
23/// # }
24/// ```
25pub async fn try_exists(path: impl AsRef<Path>) -> io::Result<bool> {
26 let path = path.as_ref();
27
28 #[cfg(all(
29 tokio_unstable,
30 feature = "io-uring",
31 feature = "rt",
32 feature = "fs",
33 // libc::statx is only supported on these platforms
34 // FIXME: Add musl target env when our minimum supported
35 // rust version is 1.93. To clarify, statx support is
36 // introduced to musl in 1.25 as mentioned officially here:
37 // https://musl.libc.org/releases.html.
38 // However, rustup target_env building for *-linux-musl
39 // uses 1.25 musl on all *-linux-musl platforms starting
40 // in 1.93 stable rust version.
41 // https://blog.rust-lang.org/2025/12/05/Updating-musl-1.2.5/
42 any(target_env = "gnu", target_os = "android")
43 ))]
44 {
45 let handle = crate::runtime::Handle::current();
46 let driver_handle = handle.inner.driver().io();
47 if driver_handle
48 .check_and_init(io_uring::opcode::Statx::CODE)
49 .await?
50 {
51 return try_exists_uring(path).await;
52 }
53 }
54
55 try_exists_spawn_blocking(path).await
56}
57
58cfg_io_uring! {
59 #[inline]
60 #[cfg(
61 // libc::statx is only supported on these platforms
62 // FIXME: Add musl target env when our minimum supported
63 // rust version is 1.93. To clarify, statx support is
64 // introduced to musl in 1.25 as mentioned officially here:
65 // https://musl.libc.org/releases.html.
66 // However, rustup target_env building for *-linux-musl
67 // uses 1.25 musl on all *-linux-musl platforms starting
68 // in 1.93 stable rust version.
69 // https://blog.rust-lang.org/2025/12/05/Updating-musl-1.2.5/
70 any(target_env = "gnu", target_os = "android")
71 )]
72 async fn try_exists_uring(path: &Path) -> io::Result<bool> {
73 use crate::runtime::driver::op::Op;
74
75 match Op::metadata(path)?.await {
76 Ok(_) => Ok(true),
77 Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
78 Err(error) => Err(error),
79 }
80 }
81}
82
83async fn try_exists_spawn_blocking(path: &Path) -> io::Result<bool> {
84 let path = path.to_owned();
85 // FIXME: When MSRV is 1.81, change this to
86 // std::fs::exists() to be consistent with
87 // all other tokio::fs operations
88 asyncify(move || path.try_exists()).await
89}