about summary refs log tree commit diff
path: root/src/libstd/sys/windows
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-07-10 11:07:25 +0000
committerbors <bors@rust-lang.org>2015-07-10 11:07:25 +0000
commitd0d37075a54b68df99c46d42655a06c575eecd3f (patch)
tree03a0f0e30444469beca4f346f495b368ed37d2d2 /src/libstd/sys/windows
parent4695fbde2157d1a172cea5df99bd661c4aa1204a (diff)
parent1d202692ecfddb4b731993a5db4271c8698cbade (diff)
downloadrust-d0d37075a54b68df99c46d42655a06c575eecd3f.tar.gz
rust-d0d37075a54b68df99c46d42655a06c575eecd3f.zip
Auto merge of #26751 - retep998:copy-that-floppy, r=alexcrichton
Using the OS mechanism for copying files allows the OS to optimize the transfer using stuff such as [Offloaded Data Transfers (ODX)](https://msdn.microsoft.com/en-us/library/windows/desktop/hh848056%28v=vs.85%29.aspx).
Also preserves a lot more information, including NTFS [File Streams](https://msdn.microsoft.com/en-us/library/windows/desktop/aa364404%28v=vs.85%29.aspx), which the manual implementation threw away.
In addition, it is an atomic operation, unlike the manual implementation which has extra calls for copying over permissions.

r? @alexcrichton 
Diffstat (limited to 'src/libstd/sys/windows')
-rw-r--r--src/libstd/sys/windows/c.rs24
-rw-r--r--src/libstd/sys/windows/fs.rs25
2 files changed, 49 insertions, 0 deletions
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 2ddf685729b..16563be2cfb 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -66,6 +66,11 @@ pub const STD_ERROR_HANDLE: libc::DWORD = -12i32 as libc::DWORD;
 
 pub const HANDLE_FLAG_INHERIT: libc::DWORD = 0x00000001;
 
+pub const PROGRESS_CONTINUE: libc::DWORD = 0;
+pub const PROGRESS_CANCEL: libc::DWORD = 1;
+pub const PROGRESS_STOP: libc::DWORD = 2;
+pub const PROGRESS_QUIET: libc::DWORD = 3;
+
 #[repr(C)]
 #[cfg(target_arch = "x86")]
 pub struct WSADATA {
@@ -249,6 +254,19 @@ pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
 pub type PSRWLOCK = *mut SRWLOCK;
 pub type ULONG = c_ulong;
 pub type ULONG_PTR = c_ulong;
+pub type LPBOOL = *mut BOOL;
+
+pub type LPPROGRESS_ROUTINE = ::option::Option<unsafe extern "system" fn(
+    TotalFileSize: libc::LARGE_INTEGER,
+    TotalBytesTransferred: libc::LARGE_INTEGER,
+    StreamSize: libc::LARGE_INTEGER,
+    StreamBytesTransferred: libc::LARGE_INTEGER,
+    dwStreamNumber: DWORD,
+    dwCallbackReason: DWORD,
+    hSourceFile: HANDLE,
+    hDestinationFile: HANDLE,
+    lpData: LPVOID,
+) -> DWORD>;
 
 #[repr(C)]
 pub struct CONDITION_VARIABLE { pub ptr: LPVOID }
@@ -413,6 +431,12 @@ extern "system" {
     pub fn SetHandleInformation(hObject: libc::HANDLE,
                                 dwMask: libc::DWORD,
                                 dwFlags: libc::DWORD) -> libc::BOOL;
+    pub fn CopyFileExW(lpExistingFileName: libc::LPCWSTR,
+                       lpNewFileName: libc::LPCWSTR,
+                       lpProgressRoutine: LPPROGRESS_ROUTINE,
+                       lpData: libc::LPVOID,
+                       pbCancel: LPBOOL,
+                       dwCopyFlags: libc::DWORD) -> libc::BOOL;
 }
 
 // Functions that aren't available on Windows XP, but we still use them and just
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 36fabe72aa0..ae6b20de639 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -575,3 +575,28 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
         PathBuf::from(OsString::from_wide(buf))
     })
 }
+
+pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+    unsafe extern "system" fn callback(
+        _TotalFileSize: libc::LARGE_INTEGER,
+        TotalBytesTransferred: libc::LARGE_INTEGER,
+        _StreamSize: libc::LARGE_INTEGER,
+        _StreamBytesTransferred: libc::LARGE_INTEGER,
+        _dwStreamNumber: libc::DWORD,
+        _dwCallbackReason: libc::DWORD,
+        _hSourceFile: HANDLE,
+        _hDestinationFile: HANDLE,
+        lpData: libc::LPVOID,
+    ) -> libc::DWORD {
+        *(lpData as *mut i64) = TotalBytesTransferred;
+        c::PROGRESS_CONTINUE
+    }
+    let pfrom = to_utf16(from);
+    let pto = to_utf16(to);
+    let mut size = 0i64;
+    try!(cvt(unsafe {
+        c::CopyFileExW(pfrom.as_ptr(), pto.as_ptr(), Some(callback),
+                       &mut size as *mut _ as *mut _, ptr::null_mut(), 0)
+    }));
+    Ok(size as u64)
+}