diff options
| author | Urgau <3616612+Urgau@users.noreply.github.com> | 2025-02-09 00:37:26 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-09 00:37:26 +0100 |
| commit | 34182470ebbc0c8fd67f09c7902b3bd44f4abbe5 (patch) | |
| tree | 7d939978e6272a27d5e64358662e8176c5725a45 /library/std/src/sys | |
| parent | 73bf7947e9ab731bf2764db219cd9cda216a3aed (diff) | |
| parent | 962ebf0a48436445cf300efc0fa552044f4ca19d (diff) | |
| download | rust-34182470ebbc0c8fd67f09c7902b3bd44f4abbe5.tar.gz rust-34182470ebbc0c8fd67f09c7902b3bd44f4abbe5.zip | |
Rollup merge of #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
Diffstat (limited to 'library/std/src/sys')
| -rw-r--r-- | library/std/src/sys/pal/windows/fs.rs | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index f8493c21ad4..bdb55643bb1 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -296,6 +296,10 @@ impl OpenOptions { impl File { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> { let path = maybe_verbatim(path)?; + Self::open_native(&path, opts) + } + + fn open_native(path: &[u16], opts: &OpenOptions) -> io::Result<File> { let creation = opts.get_creation_mode()?; let handle = unsafe { c::CreateFileW( @@ -1226,8 +1230,26 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> { pub fn unlink(p: &Path) -> io::Result<()> { let p_u16s = maybe_verbatim(p)?; - cvt(unsafe { c::DeleteFileW(p_u16s.as_ptr()) })?; - Ok(()) + if unsafe { c::DeleteFileW(p_u16s.as_ptr()) } == 0 { + let err = api::get_last_error(); + // if `DeleteFileW` fails with ERROR_ACCESS_DENIED then try to remove + // the file while ignoring the readonly attribute. + // This is accomplished by calling the `posix_delete` function on an open file handle. + if err == WinError::ACCESS_DENIED { + let mut opts = OpenOptions::new(); + opts.access_mode(c::DELETE); + opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT); + if let Ok(f) = File::open_native(&p_u16s, &opts) { + if f.posix_delete().is_ok() { + return Ok(()); + } + } + } + // return the original error if any of the above fails. + Err(io::Error::from_raw_os_error(err.code as i32)) + } else { + Ok(()) + } } pub fn rename(old: &Path, new: &Path) -> io::Result<()> { |
