@@ -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 (
@@ -1217,8 +1221,24 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
1217
1221
1218
1222
pub fn unlink ( p : & Path ) -> io:: Result < ( ) > {
1219
1223
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
+ }
1222
1242
}
1223
1243
1224
1244
pub fn rename ( old : & Path , new : & Path ) -> io:: Result < ( ) > {
0 commit comments