@@ -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 (
@@ -1217,8 +1221,24 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
12171221
12181222pub 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
12241244pub fn rename ( old : & Path , new : & Path ) -> io:: Result < ( ) > {
0 commit comments