Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions library/std/src/fs/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,14 @@ fn open_flavors() {
assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 9);
}

#[test]
#[cfg(windows)]
fn windows_access_mode_override() {
// ensure that using access_mode negates the need for using write or append
use crate::os::windows::fs::OpenOptionsExt;
File::options().create(true).access_mode(0).open(tmpdir().join("foo.txt")).unwrap();
}

#[test]
fn _assert_send_sync() {
fn _assert_send_sync<T: Send + Sync>() {}
Expand Down
66 changes: 23 additions & 43 deletions library/std/src/sys/fs/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,54 +263,34 @@ impl OpenOptions {
}

fn get_access_mode(&self) -> io::Result<u32> {
match (self.read, self.write, self.append, self.access_mode) {
(.., Some(mode)) => Ok(mode),
(true, false, false, None) => Ok(c::GENERIC_READ),
(false, true, false, None) => Ok(c::GENERIC_WRITE),
(true, true, false, None) => Ok(c::GENERIC_READ | c::GENERIC_WRITE),
(false, _, true, None) => Ok(c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA),
(true, _, true, None) => {
Ok(c::GENERIC_READ | (c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA))
}
(false, false, false, None) => {
// If no access mode is set, check if any creation flags are set
// to provide a more descriptive error message
if self.create || self.create_new || self.truncate {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"creating or truncating a file requires write or append access",
))
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"must specify at least one of read, write, or append access",
))
}
}
if let Some(access) = self.access_mode {
return Ok(access);
}
}

fn get_cmode_disposition(&self) -> io::Result<(u32, u32)> {
match (self.write, self.append) {
(true, false) => {}
(false, false) => {
if self.truncate || self.create || self.create_new {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"creating or truncating a file requires write or append access",
));
}
}
(_, true) => {
if self.truncate && !self.create_new {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"append and truncate cannot both be enabled",
));
}
match (self.read, self.write, self.append) {
(_, false, false) if self.truncate || self.create || self.create_new => {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"creating or truncating a file requires write or append access",
))
}
(_, _, true) if self.truncate && !self.create_new => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"append and truncate cannot both be enabled",
)),
(true, false, false) => Ok(c::GENERIC_READ),
(false, true, false) => Ok(c::GENERIC_WRITE),
(true, true, false) => Ok(c::GENERIC_READ | c::GENERIC_WRITE),
(false, _, true) => Ok(c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA),
(true, _, true) => Ok(c::GENERIC_READ | (c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA)),
(false, false, false) => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"must specify at least one of read, write, or append access",
)),
}
}

fn get_cmode_disposition(&self) -> io::Result<(u32, u32)> {
Ok(match (self.create, self.truncate, self.create_new) {
(false, false, false) => (c::OPEN_EXISTING, c::FILE_OPEN),
(true, false, false) => (c::OPEN_ALWAYS, c::FILE_OPEN_IF),
Expand Down
Loading