@@ -296,6 +296,10 @@ impl OpenOptions {
296296impl 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,24 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
12261230
12271231pub 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 File :: open_native ( & p_u16s, & opts) . map ( |f| f. posix_delete ( ) ) . is_ok ( ) {
1243+ return Ok ( ( ) ) ;
1244+ }
1245+ }
1246+ // return the original error if any of the above fails.
1247+ Err ( io:: Error :: from_raw_os_error ( err. code as i32 ) )
1248+ } else {
1249+ Ok ( ( ) )
1250+ }
12311251}
12321252
12331253pub fn rename ( old : & Path , new : & Path ) -> io:: Result < ( ) > {
0 commit comments