diff options
Diffstat (limited to 'src/bootstrap/util.rs')
-rw-r--r-- | src/bootstrap/util.rs | 93 |
1 files changed, 1 insertions, 92 deletions
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 93e53d383..2e1adbf63 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -146,100 +146,9 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> { fs::symlink(src, dest) } - // Creating a directory junction on windows involves dealing with reparse - // points and the DeviceIoControl function, and this code is a skeleton of - // what can be found here: - // - // http://www.flexhex.com/docs/articles/hard-links.phtml #[cfg(windows)] fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> { - use std::ffi::OsStr; - use std::os::windows::ffi::OsStrExt; - use std::ptr; - - use winapi::shared::minwindef::{DWORD, WORD}; - use winapi::um::fileapi::{CreateFileW, OPEN_EXISTING}; - use winapi::um::handleapi::CloseHandle; - use winapi::um::ioapiset::DeviceIoControl; - use winapi::um::winbase::{FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT}; - use winapi::um::winioctl::FSCTL_SET_REPARSE_POINT; - use winapi::um::winnt::{ - FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_WRITE, - IO_REPARSE_TAG_MOUNT_POINT, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, WCHAR, - }; - - #[allow(non_snake_case)] - #[repr(C)] - struct REPARSE_MOUNTPOINT_DATA_BUFFER { - ReparseTag: DWORD, - ReparseDataLength: DWORD, - Reserved: WORD, - ReparseTargetLength: WORD, - ReparseTargetMaximumLength: WORD, - Reserved1: WORD, - ReparseTarget: WCHAR, - } - - fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> { - Ok(s.as_ref().encode_wide().chain(Some(0)).collect()) - } - - // We're using low-level APIs to create the junction, and these are more - // picky about paths. For example, forward slashes cannot be used as a - // path separator, so we should try to canonicalize the path first. - let target = fs::canonicalize(target)?; - - fs::create_dir(junction)?; - - let path = to_u16s(junction)?; - - unsafe { - let h = CreateFileW( - path.as_ptr(), - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - ptr::null_mut(), - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, - ptr::null_mut(), - ); - - #[repr(C, align(8))] - struct Align8<T>(T); - let mut data = Align8([0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]); - let db = data.0.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER; - let buf = core::ptr::addr_of_mut!((*db).ReparseTarget) as *mut u16; - let mut i = 0; - // FIXME: this conversion is very hacky - let v = br"\??\"; - let v = v.iter().map(|x| *x as u16); - for c in v.chain(target.as_os_str().encode_wide().skip(4)) { - *buf.offset(i) = c; - i += 1; - } - *buf.offset(i) = 0; - i += 1; - (*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; - (*db).ReparseTargetMaximumLength = (i * 2) as WORD; - (*db).ReparseTargetLength = ((i - 1) * 2) as WORD; - (*db).ReparseDataLength = (*db).ReparseTargetLength as DWORD + 12; - - let mut ret = 0; - let res = DeviceIoControl( - h as *mut _, - FSCTL_SET_REPARSE_POINT, - db.cast(), - (*db).ReparseDataLength + 8, - ptr::null_mut(), - 0, - &mut ret, - ptr::null_mut(), - ); - - let out = if res == 0 { Err(io::Error::last_os_error()) } else { Ok(()) }; - CloseHandle(h); - out - } + junction::create(&target, &junction) } } |