diff --git a/cap-fs-ext/src/open_options_maybe_dir_ext.rs b/cap-fs-ext/src/open_options_maybe_dir_ext.rs index 52b687f8..a286adf0 100644 --- a/cap-fs-ext/src/open_options_maybe_dir_ext.rs +++ b/cap-fs-ext/src/open_options_maybe_dir_ext.rs @@ -1,11 +1,13 @@ /// Extension trait for `cap_primitives::fs::OpenOptions` which adds -/// `maybe_dir`, a function for controlling whether an open should -/// attempt to succeed on a directory. On Posix-ish platforms, opening -/// a directory always succeeds, but on Windows, opening a directory -/// needs this option. +/// `maybe_dir`, a function for controlling whether an open should attempt to +/// succeed on a directory. On Posix-ish platforms, opening a directory always +/// succeeds, but on Windows, opening a directory needs this option. pub trait OpenOptionsMaybeDirExt { - /// Sets the option for disabling an error that might be generated - /// by the opened object being a directory. + /// Sets the option for disabling an error that might be generated by the + /// opened object being a directory. + /// + /// On some platforms, this may prevent the directory from being deleted + /// or renamed while the handle is open. fn maybe_dir(&mut self, maybe_dir: bool) -> &mut Self; } diff --git a/cap-primitives/src/windows/fs/oflags.rs b/cap-primitives/src/windows/fs/oflags.rs index f2867e0a..8f5022a5 100644 --- a/cap-primitives/src/windows/fs/oflags.rs +++ b/cap-primitives/src/windows/fs/oflags.rs @@ -2,7 +2,7 @@ use crate::fs::{FollowSymlinks, OpenOptions}; use std::fs; use std::os::windows::fs::OpenOptionsExt; use windows_sys::Win32::Storage::FileSystem::{ - FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT, + FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, }; /// Translate the given `cap_std` into `std` options. Also return a bool @@ -24,8 +24,15 @@ pub(in super::super) fn open_options_to_std(opts: &OpenOptions) -> (fs::OpenOpti opts.ext.custom_flags | FILE_FLAG_OPEN_REPARSE_POINT } }; + let mut share_mode = opts.ext.share_mode; if opts.maybe_dir { custom_flags |= FILE_FLAG_BACKUP_SEMANTICS; + + // Only allow `FILE_SHARE_READ` and `FILE_SHARE_WRITE`; this mirrors + // the values in `dir_options()` and is done to prevent directories + // from being deleted or renamed underneath cap-std's sandboxed path + // lookups on Windows. + share_mode &= !FILE_SHARE_DELETE; } let mut std_opts = fs::OpenOptions::new(); std_opts @@ -35,7 +42,7 @@ pub(in super::super) fn open_options_to_std(opts: &OpenOptions) -> (fs::OpenOpti .truncate(trunc) .create(opts.create) .create_new(opts.create_new) - .share_mode(opts.ext.share_mode) + .share_mode(share_mode) .custom_flags(custom_flags) .attributes(opts.ext.attributes);