@@ -968,7 +968,8 @@ fn run_path_with_utf16<T, P: AsRef<Path>>(
968
968
969
969
impl Dir {
970
970
pub fn new < P : AsRef < Path > > ( path : P ) -> io:: Result < Self > {
971
- let opts = OpenOptions :: new ( ) ;
971
+ let mut opts = OpenOptions :: new ( ) ;
972
+ opts. read ( true ) ;
972
973
run_path_with_wcstr ( path. as_ref ( ) , & |path| Self :: new_with_native ( path, & opts) )
973
974
}
974
975
@@ -982,31 +983,36 @@ impl Dir {
982
983
983
984
pub fn open < P : AsRef < Path > > ( & self , path : P ) -> io:: Result < File > {
984
985
let mut opts = OpenOptions :: new ( ) ;
985
- let path = path. as_ref ( ) . as_os_str ( ) . encode_wide ( ) . collect :: < Vec < _ > > ( ) ;
986
986
opts. read ( true ) ;
987
- self . open_native ( & path, & opts) . map ( |handle| File { handle } )
987
+ let path = path. as_ref ( ) ;
988
+ if path. is_absolute ( ) {
989
+ return File :: open ( path, & opts) ;
990
+ }
991
+ let path = path. as_os_str ( ) . encode_wide ( ) . collect :: < Vec < _ > > ( ) ;
992
+ self . open_native ( & path, & opts, false ) . map ( |handle| File { handle } )
988
993
}
989
994
990
995
pub fn open_with < P : AsRef < Path > > ( & self , path : P , opts : & OpenOptions ) -> io:: Result < File > {
991
996
let path = path. as_ref ( ) . as_os_str ( ) . encode_wide ( ) . collect :: < Vec < _ > > ( ) ;
992
- self . open_native ( & path, & opts) . map ( |handle| File { handle } )
997
+ self . open_native ( & path, & opts, false ) . map ( |handle| File { handle } )
993
998
}
994
999
995
1000
pub fn open_dir < P : AsRef < Path > > ( & self , path : P ) -> io:: Result < Self > {
996
1001
let mut opts = OpenOptions :: new ( ) ;
997
1002
let path = path. as_ref ( ) . as_os_str ( ) . encode_wide ( ) . collect :: < Vec < _ > > ( ) ;
998
1003
opts. read ( true ) ;
999
- self . open_native ( & path, & opts) . map ( |handle| Self { handle } )
1004
+ self . open_native ( & path, & opts, true ) . map ( |handle| Self { handle } )
1000
1005
}
1001
1006
1002
1007
pub fn open_dir_with < P : AsRef < Path > > ( & self , path : P , opts : & OpenOptions ) -> io:: Result < Self > {
1003
1008
let path = path. as_ref ( ) . as_os_str ( ) . encode_wide ( ) . collect :: < Vec < _ > > ( ) ;
1004
- self . open_native ( & path, & opts) . map ( |handle| Self { handle } )
1009
+ self . open_native ( & path, & opts, true ) . map ( |handle| Self { handle } )
1005
1010
}
1006
1011
1007
1012
pub fn create_dir < P : AsRef < Path > > ( & self , path : P ) -> io:: Result < ( ) > {
1008
1013
let mut opts = OpenOptions :: new ( ) ;
1009
1014
opts. write ( true ) ;
1015
+ opts. create_new ( true ) ;
1010
1016
run_path_with_utf16 ( path, & |path| self . create_dir_native ( path, & opts) . map ( |_| ( ) ) )
1011
1017
}
1012
1018
@@ -1024,7 +1030,7 @@ impl Dir {
1024
1030
to_dir : & Self ,
1025
1031
to : Q ,
1026
1032
) -> io:: Result < ( ) > {
1027
- run_path_with_wcstr ( to. as_ref ( ) , & |to| self . rename_native ( from. as_ref ( ) , to_dir, to) )
1033
+ run_path_with_wcstr ( to. as_ref ( ) , & |to| self . rename_native ( from. as_ref ( ) , to_dir, to, false ) )
1028
1034
}
1029
1035
1030
1036
pub fn symlink < P : AsRef < Path > , Q : AsRef < Path > > ( & self , original : P , link : Q ) -> io:: Result < ( ) > {
@@ -1058,16 +1064,16 @@ impl Dir {
1058
1064
}
1059
1065
}
1060
1066
1061
- fn open_native ( & self , path : & [ u16 ] , opts : & OpenOptions ) -> io:: Result < Handle > {
1067
+ fn open_native ( & self , path : & [ u16 ] , opts : & OpenOptions , dir : bool ) -> io:: Result < Handle > {
1062
1068
let name = c:: UNICODE_STRING {
1063
- Length : path. len ( ) as _ ,
1064
- MaximumLength : path. len ( ) as _ ,
1069
+ Length : ( path. len ( ) * 2 ) as _ ,
1070
+ MaximumLength : ( path. len ( ) * 2 ) as _ ,
1065
1071
Buffer : path. as_ptr ( ) as * mut _ ,
1066
1072
} ;
1067
1073
let object_attributes = c:: OBJECT_ATTRIBUTES {
1068
1074
Length : size_of :: < c:: OBJECT_ATTRIBUTES > ( ) as _ ,
1069
1075
RootDirectory : self . handle . as_raw_handle ( ) ,
1070
- ObjectName : & name,
1076
+ ObjectName : & raw const name,
1071
1077
Attributes : 0 ,
1072
1078
SecurityDescriptor : ptr:: null ( ) ,
1073
1079
SecurityQualityOfService : ptr:: null ( ) ,
@@ -1079,16 +1085,16 @@ impl Dir {
1079
1085
opts. get_disposition ( ) ?,
1080
1086
& object_attributes,
1081
1087
share,
1082
- false ,
1088
+ dir ,
1083
1089
)
1084
1090
}
1085
1091
. io_result ( )
1086
1092
}
1087
1093
1088
1094
fn create_dir_native ( & self , path : & [ u16 ] , opts : & OpenOptions ) -> io:: Result < Handle > {
1089
1095
let name = c:: UNICODE_STRING {
1090
- Length : path. len ( ) as _ ,
1091
- MaximumLength : path. len ( ) as _ ,
1096
+ Length : ( path. len ( ) * 2 ) as _ ,
1097
+ MaximumLength : ( path. len ( ) * 2 ) as _ ,
1092
1098
Buffer : path. as_ptr ( ) as * mut _ ,
1093
1099
} ;
1094
1100
let object_attributes = c:: OBJECT_ATTRIBUTES {
@@ -1114,9 +1120,8 @@ impl Dir {
1114
1120
1115
1121
fn remove_native ( & self , path : & [ u16 ] , dir : bool ) -> io:: Result < ( ) > {
1116
1122
let mut opts = OpenOptions :: new ( ) ;
1117
- opts. access_mode ( c:: GENERIC_WRITE ) ;
1118
- let handle =
1119
- if dir { self . create_dir_native ( path, & opts) } else { self . open_native ( path, & opts) } ?;
1123
+ opts. access_mode ( c:: DELETE ) ;
1124
+ let handle = self . open_native ( path, & opts, dir) ?;
1120
1125
let info = c:: FILE_DISPOSITION_INFO_EX { Flags : c:: FILE_DISPOSITION_FLAG_DELETE } ;
1121
1126
let result = unsafe {
1122
1127
c:: SetFileInformationByHandle (
@@ -1129,10 +1134,11 @@ impl Dir {
1129
1134
if result == 0 { Err ( api:: get_last_error ( ) ) . io_result ( ) } else { Ok ( ( ) ) }
1130
1135
}
1131
1136
1132
- fn rename_native ( & self , from : & Path , to_dir : & Self , to : & WCStr ) -> io:: Result < ( ) > {
1137
+ fn rename_native ( & self , from : & Path , to_dir : & Self , to : & WCStr , dir : bool ) -> io:: Result < ( ) > {
1133
1138
let mut opts = OpenOptions :: new ( ) ;
1134
- opts. access_mode ( c:: GENERIC_WRITE ) ;
1135
- let handle = run_path_with_utf16 ( from, & |u| self . open_native ( u, & opts) ) ?;
1139
+ opts. access_mode ( c:: DELETE ) ;
1140
+ opts. custom_flags ( c:: FILE_FLAG_OPEN_REPARSE_POINT | c:: FILE_FLAG_BACKUP_SEMANTICS ) ;
1141
+ let handle = run_path_with_utf16 ( from, & |u| self . open_native ( u, & opts, dir) ) ?;
1136
1142
// Calculate the layout of the `FILE_RENAME_INFO` we pass to `SetFileInformation`
1137
1143
// This is a dynamically sized struct so we need to get the position of the last field to calculate the actual size.
1138
1144
const too_long_err: io:: Error =
@@ -1144,9 +1150,9 @@ impl Dir {
1144
1150
. ok_or ( too_long_err) ?;
1145
1151
let layout = Layout :: from_size_align ( struct_size, align_of :: < c:: FILE_RENAME_INFO > ( ) )
1146
1152
. map_err ( |_| too_long_err) ?;
1153
+ let struct_size = u32:: try_from ( struct_size) . map_err ( |_| too_long_err) ?;
1147
1154
let to_byte_len_without_nul =
1148
1155
u32:: try_from ( ( to. count_bytes ( ) - 1 ) * 2 ) . map_err ( |_| too_long_err) ?;
1149
- let struct_size = u32:: try_from ( struct_size) . map_err ( |_| too_long_err) ?;
1150
1156
1151
1157
let file_rename_info;
1152
1158
// SAFETY: We allocate enough memory for a full FILE_RENAME_INFO struct and a filename.
@@ -1166,7 +1172,7 @@ impl Dir {
1166
1172
1167
1173
to. as_ptr ( ) . copy_to_nonoverlapping (
1168
1174
( & raw mut ( * file_rename_info) . FileName ) . cast :: < u16 > ( ) ,
1169
- run_path_with_wcstr ( from , & |s| Ok ( s . count_bytes ( ) ) ) . unwrap ( ) ,
1175
+ to . count_bytes ( ) ,
1170
1176
) ;
1171
1177
}
1172
1178
0 commit comments