@@ -1033,8 +1033,8 @@ impl Dir {
10331033 }
10341034
10351035 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 ( ) )
10381038 } )
10391039 }
10401040
@@ -1193,18 +1193,19 @@ impl Dir {
11931193 . io_result ( )
11941194 }
11951195
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 < ( ) > {
11971197 const TOO_LONG_ERR : io:: Error =
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+ let linkfile = File :: open ( 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 > > ( ) ;
12041205 let sym_buffer = c:: SYMBOLIC_LINK_REPARSE_BUFFER {
12051206 SubstituteNameOffset : 0 ,
1206- SubstituteNameLength : file_name_len,
1207- PrintNameOffset : file_name_len ,
1207+ SubstituteNameLength : file_name_len + 4 ,
1208+ PrintNameOffset : 4 ,
12081209 PrintNameLength : file_name_len,
12091210 Flags : if relative { c:: SYMLINK_FLAG_RELATIVE } else { 0 } ,
12101211 PathBuffer : 0 ,
@@ -1214,15 +1215,21 @@ impl Dir {
12141215 . extend ( Layout :: new :: < c:: SYMBOLIC_LINK_REPARSE_BUFFER > ( ) )
12151216 . or ( Err ( TOO_LONG_ERR ) ) ?
12161217 . 0 ;
1217- let layout = Layout :: array :: < u16 > ( original . len ( ) * 2 )
1218+ let layout = Layout :: array :: < u16 > ( link . len ( ) * 2 )
12181219 . and_then ( |arr| layout. extend ( arr) )
12191220 . or ( Err ( TOO_LONG_ERR ) ) ?
12201221 . 0 ;
12211222 let buffer = unsafe { alloc ( layout) } . cast :: < c:: REPARSE_DATA_BUFFER > ( ) ;
12221223 unsafe {
12231224 buffer. write ( c:: REPARSE_DATA_BUFFER {
12241225 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 ) ) ?,
12261233 Reserved : 0 ,
12271234 rest : ( ) ,
12281235 } ) ;
@@ -1236,15 +1243,20 @@ impl Dir {
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+ link . len ( ) * 2 ,
12401247 ) ;
12411248 } ;
12421249 let result = unsafe {
12431250 c:: DeviceIoControl (
12441251 linkfile. handle . as_raw_handle ( ) ,
12451252 c:: FSCTL_SET_REPARSE_POINT ,
12461253 & 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 ) ) ?,
12481260 ptr:: null_mut ( ) ,
12491261 0 ,
12501262 ptr:: null_mut ( ) ,
0 commit comments