@@ -1198,31 +1198,38 @@ impl Dir {
1198
1198
io:: const_error!( io:: ErrorKind :: InvalidFilename , "File name is too long" ) ;
1199
1199
let mut opts = OpenOptions :: new ( ) ;
1200
1200
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 ) ) ?;
1204
1207
let sym_buffer = c:: SYMBOLIC_LINK_REPARSE_BUFFER {
1205
1208
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 ,
1209
1212
Flags : if relative { c:: SYMLINK_FLAG_RELATIVE } else { 0 } ,
1210
1213
PathBuffer : 0 ,
1211
1214
} ;
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 ) ) ? ;
1221
1224
let buffer = unsafe { alloc ( layout) } . cast :: < c:: REPARSE_DATA_BUFFER > ( ) ;
1222
1225
unsafe {
1223
1226
buffer. write ( c:: REPARSE_DATA_BUFFER {
1224
1227
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 ) ) ?,
1226
1233
Reserved : 0 ,
1227
1234
rest : ( ) ,
1228
1235
} ) ;
@@ -1231,20 +1238,25 @@ impl Dir {
1231
1238
. cast :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( )
1232
1239
. write ( sym_buffer) ;
1233
1240
ptr:: copy_nonoverlapping (
1234
- utf16 . as_ptr ( ) ,
1241
+ original . as_ptr ( ) ,
1235
1242
buffer
1236
1243
. add ( offset_of ! ( c:: REPARSE_DATA_BUFFER , rest) )
1237
1244
. add ( offset_of ! ( c:: SYMBOLIC_LINK_REPARSE_BUFFER , PathBuffer ) )
1238
1245
. cast :: < u16 > ( ) ,
1239
- original. len ( ) * 2 ,
1246
+ original. len ( ) ,
1240
1247
) ;
1241
1248
} ;
1242
1249
let result = unsafe {
1243
1250
c:: DeviceIoControl (
1244
1251
linkfile. handle . as_raw_handle ( ) ,
1245
1252
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 ) ) ?,
1248
1260
ptr:: null_mut ( ) ,
1249
1261
0 ,
1250
1262
ptr:: null_mut ( ) ,
0 commit comments