Module: wine Branch: oldstable Commit: a9ab13e0504b6ca28c3fd45f462a5c98cf66ee70 URL: http://source.winehq.org/git/wine.git/?a=commit;h=a9ab13e0504b6ca28c3fd45f46...
Author: Lauri Kenttä lauri.kentta@gmail.com Date: Mon Dec 5 18:53:23 2016 +0200
cmd: Fix copying when the dest is one of the sources.
"COPY a+b a" appends b to a. "COPY a+b b" skips b from the sources.
Signed-off-by: Lauri Kenttä lauri.kentta@gmail.com Signed-off-by: Alexandre Julliard julliard@winehq.org (cherry picked from commit 064508c0dd7bb331d581de77bebec62db2025e57) Signed-off-by: Michael Stefaniuc mstefani@winehq.org
---
programs/cmd/builtins.c | 44 ++++++++++++++++++++++++++++++-- programs/cmd/tests/test_builtins.cmd | 16 ++++++++++++ programs/cmd/tests/test_builtins.cmd.exp | 3 +++ 3 files changed, 61 insertions(+), 2 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c index cfa1642..dce5a78 100644 --- a/programs/cmd/builtins.c +++ b/programs/cmd/builtins.c @@ -460,6 +460,36 @@ static BOOL WCMD_AppendEOF(WCHAR *filename) }
/**************************************************************************** + * WCMD_IsSameFile + * + * Checks if the two paths reference to the same file + */ +static BOOL WCMD_IsSameFile(const WCHAR *name1, const WCHAR *name2) +{ + BOOL ret = FALSE; + HANDLE file1 = INVALID_HANDLE_VALUE, file2 = INVALID_HANDLE_VALUE; + BY_HANDLE_FILE_INFORMATION info1, info2; + + file1 = CreateFileW(name1, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + if (file1 == INVALID_HANDLE_VALUE || !GetFileInformationByHandle(file1, &info1)) + goto end; + + file2 = CreateFileW(name2, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + if (file2 == INVALID_HANDLE_VALUE || !GetFileInformationByHandle(file2, &info2)) + goto end; + + ret = info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber + && info1.nFileIndexHigh == info2.nFileIndexHigh + && info1.nFileIndexLow == info2.nFileIndexLow; +end: + if (file1 != INVALID_HANDLE_VALUE) + CloseHandle(file1); + if (file2 != INVALID_HANDLE_VALUE) + CloseHandle(file2); + return ret; +} + +/**************************************************************************** * WCMD_ManualCopy * * Copies from a file @@ -922,6 +952,7 @@ void WCMD_copy(WCHAR * args) { do { WCHAR outname[MAX_PATH]; BOOL overwrite; + BOOL appendtofirstfile = FALSE;
/* Skip . and .., and directories */ if (!srcisdevice && fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { @@ -946,8 +977,14 @@ void WCMD_copy(WCHAR * args) { WINE_TRACE("Flags: srcbinary(%d), dstbinary(%d), over(%d), prompt(%d)\n", thiscopy->binarycopy, destination->binarycopy, overwrite, prompt);
+ if (!writtenoneconcat) { + appendtofirstfile = anyconcats && WCMD_IsSameFile(srcpath, outname); + } + /* Prompt before overwriting */ - if (!overwrite) { + if (appendtofirstfile) { + overwrite = TRUE; + } else if (!overwrite) { DWORD attributes = GetFileAttributesW(outname); if (attributes != INVALID_FILE_ATTRIBUTES) { WCHAR* question; @@ -969,7 +1006,10 @@ void WCMD_copy(WCHAR * args) {
/* Do the copy as appropriate */ if (overwrite) { - if (anyconcats && writtenoneconcat) { + if (anyconcats && WCMD_IsSameFile(srcpath, outname)) { + /* Silently skip if the destination file is also a source file */ + status = TRUE; + } else if (anyconcats && writtenoneconcat) { if (thiscopy->binarycopy) { status = WCMD_ManualCopy(srcpath, outname, FALSE, TRUE); } else { diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd index 975a84b..e199c0b 100644 --- a/programs/cmd/tests/test_builtins.cmd +++ b/programs/cmd/tests/test_builtins.cmd @@ -2391,6 +2391,22 @@ rem Concat 2 files, default mode - (one EOF on the end 5+8+1) copy ..\file1+..\file2 file12_eof2 >nul 2>&1 call :CheckFileSize file12_eof2 14
+rem Test copying when destination is one of the sources. +rem Concat file1+file2+file3 into file1, should produce file1+file2+file3 = 24 +copy /y ..\file? .\ >nul 2>&1 +copy /y /b file1+file2+file3 file1 >nul 2>&1 +call :CheckFileSize file1 24 + +rem Concat file1+file2+file3 into file2, should produce file1+file3 = 16 +copy /y ..\file? .\ >nul 2>&1 +copy /y /b file1+file2+file3 file2 >nul 2>&1 +call :CheckFileSize file2 16 + +rem Concat file1+file2+file3 into file3, should produce file1+file2 = 13 +copy /y ..\file? .\ >nul 2>&1 +copy /y /b file1+file2+file3 file3 >nul 2>&1 +call :CheckFileSize file3 13 + rem -------------------------------------------------------------- rem Show ascii source copy stops at first EOF, binary does the lot rem -------------------------------------------------------------- diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp index d70aad3..17dbd19 100644 --- a/programs/cmd/tests/test_builtins.cmd.exp +++ b/programs/cmd/tests/test_builtins.cmd.exp @@ -1262,6 +1262,9 @@ Passed: file size check on file3_plus_eof [12]@or_broken@Skipping file size chec Passed: file size check on file12_plus_eof [14]@or_broken@Skipping file size check on NT4 Passed: file size check on file12_no_eof [13]@or_broken@Skipping file size check on NT4 Passed: file size check on file12_eof2 [14]@or_broken@Skipping file size check on NT4 +Passed: file size check on file1 [24]@or_broken@Skipping file size check on NT4 +Passed: file size check on file2 [16]@or_broken@Skipping file size check on NT4 +Passed: file size check on file3 [13]@or_broken@Skipping file size check on NT4 Passed: file size check on file1_binary_srccopy [6]@or_broken@Skipping file size check on NT4 Passed: file size check on file1_ascii_srccopy [5]@or_broken@Skipping file size check on NT4 Passed: file size check on file123_default_copy [25]@or_broken@Skipping file size check on NT4