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