@@ -296,6 +296,10 @@ impl OpenOptions {
296
296
impl File {
297
297
pub fn open ( path : & Path , opts : & OpenOptions ) -> io:: Result < File > {
298
298
let path = maybe_verbatim ( path) ?;
299
+ Self :: open_native ( & path, opts)
300
+ }
301
+
302
+ fn open_native ( path : & [ u16 ] , opts : & OpenOptions ) -> io:: Result < File > {
299
303
let creation = opts. get_creation_mode ( ) ?;
300
304
let handle = unsafe {
301
305
c:: CreateFileW (
@@ -1226,8 +1230,24 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
1226
1230
1227
1231
pub fn unlink ( p : & Path ) -> io:: Result < ( ) > {
1228
1232
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
+ }
1231
1251
}
1232
1252
1233
1253
pub fn rename ( old : & Path , new : & Path ) -> io:: Result < ( ) > {
0 commit comments