@@ -1033,8 +1033,8 @@ impl Dir {
1033
1033
}
1034
1034
1035
1035
pub fn symlink < P : AsRef < Path > , Q : AsRef < Path > > ( & self , original : P , link : Q ) -> io:: Result < ( ) > {
1036
- run_path_with_utf16 ( original . as_ref ( ) , & |orig | {
1037
- self . symlink_native ( orig , link . as_ref ( ) , original . as_ref ( ) . is_relative ( ) )
1036
+ run_path_with_utf16 ( link . as_ref ( ) , & |l | {
1037
+ self . symlink_native ( original . as_ref ( ) , l . as_ref ( ) , link . as_ref ( ) . is_relative ( ) )
1038
1038
} )
1039
1039
}
1040
1040
@@ -1193,18 +1193,19 @@ impl Dir {
1193
1193
. io_result ( )
1194
1194
}
1195
1195
1196
- fn symlink_native ( & self , original : & [ u16 ] , link : & Path , relative : bool ) -> io:: Result < ( ) > {
1196
+ fn symlink_native ( & self , original : & Path , link : & [ u16 ] , relative : bool ) -> io:: Result < ( ) > {
1197
1197
const TOO_LONG_ERR : io:: Error =
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
+ let linkfile = self . open_with ( original, & opts) ?;
1202
+ let file_name_len = u16:: try_from ( link. len ( ) ) . or ( Err ( TOO_LONG_ERR ) ) ?;
1203
+ let utf16 =
1204
+ b"\\ ??\\ " . iter ( ) . map ( |& n| n as u16 ) . chain ( link. iter ( ) . copied ( ) ) . collect :: < Vec < u16 > > ( ) ;
1204
1205
let sym_buffer = c:: SYMBOLIC_LINK_REPARSE_BUFFER {
1205
1206
SubstituteNameOffset : 0 ,
1206
- SubstituteNameLength : file_name_len,
1207
- PrintNameOffset : file_name_len ,
1207
+ SubstituteNameLength : file_name_len + 4 ,
1208
+ PrintNameOffset : 4 ,
1208
1209
PrintNameLength : file_name_len,
1209
1210
Flags : if relative { c:: SYMLINK_FLAG_RELATIVE } else { 0 } ,
1210
1211
PathBuffer : 0 ,
@@ -1214,15 +1215,21 @@ impl Dir {
1214
1215
. extend ( Layout :: new :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( ) )
1215
1216
. or ( Err ( TOO_LONG_ERR ) ) ?
1216
1217
. 0 ;
1217
- let layout = Layout :: array :: < u16 > ( original . len ( ) * 2 )
1218
+ let layout = Layout :: array :: < u16 > ( link . len ( ) * 2 )
1218
1219
. and_then ( |arr| layout. extend ( arr) )
1219
1220
. or ( Err ( TOO_LONG_ERR ) ) ?
1220
1221
. 0 ;
1221
1222
let buffer = unsafe { alloc ( layout) } . cast :: < c:: REPARSE_DATA_BUFFER > ( ) ;
1222
1223
unsafe {
1223
1224
buffer. write ( c:: REPARSE_DATA_BUFFER {
1224
1225
ReparseTag : c:: IO_REPARSE_TAG_SYMLINK ,
1225
- ReparseDataLength : u16:: try_from ( size_of_val ( & sym_buffer) ) . or ( Err ( TOO_LONG_ERR ) ) ?,
1226
+ ReparseDataLength : u16:: try_from (
1227
+ size_of :: < c:: REPARSE_DATA_BUFFER > ( )
1228
+ + size_of :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( )
1229
+ + usize:: from ( file_name_len) * 2
1230
+ - offset_of ! ( c:: REPARSE_DATA_BUFFER , Reserved ) ,
1231
+ )
1232
+ . or ( Err ( TOO_LONG_ERR ) ) ?,
1226
1233
Reserved : 0 ,
1227
1234
rest : ( ) ,
1228
1235
} ) ;
@@ -1236,15 +1243,20 @@ impl Dir {
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
+ link . len ( ) * 2 ,
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
1253
& raw const buffer as * const c_void ,
1247
- u32:: try_from ( size_of_val ( & buffer) ) . or ( Err ( TOO_LONG_ERR ) ) ?,
1254
+ u32:: try_from (
1255
+ size_of :: < c:: REPARSE_DATA_BUFFER > ( )
1256
+ + size_of :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( )
1257
+ + usize:: from ( file_name_len) * 2 ,
1258
+ )
1259
+ . or ( Err ( TOO_LONG_ERR ) ) ?,
1248
1260
ptr:: null_mut ( ) ,
1249
1261
0 ,
1250
1262
ptr:: null_mut ( ) ,
0 commit comments