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