summaryrefslogtreecommitdiffstats
path: root/src/bootstrap/util.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap/util.rs')
-rw-r--r--src/bootstrap/util.rs93
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)
}
}