@@ -1204,53 +1204,56 @@ impl Dir {
12041204 io:: const_error!( io:: ErrorKind :: InvalidFilename , "File name is too long" ) ;
12051205 let mut opts = OpenOptions :: new ( ) ;
12061206 opts. write ( true ) ;
1207- let linkfile = File :: open ( link, & opts) ?;
1208- let utf16: Vec < u16 > = original. iter ( ) . chain ( original) . copied ( ) . collect ( ) ;
1209- let file_name_len = u16:: try_from ( original. len ( ) ) . or ( Err ( TOO_LONG_ERR ) ) ?;
1210- let sym_buffer = c:: SYMBOLIC_LINK_REPARSE_BUFFER {
1211- SubstituteNameOffset : 0 ,
1212- SubstituteNameLength : file_name_len,
1213- PrintNameOffset : file_name_len,
1214- PrintNameLength : file_name_len,
1215- Flags : if relative { c:: SYMLINK_FLAG_RELATIVE } else { 0 } ,
1216- PathBuffer : 0 ,
1217- } ;
1218- let layout = Layout :: new :: < c:: REPARSE_DATA_BUFFER > ( ) ;
1219- let layout = layout
1220- . extend ( Layout :: new :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( ) )
1221- . or ( Err ( TOO_LONG_ERR ) ) ?
1222- . 0 ;
1223- let layout = Layout :: array :: < u16 > ( original. len ( ) * 2 )
1224- . and_then ( |arr| layout. extend ( arr) )
1225- . or ( Err ( TOO_LONG_ERR ) ) ?
1226- . 0 ;
1207+ opts. create ( true ) ;
1208+ opts. custom_flags ( c:: FILE_FLAG_OPEN_REPARSE_POINT | c:: FILE_FLAG_BACKUP_SEMANTICS ) ;
1209+ opts. attributes ( c:: FILE_ATTRIBUTE_REPARSE_POINT ) ;
1210+ let linkfile = self . open_with ( link, & opts) ?;
1211+ let original_name_byte_len =
1212+ u16:: try_from ( size_of :: < u16 > ( ) * original. len ( ) ) . or ( Err ( TOO_LONG_ERR ) ) ?;
1213+ let layout = Layout :: from_size_align (
1214+ size_of :: < c:: REPARSE_DATA_BUFFER > ( )
1215+ + size_of :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( )
1216+ + size_of :: < u16 > ( ) * ( original. len ( ) - 1 ) ,
1217+ align_of :: < c:: REPARSE_DATA_BUFFER > ( )
1218+ . max ( align_of :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( ) )
1219+ . max ( align_of :: < u16 > ( ) ) ,
1220+ )
1221+ . or ( Err ( TOO_LONG_ERR ) ) ?;
12271222 let buffer = unsafe { alloc ( layout) } . cast :: < c:: REPARSE_DATA_BUFFER > ( ) ;
1223+ if buffer. is_null ( ) {
1224+ return Err ( io:: ErrorKind :: OutOfMemory . into ( ) ) ;
1225+ }
12281226 unsafe {
1229- buffer. write ( c:: REPARSE_DATA_BUFFER {
1230- ReparseTag : c:: IO_REPARSE_TAG_SYMLINK ,
1231- ReparseDataLength : u16:: try_from ( size_of_val ( & sym_buffer) ) . or ( Err ( TOO_LONG_ERR ) ) ?,
1232- Reserved : 0 ,
1233- rest : ( ) ,
1234- } ) ;
1235- buffer
1236- . add ( offset_of ! ( c:: REPARSE_DATA_BUFFER , rest) )
1237- . cast :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( )
1238- . write ( sym_buffer) ;
1239- ptr:: copy_nonoverlapping (
1240- utf16. as_ptr ( ) ,
1241- buffer
1242- . add ( offset_of ! ( c:: REPARSE_DATA_BUFFER , rest) )
1243- . add ( offset_of ! ( c:: SYMBOLIC_LINK_REPARSE_BUFFER , PathBuffer ) )
1244- . cast :: < u16 > ( ) ,
1245- original. len ( ) * 2 ,
1227+ ( & raw mut ( * buffer) . ReparseTag ) . write ( c:: IO_REPARSE_TAG_SYMLINK ) ;
1228+ ( & raw mut ( * buffer) . ReparseDataLength ) . write (
1229+ u16:: try_from (
1230+ size_of :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( )
1231+ + size_of :: < u16 > ( ) * ( original. len ( ) - 1 ) ,
1232+ )
1233+ . or ( Err ( TOO_LONG_ERR ) ) ?,
12461234 ) ;
1235+ ( & raw mut ( * buffer) . Reserved ) . write ( 0 ) ;
1236+ let rest = ( & raw mut ( * buffer) . rest ) . cast :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( ) ;
1237+
1238+ ( & raw mut ( * rest) . SubstituteNameOffset ) . write ( 0 ) ;
1239+ ( & raw mut ( * rest) . SubstituteNameLength ) . write ( original_name_byte_len) ;
1240+ ( & raw mut ( * rest) . PrintNameOffset ) . write ( 0 ) ;
1241+ ( & raw mut ( * rest) . PrintNameLength ) . write ( original_name_byte_len) ;
1242+ ( & raw mut ( * rest) . Flags ) . write ( if relative { c:: SYMLINK_FLAG_RELATIVE } else { 0 } ) ;
1243+
1244+ original. as_ptr ( ) . copy_to_nonoverlapping ( & raw mut ( * rest) . PathBuffer , original. len ( ) ) ;
12471245 } ;
12481246 let result = unsafe {
12491247 c:: DeviceIoControl (
12501248 linkfile. handle . as_raw_handle ( ) ,
12511249 c:: FSCTL_SET_REPARSE_POINT ,
1252- & raw const buffer as * const c_void ,
1253- u32:: try_from ( size_of_val ( & buffer) ) . or ( Err ( TOO_LONG_ERR ) ) ?,
1250+ buffer as * mut c_void as * const c_void ,
1251+ u32:: try_from (
1252+ size_of :: < c:: REPARSE_DATA_BUFFER > ( )
1253+ + size_of :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( )
1254+ + size_of :: < u16 > ( ) * ( original. len ( ) - 1 ) ,
1255+ )
1256+ . or ( Err ( TOO_LONG_ERR ) ) ?,
12541257 ptr:: null_mut ( ) ,
12551258 0 ,
12561259 ptr:: null_mut ( ) ,
0 commit comments