about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorMartin Habovstiak <martin.habovstiak@gmail.com>2022-06-09 12:34:23 +0200
committerMartin Habovstiak <martin.habovstiak@gmail.com>2022-06-14 17:48:55 +0200
commit56087074c655bc17af048ad6483ecf7c32ce1762 (patch)
treec00b07a20adb9782b637db413feae58de7b8a1be /library/std/src
parentedab34ab2abbafc16a78daedf71dbacd2eb0b7bf (diff)
downloadrust-56087074c655bc17af048ad6483ecf7c32ce1762.tar.gz
rust-56087074c655bc17af048ad6483ecf7c32ce1762.zip
Stabilize `Path::try_exists()` and improve doc
This stabilizes the `Path::try_exists()` method which returns
`Result<bool, io::Error>` instead of `bool` allowing handling of errors
unrelated to the file not existing. (e.g permission errors)

Along with the stabilization it also:

* Warns that the `exists()` method is error-prone and suggests to use
  the newly stabilized one.
* Suggests it instead of `metadata()` to handle errors.
* Mentions TOCTOU bugs to avoid false assumption that `try_exists()` is
  completely safe fixed version of `exists()`.
* Renames the feature of still-unstable `std::fs::try_exists()` to
  `fs_try_exists` to avoid name conflict.

The tracking issue #83186 remains open to track `fs_try_exists`.
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/fs.rs8
-rw-r--r--library/std/src/path.rs17
2 files changed, 17 insertions, 8 deletions
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 55bd2c59406..f46997b807a 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -2317,10 +2317,14 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
 /// 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
-/// #![feature(path_try_exists)]
+/// #![feature(fs_try_exists)]
 /// use std::fs;
 ///
 /// assert!(!fs::try_exists("does_not_exist.txt").expect("Can't check existence of file does_not_exist.txt"));
@@ -2330,7 +2334,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
 /// [`Path::exists`]: crate::path::Path::exists
 // FIXME: stabilization should modify documentation of `exists()` to recommend this method
 // instead.
-#[unstable(feature = "path_try_exists", issue = "83186")]
+#[unstable(feature = "fs_try_exists", issue = "83186")]
 #[inline]
 pub fn try_exists<P: AsRef<Path>>(path: P) -> io::Result<bool> {
     fs_imp::try_exists(path.as_ref())
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 36d6469c02d..c56d5aa9b2e 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2705,6 +2705,9 @@ impl Path {
 
     /// 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.
     ///
@@ -2721,7 +2724,9 @@ impl Path {
     /// # See Also
     ///
     /// This is a convenience function that coerces errors to false. If you want to
-    /// check errors, call [`fs::metadata`].
+    /// check errors, call [`Path::try_exists`].
+    ///
+    /// [`try_exists()`]: Self::try_exists
     #[stable(feature = "path_ext", since = "1.5.0")]
     #[must_use]
     #[inline]
@@ -2738,20 +2743,20 @@ impl Path {
     /// 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
-    /// #![feature(path_try_exists)]
-    ///
     /// use std::path::Path;
     /// assert!(!Path::new("does_not_exist.txt").try_exists().expect("Can't check existence of file does_not_exist.txt"));
     /// assert!(Path::new("/root/secret_file.txt").try_exists().is_err());
     /// ```
     ///
     /// [`exists()`]: Self::exists
-    // FIXME: stabilization should modify documentation of `exists()` to recommend this method
-    // instead.
-    #[unstable(feature = "path_try_exists", issue = "83186")]
+    #[stable(feature = "path_try_exists", since = "1.63.0")]
     #[inline]
     pub fn try_exists(&self) -> io::Result<bool> {
         fs::try_exists(self)