@@ -146,106 +146,9 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
146146 fs:: symlink ( src, dest)
147147 }
148148
149- // Creating a directory junction on windows involves dealing with reparse
150- // points and the DeviceIoControl function, and this code is a skeleton of
151- // what can be found here:
152- //
153- // http://www.flexhex.com/docs/articles/hard-links.phtml
154149 #[ cfg( windows) ]
155150 fn symlink_dir_inner ( target : & Path , junction : & Path ) -> io:: Result < ( ) > {
156- use std:: ffi:: OsStr ;
157- use std:: os:: windows:: ffi:: OsStrExt ;
158-
159- use windows:: {
160- core:: PCWSTR ,
161- Win32 :: Foundation :: { CloseHandle , HANDLE } ,
162- Win32 :: Storage :: FileSystem :: {
163- CreateFileW , FILE_ACCESS_FLAGS , FILE_FLAG_BACKUP_SEMANTICS ,
164- FILE_FLAG_OPEN_REPARSE_POINT , FILE_SHARE_DELETE , FILE_SHARE_READ , FILE_SHARE_WRITE ,
165- MAXIMUM_REPARSE_DATA_BUFFER_SIZE , OPEN_EXISTING ,
166- } ,
167- Win32 :: System :: Ioctl :: FSCTL_SET_REPARSE_POINT ,
168- Win32 :: System :: SystemServices :: { GENERIC_WRITE , IO_REPARSE_TAG_MOUNT_POINT } ,
169- Win32 :: System :: IO :: DeviceIoControl ,
170- } ;
171-
172- #[ allow( non_snake_case) ]
173- #[ repr( C ) ]
174- struct REPARSE_MOUNTPOINT_DATA_BUFFER {
175- ReparseTag : u32 ,
176- ReparseDataLength : u32 ,
177- Reserved : u16 ,
178- ReparseTargetLength : u16 ,
179- ReparseTargetMaximumLength : u16 ,
180- Reserved1 : u16 ,
181- ReparseTarget : u16 ,
182- }
183-
184- fn to_u16s < S : AsRef < OsStr > > ( s : S ) -> io:: Result < Vec < u16 > > {
185- Ok ( s. as_ref ( ) . encode_wide ( ) . chain ( Some ( 0 ) ) . collect ( ) )
186- }
187-
188- // We're using low-level APIs to create the junction, and these are more
189- // picky about paths. For example, forward slashes cannot be used as a
190- // path separator, so we should try to canonicalize the path first.
191- let target = fs:: canonicalize ( target) ?;
192-
193- fs:: create_dir ( junction) ?;
194-
195- let path = to_u16s ( junction) ?;
196-
197- let h = unsafe {
198- CreateFileW (
199- PCWSTR ( path. as_ptr ( ) ) ,
200- FILE_ACCESS_FLAGS ( GENERIC_WRITE ) ,
201- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
202- None ,
203- OPEN_EXISTING ,
204- FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS ,
205- HANDLE :: default ( ) ,
206- )
207- }
208- . map_err ( |_| io:: Error :: last_os_error ( ) ) ?;
209-
210- unsafe {
211- #[ repr( C , align( 8 ) ) ]
212- struct Align8 < T > ( T ) ;
213- let mut data = Align8 ( [ 0u8 ; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize ] ) ;
214- let db = data. 0 . as_mut_ptr ( ) as * mut REPARSE_MOUNTPOINT_DATA_BUFFER ;
215- let buf = core:: ptr:: addr_of_mut!( ( * db) . ReparseTarget ) as * mut u16 ;
216- let mut i = 0 ;
217- // FIXME: this conversion is very hacky
218- let v = br"\??\" ;
219- let v = v. iter ( ) . map ( |x| * x as u16 ) ;
220- for c in v. chain ( target. as_os_str ( ) . encode_wide ( ) . skip ( 4 ) ) {
221- * buf. offset ( i) = c;
222- i += 1 ;
223- }
224- * buf. offset ( i) = 0 ;
225- i += 1 ;
226-
227- ( * db) . ReparseTag = IO_REPARSE_TAG_MOUNT_POINT ;
228- ( * db) . ReparseTargetMaximumLength = ( i * 2 ) as u16 ;
229- ( * db) . ReparseTargetLength = ( ( i - 1 ) * 2 ) as u16 ;
230- ( * db) . ReparseDataLength = ( ( * db) . ReparseTargetLength + 12 ) as u32 ;
231-
232- let mut ret = 0u32 ;
233- DeviceIoControl (
234- h,
235- FSCTL_SET_REPARSE_POINT ,
236- Some ( db. cast ( ) ) ,
237- ( * db) . ReparseDataLength + 8 ,
238- None ,
239- 0 ,
240- Some ( & mut ret) ,
241- None ,
242- )
243- . ok ( )
244- . map_err ( |_| io:: Error :: last_os_error ( ) ) ?;
245- }
246-
247- unsafe { CloseHandle ( h) } ;
248- Ok ( ( ) )
151+ junction:: create ( & target, & junction)
249152 }
250153}
251154
0 commit comments