@@ -968,7 +968,8 @@ fn run_path_with_utf16<T, P: AsRef<Path>>(
968968
969969impl Dir {
970970 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 ) ;
972973 run_path_with_wcstr ( path. as_ref ( ) , & |path| Self :: new_with_native ( path, & opts) )
973974 }
974975
@@ -982,31 +983,36 @@ impl Dir {
982983
983984 pub fn open < P : AsRef < Path > > ( & self , path : P ) -> io:: Result < File > {
984985 let mut opts = OpenOptions :: new ( ) ;
985- let path = path. as_ref ( ) . as_os_str ( ) . encode_wide ( ) . collect :: < Vec < _ > > ( ) ;
986986 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 } )
988993 }
989994
990995 pub fn open_with < P : AsRef < Path > > ( & self , path : P , opts : & OpenOptions ) -> io:: Result < File > {
991996 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 } )
993998 }
994999
9951000 pub fn open_dir < P : AsRef < Path > > ( & self , path : P ) -> io:: Result < Self > {
9961001 let mut opts = OpenOptions :: new ( ) ;
9971002 let path = path. as_ref ( ) . as_os_str ( ) . encode_wide ( ) . collect :: < Vec < _ > > ( ) ;
9981003 opts. read ( true ) ;
999- self . open_native ( & path, & opts) . map ( |handle| Self { handle } )
1004+ self . open_native ( & path, & opts, true ) . map ( |handle| Self { handle } )
10001005 }
10011006
10021007 pub fn open_dir_with < P : AsRef < Path > > ( & self , path : P , opts : & OpenOptions ) -> io:: Result < Self > {
10031008 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 } )
10051010 }
10061011
10071012 pub fn create_dir < P : AsRef < Path > > ( & self , path : P ) -> io:: Result < ( ) > {
10081013 let mut opts = OpenOptions :: new ( ) ;
10091014 opts. write ( true ) ;
1015+ opts. create_new ( true ) ;
10101016 run_path_with_utf16 ( path, & |path| self . create_dir_native ( path, & opts) . map ( |_| ( ) ) )
10111017 }
10121018
@@ -1024,7 +1030,7 @@ impl Dir {
10241030 to_dir : & Self ,
10251031 to : Q ,
10261032 ) -> 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 ) )
10281034 }
10291035
10301036 pub fn symlink < P : AsRef < Path > , Q : AsRef < Path > > ( & self , original : P , link : Q ) -> io:: Result < ( ) > {
@@ -1058,16 +1064,16 @@ impl Dir {
10581064 }
10591065 }
10601066
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 > {
10621068 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 _ ,
10651071 Buffer : path. as_ptr ( ) as * mut _ ,
10661072 } ;
10671073 let object_attributes = c:: OBJECT_ATTRIBUTES {
10681074 Length : size_of :: < c:: OBJECT_ATTRIBUTES > ( ) as _ ,
10691075 RootDirectory : self . handle . as_raw_handle ( ) ,
1070- ObjectName : & name,
1076+ ObjectName : & raw const name,
10711077 Attributes : 0 ,
10721078 SecurityDescriptor : ptr:: null ( ) ,
10731079 SecurityQualityOfService : ptr:: null ( ) ,
@@ -1079,16 +1085,16 @@ impl Dir {
10791085 opts. get_disposition ( ) ?,
10801086 & object_attributes,
10811087 share,
1082- false ,
1088+ dir ,
10831089 )
10841090 }
10851091 . io_result ( )
10861092 }
10871093
10881094 fn create_dir_native ( & self , path : & [ u16 ] , opts : & OpenOptions ) -> io:: Result < Handle > {
10891095 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 _ ,
10921098 Buffer : path. as_ptr ( ) as * mut _ ,
10931099 } ;
10941100 let object_attributes = c:: OBJECT_ATTRIBUTES {
@@ -1114,9 +1120,8 @@ impl Dir {
11141120
11151121 fn remove_native ( & self , path : & [ u16 ] , dir : bool ) -> io:: Result < ( ) > {
11161122 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) ?;
11201125 let info = c:: FILE_DISPOSITION_INFO_EX { Flags : c:: FILE_DISPOSITION_FLAG_DELETE } ;
11211126 let result = unsafe {
11221127 c:: SetFileInformationByHandle (
@@ -1129,10 +1134,11 @@ impl Dir {
11291134 if result == 0 { Err ( api:: get_last_error ( ) ) . io_result ( ) } else { Ok ( ( ) ) }
11301135 }
11311136
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 < ( ) > {
11331138 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) ) ?;
11361142 // Calculate the layout of the `FILE_RENAME_INFO` we pass to `SetFileInformation`
11371143 // This is a dynamically sized struct so we need to get the position of the last field to calculate the actual size.
11381144 const too_long_err: io:: Error =
@@ -1144,9 +1150,9 @@ impl Dir {
11441150 . ok_or ( too_long_err) ?;
11451151 let layout = Layout :: from_size_align ( struct_size, align_of :: < c:: FILE_RENAME_INFO > ( ) )
11461152 . map_err ( |_| too_long_err) ?;
1153+ let struct_size = u32:: try_from ( struct_size) . map_err ( |_| too_long_err) ?;
11471154 let to_byte_len_without_nul =
11481155 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) ?;
11501156
11511157 let file_rename_info;
11521158 // SAFETY: We allocate enough memory for a full FILE_RENAME_INFO struct and a filename.
@@ -1166,7 +1172,7 @@ impl Dir {
11661172
11671173 to. as_ptr ( ) . copy_to_nonoverlapping (
11681174 ( & raw mut ( * file_rename_info) . FileName ) . cast :: < u16 > ( ) ,
1169- run_path_with_wcstr ( from , & |s| Ok ( s . count_bytes ( ) ) ) . unwrap ( ) ,
1175+ to . count_bytes ( ) ,
11701176 ) ;
11711177 }
11721178
0 commit comments