[PATCH 7/7] [cmd] Add full support for copy concatenation and ascii/binary
Ann and Jason Edmeades
jason at edmeades.me.uk
Fri Oct 12 04:53:13 CDT 2012
This patch adds full support for concatenation, whether in ascii
or binary modes. Effectively it adds copy a+b filename, or copy
a* filename support, and handles the EOF oddities that such
syntax brings in by honouring the /a and /b options.
[Should fix bugs 26943 and 27899]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-patches/attachments/20121012/eb71abe9/attachment-0001.html>
-------------- next part --------------
From 53c30bad90f406788c0c49ac92077052711f1d6f Mon Sep 17 00:00:00 2001
From: Jason Edmeades <jason at edmeades.me.uk>
Date: Fri, 12 Oct 2012 10:23:24 +0100
Subject: [PATCH 7/7] [cmd] Add full support for copy concatenation and
ascii/binary
This patch adds full support for concatenation, whether in ascii
or binary modes. Effectively it adds copy a+b filename, or copy
a* filename support, and handles the EOF oddities that such
syntax brings in by honouring the /a and /b options.
[Should fix bugs 26943 and 27899]
---
programs/cmd/builtins.c | 101 +++++++++++++++++++++++++-----
programs/cmd/tests/test_builtins.cmd | 4 ++
programs/cmd/tests/test_builtins.cmd.exp | 29 ++++-----
3 files changed, 106 insertions(+), 28 deletions(-)
diff --git a/programs/cmd/builtins.c b/programs/cmd/builtins.c
index 4e452b8..a81fec4 100644
--- a/programs/cmd/builtins.c
+++ b/programs/cmd/builtins.c
@@ -401,6 +401,76 @@ BOOL WCMD_AppendEOF(WCHAR *filename)
}
/****************************************************************************
+ * WCMD_ManualCopy
+ *
+ * Copies from a file
+ * optionally reading only until EOF (ascii copy)
+ * optionally appending onto an existing file (append)
+ * Returns TRUE on success
+ */
+BOOL WCMD_ManualCopy(WCHAR *srcname, WCHAR *dstname, BOOL ascii, BOOL append)
+{
+ HANDLE in,out;
+ BOOL ok;
+ DWORD bytesread, byteswritten;
+
+ WINE_TRACE("ASCII Copying %s to %s (append?%d)\n",
+ wine_dbgstr_w(srcname), wine_dbgstr_w(dstname), append);
+
+ in = CreateFileW(srcname, GENERIC_READ, 0, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (in == NULL) {
+ WINE_ERR("Failed to open %s (%d)\n", wine_dbgstr_w(srcname), GetLastError());
+ return FALSE;
+ }
+
+ /* Open the output file, overwriting if not appending */
+ out = CreateFileW(dstname, GENERIC_WRITE, 0, NULL,
+ append?OPEN_EXISTING:CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (out == NULL) {
+ WINE_ERR("Failed to open %s (%d)\n", wine_dbgstr_w(dstname), GetLastError());
+ return FALSE;
+ }
+
+ /* Move to end of destination if we are going to append to it */
+ if (append) {
+ SetFilePointer(out, 0, NULL, FILE_END);
+ }
+
+ /* Loop copying data from source to destination until EOF read */
+ ok = TRUE;
+ do
+ {
+ char buffer[MAXSTRING];
+
+ ok = ReadFile(in, buffer, MAXSTRING, &bytesread, NULL);
+ if (ok) {
+
+ /* Stop at first EOF */
+ if (ascii) {
+ char *ptr = (char *)memchr((void *)buffer, '\x1a', bytesread);
+ if (ptr) bytesread = (ptr - buffer);
+ }
+
+ if (bytesread) {
+ ok = WriteFile(out, buffer, bytesread, &byteswritten, NULL);
+ if (!ok || byteswritten != bytesread) {
+ WINE_ERR("Unexpected failure writing to %s, rc=%d\n",
+ wine_dbgstr_w(dstname), GetLastError());
+ }
+ }
+ } else {
+ WINE_ERR("Unexpected failure reading from %s, rc=%d\n",
+ wine_dbgstr_w(srcname), GetLastError());
+ }
+ } while (ok && bytesread > 0);
+
+ CloseHandle(out);
+ CloseHandle(in);
+ return ok;
+}
+
+/****************************************************************************
* WCMD_copy
*
* Copy a file or wildcarded set.
@@ -697,11 +767,13 @@ void WCMD_copy(WCHAR * command) {
} else if (!destisdirectory) {
/* We have been asked to copy to a filename. Default to ascii IF the
source contains wildcards (true even if only one match) */
- if (destination->binarycopy == -1) {
- if (strpbrkW(sourcelist->name, wildcardsW) != NULL) {
- anyconcats = TRUE; /* We really are concatenating to a single file */
+ if (strpbrkW(sourcelist->name, wildcardsW) != NULL) {
+ anyconcats = TRUE; /* We really are concatenating to a single file */
+ if (destination->binarycopy == -1) {
destination->binarycopy = 0;
- } else {
+ }
+ } else {
+ if (destination->binarycopy == -1) {
destination->binarycopy = 1;
}
}
@@ -731,7 +803,7 @@ void WCMD_copy(WCHAR * command) {
WCHAR *filenamepart;
DWORD attributes;
- /* If it was not explicit, we now know whehter we are concatenating or not and
+ /* If it was not explicit, we now know whether we are concatenating or not and
hence whether to copy as binary or ascii */
if (thiscopy->binarycopy == -1) thiscopy->binarycopy = !anyconcats;
@@ -820,17 +892,15 @@ void WCMD_copy(WCHAR * command) {
if (overwrite) {
if (anyconcats && writtenoneconcat) {
if (thiscopy->binarycopy) {
- WINE_FIXME("Need to concatenate %s to %s (read as binary), will overwrite\n",
- wine_dbgstr_w(srcpath), wine_dbgstr_w(outname));
+ status = WCMD_ManualCopy(srcpath, outname, FALSE, TRUE);
} else {
- WINE_FIXME("Need to concatenate %s to %s (read as ascii), will overwrite\n",
- wine_dbgstr_w(srcpath), wine_dbgstr_w(outname));
+ status = WCMD_ManualCopy(srcpath, outname, TRUE, TRUE);
}
} else if (!thiscopy->binarycopy) {
- WINE_FIXME("Need to ascii copy %s to %s - dropping to binary copy\n",
- wine_dbgstr_w(srcpath), wine_dbgstr_w(outname));
+ status = WCMD_ManualCopy(srcpath, outname, TRUE, FALSE);
+ } else {
+ status = CopyFileW(srcpath, outname, FALSE);
}
- status = CopyFileW(srcpath, outname, FALSE);
if (!status) {
WCMD_print_error ();
errorlevel = 1;
@@ -838,8 +908,11 @@ void WCMD_copy(WCHAR * command) {
WINE_TRACE("Copied successfully\n");
if (anyconcats) writtenoneconcat = TRUE;
- /* Append EOF if ascii destination and we are not going to add more onto the end */
- if (!destination->binarycopy && !anyconcats) {
+ /* Append EOF if ascii destination and we are not going to add more onto the end
+ Note: Testing shows windows has an optimization whereas if you have a binary
+ copy of a file to a single destination (ie concatenation) then it does not add
+ the EOF, hence the check on the source copy type below. */
+ if (!destination->binarycopy && !anyconcats && !thiscopy->binarycopy) {
if (!WCMD_AppendEOF(outname)) {
WCMD_print_error ();
errorlevel = 1;
diff --git a/programs/cmd/tests/test_builtins.cmd b/programs/cmd/tests/test_builtins.cmd
index c7795bf..1956c3f 100644
--- a/programs/cmd/tests/test_builtins.cmd
+++ b/programs/cmd/tests/test_builtins.cmd
@@ -1911,6 +1911,10 @@ rem One file has EOF, but doesnt get an extra one, ie 6
copy /b file1_plus_eof file123_mixed_copy7 /a >nul 2>&1
call :CheckFileSize file123_mixed_copy7 6
+rem Syntax means concatenate so ascii destination kicks in
+copy /b file1_plus_eof* file123_mixed_copy8 /a >nul 2>&1
+call :CheckFileSize file123_mixed_copy8 7
+
del *.* /q
cd ..
diff --git a/programs/cmd/tests/test_builtins.cmd.exp b/programs/cmd/tests/test_builtins.cmd.exp
index 620e44b..f6e7d11 100644
--- a/programs/cmd/tests/test_builtins.cmd.exp
+++ b/programs/cmd/tests/test_builtins.cmd.exp
@@ -882,21 +882,22 @@ Passed: file size check on file1_default2 [5]@or_broken at Skipping file size check
Passed: file size check on file1_plus_eof [6]@or_broken at Skipping file size check on NT4
Passed: file size check on file2_plus_eof [9]@or_broken at Skipping file size check on NT4
Passed: file size check on file3_plus_eof [12]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file12_plus_eof [14]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file12_no_eof [13]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file12_eof2 [14]@or_broken at Skipping file size check on NT4
+Passed: file size check on file12_plus_eof [14]@or_broken at Skipping file size check on NT4
+Passed: file size check on file12_no_eof [13]@or_broken at Skipping file size check on NT4
+Passed: file size check on file12_eof2 [14]@or_broken at Skipping file size check on NT4
Passed: file size check on file1_binary_srccopy [6]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file1_ascii_srccopy [5]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file123_default_copy [25]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file123_ascii_copy [25]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file123_binary_copy [27]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file123_mixed_copy1 [26]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file123_mixed_copy2 [27]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file123_mixed_copy3 [26]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file123_mixed_copy4 [25]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file123_mixed_copy5 [28]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file123_mixed_copy6 [19]@or_broken at Skipping file size check on NT4
- at todo_wine@Passed: file size check on file123_mixed_copy7 [6]@or_broken at Skipping file size check on NT4
+Passed: file size check on file1_ascii_srccopy [5]@or_broken at Skipping file size check on NT4
+Passed: file size check on file123_default_copy [25]@or_broken at Skipping file size check on NT4
+Passed: file size check on file123_ascii_copy [25]@or_broken at Skipping file size check on NT4
+Passed: file size check on file123_binary_copy [27]@or_broken at Skipping file size check on NT4
+Passed: file size check on file123_mixed_copy1 [26]@or_broken at Skipping file size check on NT4
+Passed: file size check on file123_mixed_copy2 [27]@or_broken at Skipping file size check on NT4
+Passed: file size check on file123_mixed_copy3 [26]@or_broken at Skipping file size check on NT4
+Passed: file size check on file123_mixed_copy4 [25]@or_broken at Skipping file size check on NT4
+Passed: file size check on file123_mixed_copy5 [28]@or_broken at Skipping file size check on NT4
+Passed: file size check on file123_mixed_copy6 [19]@or_broken at Skipping file size check on NT4
+Passed: file size check on file123_mixed_copy7 [6]@or_broken at Skipping file size check on NT4
+Passed: file size check on file123_mixed_copy8 [7]@or_broken at Skipping file size check on NT4
Passed: errorlevel invalid check 1
Passed: Did not find dir1\file1
Passed: errorlevel invalid check 2
--
1.7.9.5
More information about the wine-patches
mailing list