cmd: Add support for NUL in copy.
This commit is contained in:
parent
2e92853091
commit
d16f4e700b
|
@ -47,6 +47,7 @@ const WCHAR slashW[] = {'\\','\0'};
|
||||||
const WCHAR equalW[] = {'=','\0'};
|
const WCHAR equalW[] = {'=','\0'};
|
||||||
const WCHAR wildcardsW[] = {'*','?','\0'};
|
const WCHAR wildcardsW[] = {'*','?','\0'};
|
||||||
const WCHAR slashstarW[] = {'\\','*','\0'};
|
const WCHAR slashstarW[] = {'\\','*','\0'};
|
||||||
|
const WCHAR deviceW[] = {'\\','\\','.','\\','\0'};
|
||||||
const WCHAR inbuilt[][10] = {
|
const WCHAR inbuilt[][10] = {
|
||||||
{'C','A','L','L','\0'},
|
{'C','A','L','L','\0'},
|
||||||
{'C','D','\0'},
|
{'C','D','\0'},
|
||||||
|
@ -414,7 +415,7 @@ static BOOL WCMD_ManualCopy(WCHAR *srcname, WCHAR *dstname, BOOL ascii, BOOL app
|
||||||
BOOL ok;
|
BOOL ok;
|
||||||
DWORD bytesread, byteswritten;
|
DWORD bytesread, byteswritten;
|
||||||
|
|
||||||
WINE_TRACE("ASCII Copying %s to %s (append?%d)\n",
|
WINE_TRACE("Manual Copying %s to %s (append?%d)\n",
|
||||||
wine_dbgstr_w(srcname), wine_dbgstr_w(dstname), append);
|
wine_dbgstr_w(srcname), wine_dbgstr_w(dstname), append);
|
||||||
|
|
||||||
in = CreateFileW(srcname, GENERIC_READ, 0, NULL,
|
in = CreateFileW(srcname, GENERIC_READ, 0, NULL,
|
||||||
|
@ -502,7 +503,7 @@ void WCMD_copy(WCHAR * args) {
|
||||||
int argno = 0;
|
int argno = 0;
|
||||||
WCHAR *rawarg;
|
WCHAR *rawarg;
|
||||||
WIN32_FIND_DATAW fd;
|
WIN32_FIND_DATAW fd;
|
||||||
HANDLE hff;
|
HANDLE hff = INVALID_HANDLE_VALUE;
|
||||||
int binarymode = -1; /* -1 means use the default, 1 is binary, 0 ascii */
|
int binarymode = -1; /* -1 means use the default, 1 is binary, 0 ascii */
|
||||||
BOOL concatnextfilename = FALSE; /* True if we have just processed a + */
|
BOOL concatnextfilename = FALSE; /* True if we have just processed a + */
|
||||||
BOOL anyconcats = FALSE; /* Have we found any + options */
|
BOOL anyconcats = FALSE; /* Have we found any + options */
|
||||||
|
@ -514,6 +515,7 @@ void WCMD_copy(WCHAR * args) {
|
||||||
BOOL status;
|
BOOL status;
|
||||||
WCHAR copycmd[4];
|
WCHAR copycmd[4];
|
||||||
DWORD len;
|
DWORD len;
|
||||||
|
BOOL dstisdevice = FALSE;
|
||||||
static const WCHAR copyCmdW[] = {'C','O','P','Y','C','M','D','\0'};
|
static const WCHAR copyCmdW[] = {'C','O','P','Y','C','M','D','\0'};
|
||||||
|
|
||||||
typedef struct _COPY_FILES
|
typedef struct _COPY_FILES
|
||||||
|
@ -785,6 +787,12 @@ void WCMD_copy(WCHAR * args) {
|
||||||
WINE_TRACE("Resolved destination is '%s' (calc later %d)\n",
|
WINE_TRACE("Resolved destination is '%s' (calc later %d)\n",
|
||||||
wine_dbgstr_w(destname), appendfirstsource);
|
wine_dbgstr_w(destname), appendfirstsource);
|
||||||
|
|
||||||
|
/* Remember if the destination is a device */
|
||||||
|
if (strncmpW(destination->name, deviceW, strlenW(deviceW)) == 0) {
|
||||||
|
WINE_TRACE("Destination is a device\n");
|
||||||
|
dstisdevice = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Now we need to walk the set of sources, and process each name we come to.
|
/* Now we need to walk the set of sources, and process each name we come to.
|
||||||
If anyconcats is true, we are writing to one file, otherwise we are using
|
If anyconcats is true, we are writing to one file, otherwise we are using
|
||||||
the source name each time.
|
the source name each time.
|
||||||
|
@ -800,8 +808,10 @@ void WCMD_copy(WCHAR * args) {
|
||||||
while (thiscopy != NULL) {
|
while (thiscopy != NULL) {
|
||||||
|
|
||||||
WCHAR srcpath[MAX_PATH];
|
WCHAR srcpath[MAX_PATH];
|
||||||
|
const WCHAR *srcname;
|
||||||
WCHAR *filenamepart;
|
WCHAR *filenamepart;
|
||||||
DWORD attributes;
|
DWORD attributes;
|
||||||
|
BOOL srcisdevice = FALSE;
|
||||||
|
|
||||||
/* If it was not explicit, we now know whether 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 */
|
hence whether to copy as binary or ascii */
|
||||||
|
@ -836,29 +846,41 @@ void WCMD_copy(WCHAR * args) {
|
||||||
WINE_TRACE("Copy source (calculated): path: '%s' (Concats: %d)\n",
|
WINE_TRACE("Copy source (calculated): path: '%s' (Concats: %d)\n",
|
||||||
wine_dbgstr_w(srcpath), anyconcats);
|
wine_dbgstr_w(srcpath), anyconcats);
|
||||||
|
|
||||||
/* Loop through all source files */
|
/* If the source is a device, just use it, otherwise search */
|
||||||
WINE_TRACE("Searching for: '%s'\n", wine_dbgstr_w(srcpath));
|
if (strncmpW(srcpath, deviceW, strlenW(deviceW)) == 0) {
|
||||||
hff = FindFirstFileW(srcpath, &fd);
|
WINE_TRACE("Source is a device\n");
|
||||||
if (hff != INVALID_HANDLE_VALUE) {
|
srcisdevice = TRUE;
|
||||||
|
srcname = &srcpath[4]; /* After the \\.\ prefix */
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Loop through all source files */
|
||||||
|
WINE_TRACE("Searching for: '%s'\n", wine_dbgstr_w(srcpath));
|
||||||
|
hff = FindFirstFileW(srcpath, &fd);
|
||||||
|
if (hff != INVALID_HANDLE_VALUE) {
|
||||||
|
srcname = fd.cFileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcisdevice || hff != INVALID_HANDLE_VALUE) {
|
||||||
do {
|
do {
|
||||||
WCHAR outname[MAX_PATH];
|
WCHAR outname[MAX_PATH];
|
||||||
BOOL overwrite;
|
BOOL overwrite;
|
||||||
|
|
||||||
/* Skip . and .., and directories */
|
/* Skip . and .., and directories */
|
||||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
if (!srcisdevice && fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
WINE_TRACE("Skipping directories\n");
|
WINE_TRACE("Skipping directories\n");
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Build final destination name */
|
/* Build final destination name */
|
||||||
strcpyW(outname, destination->name);
|
strcpyW(outname, destination->name);
|
||||||
if (destisdirectory || appendfirstsource) strcatW(outname, fd.cFileName);
|
if (destisdirectory || appendfirstsource) strcatW(outname, srcname);
|
||||||
|
|
||||||
/* Build source name */
|
/* Build source name */
|
||||||
strcpyW(filenamepart, fd.cFileName);
|
if (!srcisdevice) strcpyW(filenamepart, srcname);
|
||||||
|
|
||||||
/* Do we just overwrite */
|
/* Do we just overwrite (we do if we are writing to a device) */
|
||||||
overwrite = !prompt;
|
overwrite = !prompt;
|
||||||
if (anyconcats && writtenoneconcat) {
|
if (dstisdevice || (anyconcats && writtenoneconcat)) {
|
||||||
overwrite = TRUE;
|
overwrite = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,7 +901,7 @@ void WCMD_copy(WCHAR * args) {
|
||||||
else overwrite = TRUE;
|
else overwrite = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we needed tyo save away the first filename, do it */
|
/* If we needed to save away the first filename, do it */
|
||||||
if (appendfirstsource && overwrite) {
|
if (appendfirstsource && overwrite) {
|
||||||
heap_free(destination->name);
|
heap_free(destination->name);
|
||||||
destination->name = heap_strdupW(outname);
|
destination->name = heap_strdupW(outname);
|
||||||
|
@ -898,6 +920,8 @@ void WCMD_copy(WCHAR * args) {
|
||||||
}
|
}
|
||||||
} else if (!thiscopy->binarycopy) {
|
} else if (!thiscopy->binarycopy) {
|
||||||
status = WCMD_ManualCopy(srcpath, outname, TRUE, FALSE);
|
status = WCMD_ManualCopy(srcpath, outname, TRUE, FALSE);
|
||||||
|
} else if (srcisdevice) {
|
||||||
|
status = WCMD_ManualCopy(srcpath, outname, FALSE, FALSE);
|
||||||
} else {
|
} else {
|
||||||
status = CopyFileW(srcpath, outname, FALSE);
|
status = CopyFileW(srcpath, outname, FALSE);
|
||||||
}
|
}
|
||||||
|
@ -921,8 +945,8 @@ void WCMD_copy(WCHAR * args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (FindNextFileW(hff, &fd) != 0);
|
} while (!srcisdevice && FindNextFileW(hff, &fd) != 0);
|
||||||
FindClose (hff);
|
if (!srcisdevice) FindClose (hff);
|
||||||
} else {
|
} else {
|
||||||
/* Error if the first file was not found */
|
/* Error if the first file was not found */
|
||||||
if (!anyconcats || (anyconcats && !writtenoneconcat)) {
|
if (!anyconcats || (anyconcats && !writtenoneconcat)) {
|
||||||
|
|
|
@ -607,7 +607,22 @@ if exist foo (
|
||||||
) else (
|
) else (
|
||||||
echo ***
|
echo ***
|
||||||
)
|
)
|
||||||
cd .. & rd foobar
|
echo 1234 >a.a
|
||||||
|
copy a.a+NUL b.b >nul
|
||||||
|
call :CheckFileSize a.a 7 b.b 8
|
||||||
|
copy NUL+a.a b.b >nul
|
||||||
|
call :CheckFileSize a.a 7 b.b 8
|
||||||
|
mkdir subdir
|
||||||
|
copy a.a+NUL subdir\ >nul
|
||||||
|
call :CheckFileSize a.a 7 subdir\a.a 8
|
||||||
|
del subdir\a.a
|
||||||
|
cd subdir
|
||||||
|
copy ..\a.a NUL >nul
|
||||||
|
if exist a.a echo Failed
|
||||||
|
cd ..
|
||||||
|
rd subdir /s /q
|
||||||
|
del a.a b.b
|
||||||
|
cd .. & rd foobar /s /q
|
||||||
|
|
||||||
echo ------------ Testing if/else ------------
|
echo ------------ Testing if/else ------------
|
||||||
echo --- if/else should work with blocks
|
echo --- if/else should work with blocks
|
||||||
|
|
|
@ -415,7 +415,13 @@ bar
|
||||||
bar
|
bar
|
||||||
bar
|
bar
|
||||||
NUL
|
NUL
|
||||||
@todo_wine@foo created
|
foo created
|
||||||
|
Passed: file size check on a.a [7]@or_broken@Skipping file size check on NT4
|
||||||
|
Passed: file size check on b.b [8]@or_broken@Skipping file size check on NT4
|
||||||
|
Passed: file size check on a.a [7]@or_broken@Skipping file size check on NT4
|
||||||
|
Passed: file size check on b.b [8]@or_broken@Skipping file size check on NT4
|
||||||
|
Passed: file size check on a.a [7]@or_broken@Skipping file size check on NT4
|
||||||
|
Passed: file size check on subdir\a.a [8]@or_broken@Skipping file size check on NT4
|
||||||
------------ Testing if/else ------------
|
------------ Testing if/else ------------
|
||||||
--- if/else should work with blocks
|
--- if/else should work with blocks
|
||||||
if seems to work
|
if seems to work
|
||||||
|
|
Loading…
Reference in New Issue