@@ -973,7 +973,8 @@ fn run_path_with_utf16<T, P: AsRef<Path>>(
973973
974974impl Dir {
975975 pub fn new < P : AsRef < Path > > ( path : P ) -> io:: Result < Self > {
976- let opts = OpenOptions :: new ( ) ;
976+ let mut opts = OpenOptions :: new ( ) ;
977+ opts. read ( true ) ;
977978 run_path_with_wcstr ( path. as_ref ( ) , & |path| Self :: new_with_native ( path, & opts) )
978979 }
979980
@@ -987,31 +988,36 @@ impl Dir {
987988
988989 pub fn open < P : AsRef < Path > > ( & self , path : P ) -> io:: Result < File > {
989990 let mut opts = OpenOptions :: new ( ) ;
990- let path = path. as_ref ( ) . as_os_str ( ) . encode_wide ( ) . collect :: < Vec < _ > > ( ) ;
991991 opts. read ( true ) ;
992- self . open_native ( & path, & opts) . map ( |handle| File { handle } )
992+ let path = path. as_ref ( ) ;
993+ if path. is_absolute ( ) {
994+ return File :: open ( path, & opts) ;
995+ }
996+ let path = path. as_os_str ( ) . encode_wide ( ) . collect :: < Vec < _ > > ( ) ;
997+ self . open_native ( & path, & opts, false ) . map ( |handle| File { handle } )
993998 }
994999
9951000 pub fn open_with < P : AsRef < Path > > ( & self , path : P , opts : & OpenOptions ) -> io:: Result < File > {
9961001 let path = path. as_ref ( ) . as_os_str ( ) . encode_wide ( ) . collect :: < Vec < _ > > ( ) ;
997- self . open_native ( & path, & opts) . map ( |handle| File { handle } )
1002+ self . open_native ( & path, & opts, false ) . map ( |handle| File { handle } )
9981003 }
9991004
10001005 pub fn open_dir < P : AsRef < Path > > ( & self , path : P ) -> io:: Result < Self > {
10011006 let mut opts = OpenOptions :: new ( ) ;
10021007 let path = path. as_ref ( ) . as_os_str ( ) . encode_wide ( ) . collect :: < Vec < _ > > ( ) ;
10031008 opts. read ( true ) ;
1004- self . open_native ( & path, & opts) . map ( |handle| Self { handle } )
1009+ self . open_native ( & path, & opts, true ) . map ( |handle| Self { handle } )
10051010 }
10061011
10071012 pub fn open_dir_with < P : AsRef < Path > > ( & self , path : P , opts : & OpenOptions ) -> io:: Result < Self > {
10081013 let path = path. as_ref ( ) . as_os_str ( ) . encode_wide ( ) . collect :: < Vec < _ > > ( ) ;
1009- self . open_native ( & path, & opts) . map ( |handle| Self { handle } )
1014+ self . open_native ( & path, & opts, true ) . map ( |handle| Self { handle } )
10101015 }
10111016
10121017 pub fn create_dir < P : AsRef < Path > > ( & self , path : P ) -> io:: Result < ( ) > {
10131018 let mut opts = OpenOptions :: new ( ) ;
10141019 opts. write ( true ) ;
1020+ opts. create_new ( true ) ;
10151021 run_path_with_utf16 ( path, & |path| self . create_dir_native ( path, & opts) . map ( |_| ( ) ) )
10161022 }
10171023
@@ -1029,7 +1035,7 @@ impl Dir {
10291035 to_dir : & Self ,
10301036 to : Q ,
10311037 ) -> io:: Result < ( ) > {
1032- run_path_with_wcstr ( to. as_ref ( ) , & |to| self . rename_native ( from. as_ref ( ) , to_dir, to) )
1038+ run_path_with_wcstr ( to. as_ref ( ) , & |to| self . rename_native ( from. as_ref ( ) , to_dir, to, false ) )
10331039 }
10341040
10351041 pub fn symlink < P : AsRef < Path > , Q : AsRef < Path > > ( & self , original : P , link : Q ) -> io:: Result < ( ) > {
@@ -1063,16 +1069,16 @@ impl Dir {
10631069 }
10641070 }
10651071
1066- fn open_native ( & self , path : & [ u16 ] , opts : & OpenOptions ) -> io:: Result < Handle > {
1072+ fn open_native ( & self , path : & [ u16 ] , opts : & OpenOptions , dir : bool ) -> io:: Result < Handle > {
10671073 let name = c:: UNICODE_STRING {
1068- Length : path. len ( ) as _ ,
1069- MaximumLength : path. len ( ) as _ ,
1074+ Length : ( path. len ( ) * 2 ) as _ ,
1075+ MaximumLength : ( path. len ( ) * 2 ) as _ ,
10701076 Buffer : path. as_ptr ( ) as * mut _ ,
10711077 } ;
10721078 let object_attributes = c:: OBJECT_ATTRIBUTES {
10731079 Length : size_of :: < c:: OBJECT_ATTRIBUTES > ( ) as _ ,
10741080 RootDirectory : self . handle . as_raw_handle ( ) ,
1075- ObjectName : & name,
1081+ ObjectName : & raw const name,
10761082 Attributes : 0 ,
10771083 SecurityDescriptor : ptr:: null ( ) ,
10781084 SecurityQualityOfService : ptr:: null ( ) ,
@@ -1084,16 +1090,16 @@ impl Dir {
10841090 opts. get_disposition ( ) ?,
10851091 & object_attributes,
10861092 share,
1087- false ,
1093+ dir ,
10881094 )
10891095 }
10901096 . io_result ( )
10911097 }
10921098
10931099 fn create_dir_native ( & self , path : & [ u16 ] , opts : & OpenOptions ) -> io:: Result < Handle > {
10941100 let name = c:: UNICODE_STRING {
1095- Length : path. len ( ) as _ ,
1096- MaximumLength : path. len ( ) as _ ,
1101+ Length : ( path. len ( ) * 2 ) as _ ,
1102+ MaximumLength : ( path. len ( ) * 2 ) as _ ,
10971103 Buffer : path. as_ptr ( ) as * mut _ ,
10981104 } ;
10991105 let object_attributes = c:: OBJECT_ATTRIBUTES {
@@ -1119,9 +1125,8 @@ impl Dir {
11191125
11201126 fn remove_native ( & self , path : & [ u16 ] , dir : bool ) -> io:: Result < ( ) > {
11211127 let mut opts = OpenOptions :: new ( ) ;
1122- opts. access_mode ( c:: GENERIC_WRITE ) ;
1123- let handle =
1124- if dir { self . create_dir_native ( path, & opts) } else { self . open_native ( path, & opts) } ?;
1128+ opts. access_mode ( c:: DELETE ) ;
1129+ let handle = self . open_native ( path, & opts, dir) ?;
11251130 let info = c:: FILE_DISPOSITION_INFO_EX { Flags : c:: FILE_DISPOSITION_FLAG_DELETE } ;
11261131 let result = unsafe {
11271132 c:: SetFileInformationByHandle (
@@ -1134,10 +1139,11 @@ impl Dir {
11341139 if result == 0 { Err ( api:: get_last_error ( ) ) . io_result ( ) } else { Ok ( ( ) ) }
11351140 }
11361141
1137- fn rename_native ( & self , from : & Path , to_dir : & Self , to : & WCStr ) -> io:: Result < ( ) > {
1142+ fn rename_native ( & self , from : & Path , to_dir : & Self , to : & WCStr , dir : bool ) -> io:: Result < ( ) > {
11381143 let mut opts = OpenOptions :: new ( ) ;
1139- opts. access_mode ( c:: GENERIC_WRITE ) ;
1140- let handle = run_path_with_utf16 ( from, & |u| self . open_native ( u, & opts) ) ?;
1144+ opts. access_mode ( c:: DELETE ) ;
1145+ opts. custom_flags ( c:: FILE_FLAG_OPEN_REPARSE_POINT | c:: FILE_FLAG_BACKUP_SEMANTICS ) ;
1146+ let handle = run_path_with_utf16 ( from, & |u| self . open_native ( u, & opts, dir) ) ?;
11411147 // Calculate the layout of the `FILE_RENAME_INFO` we pass to `SetFileInformation`
11421148 // This is a dynamically sized struct so we need to get the position of the last field to calculate the actual size.
11431149 const too_long_err: io:: Error =
@@ -1149,9 +1155,9 @@ impl Dir {
11491155 . ok_or ( too_long_err) ?;
11501156 let layout = Layout :: from_size_align ( struct_size, align_of :: < c:: FILE_RENAME_INFO > ( ) )
11511157 . map_err ( |_| too_long_err) ?;
1158+ let struct_size = u32:: try_from ( struct_size) . map_err ( |_| too_long_err) ?;
11521159 let to_byte_len_without_nul =
11531160 u32:: try_from ( ( to. count_bytes ( ) - 1 ) * 2 ) . map_err ( |_| too_long_err) ?;
1154- let struct_size = u32:: try_from ( struct_size) . map_err ( |_| too_long_err) ?;
11551161
11561162 let file_rename_info;
11571163 // SAFETY: We allocate enough memory for a full FILE_RENAME_INFO struct and a filename.
@@ -1171,7 +1177,7 @@ impl Dir {
11711177
11721178 to. as_ptr ( ) . copy_to_nonoverlapping (
11731179 ( & raw mut ( * file_rename_info) . FileName ) . cast :: < u16 > ( ) ,
1174- run_path_with_wcstr ( from , & |s| Ok ( s . count_bytes ( ) ) ) . unwrap ( ) ,
1180+ to . count_bytes ( ) ,
11751181 ) ;
11761182 }
11771183
0 commit comments