about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libstd/fs.rs21
-rw-r--r--src/libstd/sys/windows/fs.rs8
2 files changed, 22 insertions, 7 deletions
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 91600b01298..b07733d3c80 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1374,14 +1374,17 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
 /// Note that if `from` and `to` both point to the same file, then the file
 /// will likely get truncated by this operation.
 ///
-/// On success, the total number of bytes copied is returned.
+/// On success, the total number of bytes copied is returned and it is equal to
+/// the length of the `to` file as reported by `metadata`.
 ///
 /// # Platform-specific behavior
 ///
 /// This function currently corresponds to the `open` function in Unix
 /// with `O_RDONLY` for `from` and `O_WRONLY`, `O_CREAT`, and `O_TRUNC` for `to`.
 /// `O_CLOEXEC` is set for returned file descriptors.
-/// On Windows, this function currently corresponds to `CopyFileEx`.
+/// On Windows, this function currently corresponds to `CopyFileEx`. Alternate
+/// NTFS streams are copied but only the size of the main stream is returned by
+/// this function.
 /// Note that, this [may change in the future][changes].
 ///
 /// [changes]: ../io/index.html#platform-specific-behavior
@@ -2589,7 +2592,7 @@ mod tests {
     fn copy_file_preserves_streams() {
         let tmp = tmpdir();
         check!(check!(File::create(tmp.join("in.txt:bunny"))).write("carrot".as_bytes()));
-        assert_eq!(check!(fs::copy(tmp.join("in.txt"), tmp.join("out.txt"))), 6);
+        assert_eq!(check!(fs::copy(tmp.join("in.txt"), tmp.join("out.txt"))), 0);
         assert_eq!(check!(tmp.join("out.txt").metadata()).len(), 0);
         let mut v = Vec::new();
         check!(check!(File::open(tmp.join("out.txt:bunny"))).read_to_end(&mut v));
@@ -2597,6 +2600,18 @@ mod tests {
     }
 
     #[test]
+    fn copy_file_returns_metadata_len() {
+        let tmp = tmpdir();
+        let in_path = tmp.join("in.txt");
+        let out_path = tmp.join("out.txt");
+        check!(check!(File::create(&in_path)).write(b"lettuce"));
+        #[cfg(windows)]
+        check!(check!(File::create(tmp.join("in.txt:bunny"))).write(b"carrot"));
+        let copied_len = check!(fs::copy(&in_path, &out_path));
+        assert_eq!(check!(out_path.metadata()).len(), copied_len);
+    }
+
+    #[test]
     fn symlinks_work() {
         let tmpdir = tmpdir();
         if !got_symlink_permission(&tmpdir) { return };
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index f2487c1b0bd..ae9535139d9 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -722,16 +722,16 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     unsafe extern "system" fn callback(
         _TotalFileSize: c::LARGE_INTEGER,
-        TotalBytesTransferred: c::LARGE_INTEGER,
+        _TotalBytesTransferred: c::LARGE_INTEGER,
         _StreamSize: c::LARGE_INTEGER,
-        _StreamBytesTransferred: c::LARGE_INTEGER,
-        _dwStreamNumber: c::DWORD,
+        StreamBytesTransferred: c::LARGE_INTEGER,
+        dwStreamNumber: c::DWORD,
         _dwCallbackReason: c::DWORD,
         _hSourceFile: c::HANDLE,
         _hDestinationFile: c::HANDLE,
         lpData: c::LPVOID,
     ) -> c::DWORD {
-        *(lpData as *mut i64) = TotalBytesTransferred;
+        if dwStreamNumber == 1 {*(lpData as *mut i64) = StreamBytesTransferred;}
         c::PROGRESS_CONTINUE
     }
     let pfrom = to_u16s(from)?;