@@ -1198,31 +1198,38 @@ impl Dir {
11981198 io:: const_error!( io:: ErrorKind :: InvalidFilename , "File name is too long" ) ;
11991199 let mut opts = OpenOptions :: new ( ) ;
12001200 opts. write ( true ) ;
1201- let linkfile = File :: open ( link, & opts) ?;
1202- let utf16: Vec < u16 > = original. iter ( ) . chain ( original) . copied ( ) . collect ( ) ;
1203- let file_name_len = u16:: try_from ( original. len ( ) ) . or ( Err ( TOO_LONG_ERR ) ) ?;
1201+ opts. create ( true ) ;
1202+ opts. custom_flags ( c:: FILE_FLAG_OPEN_REPARSE_POINT | c:: FILE_FLAG_BACKUP_SEMANTICS ) ;
1203+ opts. attributes ( c:: FILE_ATTRIBUTE_REPARSE_POINT ) ;
1204+ let linkfile = self . open_with ( link, & opts) ?;
1205+ let original_name_byte_len =
1206+ u16:: try_from ( size_of :: < u16 > ( ) * original. len ( ) ) . or ( Err ( TOO_LONG_ERR ) ) ?;
12041207 let sym_buffer = c:: SYMBOLIC_LINK_REPARSE_BUFFER {
12051208 SubstituteNameOffset : 0 ,
1206- SubstituteNameLength : file_name_len ,
1207- PrintNameOffset : file_name_len ,
1208- PrintNameLength : file_name_len ,
1209+ SubstituteNameLength : original_name_byte_len ,
1210+ PrintNameOffset : 0 ,
1211+ PrintNameLength : original_name_byte_len ,
12091212 Flags : if relative { c:: SYMLINK_FLAG_RELATIVE } else { 0 } ,
12101213 PathBuffer : 0 ,
12111214 } ;
1212- let layout = Layout :: new :: < c :: REPARSE_DATA_BUFFER > ( ) ;
1213- let layout = layout
1214- . extend ( Layout :: new :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( ) )
1215- . or ( Err ( TOO_LONG_ERR ) ) ?
1216- . 0 ;
1217- let layout = Layout :: array :: < u16 > ( original . len ( ) * 2 )
1218- . and_then ( |arr| layout . extend ( arr ) )
1219- . or ( Err ( TOO_LONG_ERR ) ) ?
1220- . 0 ;
1215+ let layout = Layout :: from_size_align (
1216+ size_of :: < c :: REPARSE_DATA_BUFFER > ( )
1217+ + size_of :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( )
1218+ + size_of :: < u16 > ( ) * ( original . len ( ) - 1 ) ,
1219+ align_of :: < c :: REPARSE_DATA_BUFFER > ( )
1220+ . max ( align_of :: < c :: SYMBOLIC_LINK_REPARSE_BUFFER > ( ) )
1221+ . max ( align_of :: < u16 > ( ) ) ,
1222+ )
1223+ . or ( Err ( TOO_LONG_ERR ) ) ? ;
12211224 let buffer = unsafe { alloc ( layout) } . cast :: < c:: REPARSE_DATA_BUFFER > ( ) ;
12221225 unsafe {
12231226 buffer. write ( c:: REPARSE_DATA_BUFFER {
12241227 ReparseTag : c:: IO_REPARSE_TAG_SYMLINK ,
1225- ReparseDataLength : u16:: try_from ( size_of_val ( & sym_buffer) ) . or ( Err ( TOO_LONG_ERR ) ) ?,
1228+ ReparseDataLength : u16:: try_from (
1229+ size_of :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( )
1230+ + size_of :: < u16 > ( ) * ( original. len ( ) - 1 ) ,
1231+ )
1232+ . or ( Err ( TOO_LONG_ERR ) ) ?,
12261233 Reserved : 0 ,
12271234 rest : ( ) ,
12281235 } ) ;
@@ -1231,20 +1238,25 @@ impl Dir {
12311238 . cast :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( )
12321239 . write ( sym_buffer) ;
12331240 ptr:: copy_nonoverlapping (
1234- utf16 . as_ptr ( ) ,
1241+ original . as_ptr ( ) ,
12351242 buffer
12361243 . add ( offset_of ! ( c:: REPARSE_DATA_BUFFER , rest) )
12371244 . add ( offset_of ! ( c:: SYMBOLIC_LINK_REPARSE_BUFFER , PathBuffer ) )
12381245 . cast :: < u16 > ( ) ,
1239- original. len ( ) * 2 ,
1246+ original. len ( ) ,
12401247 ) ;
12411248 } ;
12421249 let result = unsafe {
12431250 c:: DeviceIoControl (
12441251 linkfile. handle . as_raw_handle ( ) ,
12451252 c:: FSCTL_SET_REPARSE_POINT ,
1246- & raw const buffer as * const c_void ,
1247- u32:: try_from ( size_of_val ( & buffer) ) . or ( Err ( TOO_LONG_ERR ) ) ?,
1253+ buffer as * mut c_void as * const c_void ,
1254+ u32:: try_from (
1255+ size_of :: < c:: REPARSE_DATA_BUFFER > ( )
1256+ + size_of :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( )
1257+ + size_of :: < u16 > ( ) * ( original. len ( ) - 1 ) ,
1258+ )
1259+ . or ( Err ( TOO_LONG_ERR ) ) ?,
12481260 ptr:: null_mut ( ) ,
12491261 0 ,
12501262 ptr:: null_mut ( ) ,
0 commit comments