cmd: Add full support for copy concatenation and ascii/binary.

This commit is contained in:
Jason Edmeades 2012-10-12 10:23:24 +01:00 committed by Alexandre Julliard
parent 260210f6e6
commit 130cdcd727
3 changed files with 106 additions and 28 deletions

View File

@ -400,6 +400,76 @@ static BOOL WCMD_AppendEOF(WCHAR *filename)
return TRUE;
}
/****************************************************************************
* WCMD_ManualCopy
*
* Copies from a file
* optionally reading only until EOF (ascii copy)
* optionally appending onto an existing file (append)
* Returns TRUE on success
*/
static 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
*
@ -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 (destination->binarycopy == -1) {
destination->binarycopy = 0;
}
} 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);
}
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;

View File

@ -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 ..

View File

@ -882,21 +882,22 @@ Passed: file size check on file1_default2 [5]@or_broken@Skipping file size check
Passed: file size check on file1_plus_eof [6]@or_broken@Skipping file size check on NT4
Passed: file size check on file2_plus_eof [9]@or_broken@Skipping file size check on NT4
Passed: file size check on file3_plus_eof [12]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file12_plus_eof [14]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file12_no_eof [13]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file12_eof2 [14]@or_broken@Skipping file size check on NT4
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_binary_srccopy [6]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file1_ascii_srccopy [5]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file123_default_copy [25]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file123_ascii_copy [25]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file123_binary_copy [27]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file123_mixed_copy1 [26]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file123_mixed_copy2 [27]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file123_mixed_copy3 [26]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file123_mixed_copy4 [25]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file123_mixed_copy5 [28]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file123_mixed_copy6 [19]@or_broken@Skipping file size check on NT4
@todo_wine@Passed: file size check on file123_mixed_copy7 [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
Passed: file size check on file123_ascii_copy [25]@or_broken@Skipping file size check on NT4
Passed: file size check on file123_binary_copy [27]@or_broken@Skipping file size check on NT4
Passed: file size check on file123_mixed_copy1 [26]@or_broken@Skipping file size check on NT4
Passed: file size check on file123_mixed_copy2 [27]@or_broken@Skipping file size check on NT4
Passed: file size check on file123_mixed_copy3 [26]@or_broken@Skipping file size check on NT4
Passed: file size check on file123_mixed_copy4 [25]@or_broken@Skipping file size check on NT4
Passed: file size check on file123_mixed_copy5 [28]@or_broken@Skipping file size check on NT4
Passed: file size check on file123_mixed_copy6 [19]@or_broken@Skipping file size check on NT4
Passed: file size check on file123_mixed_copy7 [6]@or_broken@Skipping file size check on NT4
Passed: file size check on file123_mixed_copy8 [7]@or_broken@Skipping file size check on NT4
Passed: errorlevel invalid check 1
Passed: Did not find dir1\file1
Passed: errorlevel invalid check 2