Skip to content

Commit 2257b07

Browse files
authored
Unrolled build for rust-lang#134679
Rollup merge of rust-lang#134679 - ChrisDenton:rm-readonly, r=Mark-Simulacrum Windows: remove readonly files When calling `remove_file`, we shouldn't fail to delete readonly files. As the test makes clear, this make the Windows behaviour consistent with other platforms. This also makes us internally consistent with `remove_dir_all`. try-job: x86_64-msvc-ext1
2 parents 1ff2135 + 962ebf0 commit 2257b07

File tree

4 files changed

+35
-5
lines changed

4 files changed

+35
-5
lines changed

library/std/src/fs.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2307,8 +2307,8 @@ impl AsInner<fs_imp::DirEntry> for DirEntry {
23072307
///
23082308
/// # Platform-specific behavior
23092309
///
2310-
/// This function currently corresponds to the `unlink` function on Unix
2311-
/// and the `DeleteFile` function on Windows.
2310+
/// This function currently corresponds to the `unlink` function on Unix.
2311+
/// On Windows, `DeleteFile` is used or `CreateFileW` and `SetInformationByHandle` for readonly files.
23122312
/// Note that, this [may change in the future][changes].
23132313
///
23142314
/// [changes]: io#platform-specific-behavior

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");

library/std/src/sys/pal/windows/fs.rs

+24-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(
@@ -1226,8 +1230,26 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
12261230

12271231
pub fn unlink(p: &Path) -> io::Result<()> {
12281232
let p_u16s = maybe_verbatim(p)?;
1229-
cvt(unsafe { c::DeleteFileW(p_u16s.as_ptr()) })?;
1230-
Ok(())
1233+
if unsafe { c::DeleteFileW(p_u16s.as_ptr()) } == 0 {
1234+
let err = api::get_last_error();
1235+
// if `DeleteFileW` fails with ERROR_ACCESS_DENIED then try to remove
1236+
// the file while ignoring the readonly attribute.
1237+
// This is accomplished by calling the `posix_delete` function on an open file handle.
1238+
if err == WinError::ACCESS_DENIED {
1239+
let mut opts = OpenOptions::new();
1240+
opts.access_mode(c::DELETE);
1241+
opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT);
1242+
if let Ok(f) = File::open_native(&p_u16s, &opts) {
1243+
if f.posix_delete().is_ok() {
1244+
return Ok(());
1245+
}
1246+
}
1247+
}
1248+
// return the original error if any of the above fails.
1249+
Err(io::Error::from_raw_os_error(err.code as i32))
1250+
} else {
1251+
Ok(())
1252+
}
12311253
}
12321254

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

library/std/tests/win_delete_self.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![cfg(windows)]
2+
3+
/// Attempting to delete a running binary should return an error on Windows.
4+
#[test]
5+
fn win_delete_self() {
6+
let path = std::env::current_exe().unwrap();
7+
assert!(std::fs::remove_file(path).is_err());
8+
}

0 commit comments

Comments
 (0)