@@ -146,106 +146,9 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
146
146
fs:: symlink ( src, dest)
147
147
}
148
148
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
154
149
#[ cfg( windows) ]
155
150
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)
249
152
}
250
153
}
251
154
0 commit comments