about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChris Denton <christophersdenton@gmail.com>2021-05-18 04:18:46 +0100
committerChris Denton <christophersdenton@gmail.com>2021-05-19 23:55:33 +0100
commit86dbc063ab15e67b2b7ed5411eb9fec9f7afbcb4 (patch)
tree7a5aa1540daedb997a0449ac452004136c1ff9d7
parent2c2c1593acc5479a4b502d51bb5fea239766c235 (diff)
downloadrust-86dbc063ab15e67b2b7ed5411eb9fec9f7afbcb4.tar.gz
rust-86dbc063ab15e67b2b7ed5411eb9fec9f7afbcb4.zip
Windows implementation of `fs::try_exists`
-rw-r--r--library/std/src/sys/windows/c.rs1
-rw-r--r--library/std/src/sys/windows/fs.rs30
2 files changed, 30 insertions, 1 deletions
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index e91c489361e..50d6e8cf27a 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -173,6 +173,7 @@ pub const ERROR_INVALID_HANDLE: DWORD = 6;
 pub const ERROR_NOT_ENOUGH_MEMORY: DWORD = 8;
 pub const ERROR_OUTOFMEMORY: DWORD = 14;
 pub const ERROR_NO_MORE_FILES: DWORD = 18;
+pub const ERROR_SHARING_VIOLATION: u32 = 32;
 pub const ERROR_HANDLE_EOF: DWORD = 38;
 pub const ERROR_FILE_EXISTS: DWORD = 80;
 pub const ERROR_INVALID_PARAMETER: DWORD = 87;
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 36b395507b1..2b6143de960 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -11,7 +11,6 @@ use crate::sync::Arc;
 use crate::sys::handle::Handle;
 use crate::sys::time::SystemTime;
 use crate::sys::{c, cvt};
-pub use crate::sys_common::fs::try_exists;
 use crate::sys_common::FromInner;
 
 use super::to_u16s;
@@ -945,3 +944,32 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
         .map(drop)
     }
 }
+
+// Try to see if a file exists but, unlike `exists`, report I/O errors.
+pub fn try_exists(path: &Path) -> io::Result<bool> {
+    // Open the file to ensure any symlinks are followed to their target.
+    let mut opts = OpenOptions::new();
+    // No read, write, etc access rights are needed.
+    opts.access_mode(0);
+    // Backup semantics enables opening directories as well as files.
+    opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS);
+    match File::open(path, &opts) {
+        Err(e) => match e.kind() {
+            // The file definitely does not exist
+            io::ErrorKind::NotFound => Ok(false),
+
+            // `ERROR_SHARING_VIOLATION` means that the file has been locked by
+            // another process. This is often temporary so we simply report it
+            // as the file existing.
+            io::ErrorKind::Other if e.raw_os_error() == Some(c::ERROR_SHARING_VIOLATION as i32) => {
+                Ok(true)
+            }
+            // Other errors such as `ERROR_ACCESS_DENIED` may indicate that the
+            // file exists. However, these types of errors are usually more
+            // permanent so we report them here.
+            _ => Err(e),
+        },
+        // The file was opened successfully therefore it must exist,
+        Ok(_) => Ok(true),
+    }
+}