Skip to content

Commit 4bd962b

Browse files
committed
Windows: remove readonly files
1 parent 908af5b commit 4bd962b

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

Diff for: library/std/src/fs/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1384,7 +1384,7 @@ fn file_try_clone() {
13841384
}
13851385

13861386
#[test]
1387-
#[cfg(not(windows))]
1387+
#[cfg(not(target_vendor = "win7"))]
13881388
fn unlink_readonly() {
13891389
let tmpdir = tmpdir();
13901390
let path = tmpdir.join("file");

Diff for: library/std/src/sys/pal/windows/fs.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,10 @@ impl OpenOptions {
296296
impl File {
297297
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
298298
let path = maybe_verbatim(path)?;
299+
Self::open_native(&path, opts)
300+
}
301+
302+
fn open_native(path: &[u16], opts: &OpenOptions) -> io::Result<File> {
299303
let creation = opts.get_creation_mode()?;
300304
let handle = unsafe {
301305
c::CreateFileW(
@@ -1217,8 +1221,24 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
12171221

12181222
pub fn unlink(p: &Path) -> io::Result<()> {
12191223
let p_u16s = maybe_verbatim(p)?;
1220-
cvt(unsafe { c::DeleteFileW(p_u16s.as_ptr()) })?;
1221-
Ok(())
1224+
if unsafe { c::DeleteFileW(p_u16s.as_ptr()) } == 0 {
1225+
let err = api::get_last_error();
1226+
// if `DeleteFileW` fails with ERROR_ACCESS_DENIED then try to remove
1227+
// the file while ignoring the readonly attribute.
1228+
// This is accomplished by calling the `posix_delete` function on an open file handle.
1229+
if err == WinError::ACCESS_DENIED {
1230+
let mut opts = OpenOptions::new();
1231+
opts.access_mode(c::DELETE);
1232+
opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT);
1233+
if File::open_native(&p_u16s, &opts).map(|f| f.posix_delete()).is_ok() {
1234+
return Ok(());
1235+
}
1236+
}
1237+
// return the original error if any of the above fails.
1238+
Err(io::Error::from_raw_os_error(err.code as i32))
1239+
} else {
1240+
Ok(())
1241+
}
12221242
}
12231243

12241244
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {

0 commit comments

Comments
 (0)