Skip to content

Commit

Permalink
add try_exists
Browse files Browse the repository at this point in the history
This is new in Rust 1.63, but can be backfilled to older versions of
Rust by camino.
  • Loading branch information
sunshowers committed Aug 11, 2022
1 parent 95668b9 commit 30cb807
Showing 1 changed file with 41 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1286,6 +1286,9 @@ impl Utf8Path {

/// Returns `true` if the path points at an existing entity.
///
/// Warning: this method may be error-prone, consider using [`try_exists()`] instead!
/// It also has a risk of introducing time-of-check to time-of-use (TOCTOU) bugs.
///
/// This function will traverse symbolic links to query information about the
/// destination file. In case of broken symbolic links this will return `false`.
///
Expand All @@ -1308,6 +1311,44 @@ impl Utf8Path {
self.0.exists()
}

/// 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)`.
///
/// As opposed to the [`exists()`] method, this one doesn't silently ignore errors
/// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission
/// denied on some of the parent directories.)
///
/// Note that while this avoids some pitfalls of the `exists()` method, it still can not
/// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios
/// where those bugs are not an issue.
///
/// # Examples
///
/// ```no_run
/// use camino::Utf8Path;
/// assert!(!Utf8Path::new("does_not_exist.txt").try_exists().expect("Can't check existence of file does_not_exist.txt"));
/// assert!(Utf8Path::new("/root/secret_file.txt").try_exists().is_err());
/// ```
///
/// [`exists()`]: Self::exists
#[inline]
pub fn try_exists(&self) -> io::Result<bool> {
// Note: this block is written this way rather than with a pattern guard to appease Rust
// 1.34.
match fs::metadata(self) {
Ok(_) => Ok(true),
Err(error) => {
if error.kind() == io::ErrorKind::NotFound {
Ok(false)
} else {
Err(error)
}
}
}
}

/// Returns `true` if the path exists on disk and is pointing at a regular file.
///
/// This function will traverse symbolic links to query information about the
Expand Down

0 comments on commit 30cb807

Please sign in to comment.