Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886/* * COPY.C -- copy internal command. * * * History: * * 01-Aug-98 (Rob Lake z63rrl@morgan.ucs.mun.ca) * started * * 13-Aug-1998 (John P. Price) * fixed memory leak problem in copy function. * fixed copy function so it would work with wildcards in the source * * 13-Dec-1998 (Eric Kohl) * Added COPY command to CMD. * * 26-Jan-1998 (Eric Kohl) * Replaced CRT io functions by Win32 io functions. * * 27-Oct-1998 (Eric Kohl) * Disabled prompting when used in batch mode. * * 03-Apr-2005 (Magnus Olsen <magnus@greatlord.com>) * Remove all hardcode string to En.rc * * 13-Jul-2005 (Brandon Turner <turnerb7@msu.edu>) * Rewrite to clean up copy and support wildcard. * * 20-Jul-2005 (Brandon Turner <turnerb7@msu.edu>) * Add touch syntax. "copy arp.exe+,," * Copy command is now completed. */
#include "precomp.h"
#ifdef INCLUDE_CMD_COPY
enum{ COPY_ASCII = 0x001, /* /A */ COPY_DECRYPT = 0x004, /* /D */ COPY_VERIFY = 0x008, /* /V : Dummy, Never will be Implemented */ COPY_SHORTNAME = 0x010, /* /N : Dummy, Never will be Implemented */ COPY_NO_PROMPT = 0x020, /* /Y */ COPY_PROMPT = 0x040, /* /-Y */ COPY_RESTART = 0x080, /* /Z */ COPY_BINARY = 0x100, /* /B */};
INTcopy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch){ FILETIME srctime,NewFileTime; HANDLE hFileSrc; HANDLE hFileDest; LPBYTE buffer; DWORD dwAttrib; DWORD dwRead; DWORD dwWritten; BOOL bEof = FALSE; TCHAR TrueDest[MAX_PATH]; TCHAR TempSrc[MAX_PATH]; TCHAR * FileName; SYSTEMTIME CurrentTime;
/* Check Breaker */ if (CheckCtrlBreak(BREAK_INPUT)) return 0;
TRACE ("checking mode\n");
if (bTouch) { hFileSrc = CreateFile (source, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFileSrc == INVALID_HANDLE_VALUE) { ConOutResPrintf(STRING_COPY_ERROR1, source); nErrorLevel = 1; return 0; }
GetSystemTime(&CurrentTime); SystemTimeToFileTime(&CurrentTime, &NewFileTime); if (SetFileTime(hFileSrc,(LPFILETIME) NULL, (LPFILETIME) NULL, &NewFileTime)) { CloseHandle(hFileSrc); nErrorLevel = 1; return 1;
} else { CloseHandle(hFileSrc); return 0; } }
dwAttrib = GetFileAttributes (source);
hFileSrc = CreateFile (source, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFileSrc == INVALID_HANDLE_VALUE) { ConOutResPrintf(STRING_COPY_ERROR1, source); nErrorLevel = 1; return 0; }
TRACE ("getting time\n");
GetFileTime (hFileSrc, &srctime, NULL, NULL);
TRACE ("copy: flags has %s\n", lpdwFlags & COPY_ASCII ? "ASCII" : "BINARY");
/* Check to see if /D or /Z are true, if so we need a middle man to copy the file too to allow us to use CopyFileEx later */ if (lpdwFlags & COPY_DECRYPT) { GetEnvironmentVariable(_T("TEMP"),TempSrc,MAX_PATH); _tcscat(TempSrc,_T("\\")); FileName = _tcsrchr(source,_T('\\')); FileName++; _tcscat(TempSrc,FileName); /* This is needed to be on the end to prevent an error if the user did "copy /D /Z foo bar then it would be copied too %TEMP%\foo here and when %TEMP%\foo when it sets it up for COPY_RESTART, this would mean it is copying to itself which would error when it tried to open the handles for ReadFile and WriteFile */ _tcscat(TempSrc,_T(".decrypt")); if (!CopyFileEx(source, TempSrc, NULL, NULL, FALSE, COPY_FILE_ALLOW_DECRYPTED_DESTINATION)) { CloseHandle (hFileSrc); nErrorLevel = 1; return 0; } _tcscpy(source, TempSrc); }
if (lpdwFlags & COPY_RESTART) { _tcscpy(TrueDest, dest); GetEnvironmentVariable(_T("TEMP"),dest,MAX_PATH); _tcscat(dest,_T("\\")); FileName = _tcsrchr(TrueDest,_T('\\')); FileName++; _tcscat(dest,FileName); }
if (!IsExistingFile (dest)) { TRACE ("opening/creating\n"); hFileDest = CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); } else if (!append) { TRACE ("SetFileAttributes (%s, FILE_ATTRIBUTE_NORMAL);\n", debugstr_aw(dest)); SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL);
TRACE ("DeleteFile (%s);\n", debugstr_aw(dest)); DeleteFile (dest);
hFileDest = CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); } else { LONG lFilePosHigh = 0;
if (!_tcscmp (dest, source)) { CloseHandle (hFileSrc); return 0; }
TRACE ("opening/appending\n"); SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL);
hFileDest = CreateFile (dest, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
/* Move to end of file to start writing */ SetFilePointer (hFileDest, 0, &lFilePosHigh,FILE_END); }
if (hFileDest == INVALID_HANDLE_VALUE) { CloseHandle (hFileSrc); ConOutResPuts(STRING_ERROR_PATH_NOT_FOUND); nErrorLevel = 1; return 0; }
/* A page-aligned buffer usually give more speed */ buffer = VirtualAlloc(NULL, BUFF_SIZE, MEM_COMMIT, PAGE_READWRITE); if (buffer == NULL) { CloseHandle (hFileDest); CloseHandle (hFileSrc); ConOutResPuts(STRING_ERROR_OUT_OF_MEMORY); nErrorLevel = 1; return 0; }
do { ReadFile (hFileSrc, buffer, BUFF_SIZE, &dwRead, NULL); if (lpdwFlags & COPY_ASCII) { LPBYTE pEof = memchr(buffer, 0x1A, dwRead); if (pEof != NULL) { bEof = TRUE; dwRead = pEof-buffer+1; break; } }
if (dwRead == 0) break;
WriteFile (hFileDest, buffer, dwRead, &dwWritten, NULL); if (dwWritten != dwRead || CheckCtrlBreak(BREAK_INPUT)) { ConOutResPuts(STRING_COPY_ERROR3);
VirtualFree (buffer, 0, MEM_RELEASE); CloseHandle (hFileDest); CloseHandle (hFileSrc); nErrorLevel = 1; return 0; } } while (!bEof);
TRACE ("setting time\n"); SetFileTime (hFileDest, &srctime, NULL, NULL);
if ((lpdwFlags & COPY_ASCII) && !bEof) { /* we're dealing with ASCII files! */ buffer[0] = 0x1A; TRACE ("appending ^Z\n"); WriteFile (hFileDest, buffer, sizeof(CHAR), &dwWritten, NULL); }
VirtualFree (buffer, 0, MEM_RELEASE); CloseHandle (hFileDest); CloseHandle (hFileSrc);
TRACE ("setting mode\n"); /* For MS-DOS backwards-compatibility, always remove the read-only attribute */ SetFileAttributes (dest, dwAttrib & ~FILE_ATTRIBUTE_READONLY);
/* Now finish off the copy if needed with CopyFileEx */ if (lpdwFlags & COPY_RESTART) { if (!CopyFileEx(dest, TrueDest, NULL, NULL, FALSE, COPY_FILE_RESTARTABLE)) { nErrorLevel = 1; DeleteFile(dest); return 0; } /* Take care of file in the temp folder */ DeleteFile(dest);
}
if (lpdwFlags & COPY_DECRYPT) DeleteFile(TempSrc);
return 1;}
static INT CopyOverwrite (LPTSTR fn){ /*ask the user if they want to override*/ INT res; ConOutResPrintf(STRING_COPY_HELP1, fn); res = FilePromptYNA (0); return res;}
/* The following lines of copy were written by someone else(most likely Eric Kohl) and it was taken from ren.c */static voidBuildFileName( LPTSTR pszSource, LPTSTR pszTarget, LPTSTR pszOutput){ /* build destination file name */ while (*pszTarget != 0) { if (*pszTarget == _T('*')) { pszTarget++; while ((*pszSource != 0) && (*pszSource != *pszTarget)) { *pszOutput++ = *pszSource++; } } else if (*pszTarget == _T('?')) { pszTarget++; if (*pszSource != 0) { *pszOutput++ = *pszSource++; } } else { *pszOutput++ = *pszTarget++; if (*pszSource != 0) pszSource++; } }
*pszOutput = 0;}
INT cmd_copy(LPTSTR param){ LPTSTR *arg; INT argc, i, nFiles, nOverwrite = 0, nSrc = -1, nDes = -1; /* this is the path up to the folder of the src and dest ie C:\windows\ */ TCHAR szDestPath[MAX_PATH]; TCHAR szSrcPath[MAX_PATH]; DWORD dwFlags = 0; /* If this is the type of copy where we are adding files */ BOOL bAppend = FALSE; WIN32_FIND_DATA findBuffer; HANDLE hFile = NULL; BOOL bTouch = FALSE; /* Pointer to keep track of how far through the append input(file1+file2+file3) we are */ TCHAR * appendPointer = _T("\0"); /* The full path to src and dest. This has drive letter, folders, and filename */ TCHAR tmpDestPath[MAX_PATH]; TCHAR tmpSrcPath[MAX_PATH]; /* A bool to know whether or not the destination name will be taken from the input */ BOOL bSrcName = FALSE; /* Seems like a waste but it is a pointer used to copy from input to PreserveName */ TCHAR * UseThisName; /* for CMDCOPY env */ TCHAR *evar; int size; TCHAR * szTouch; BOOL bHasWildcard, bDone = FALSE, bMoreFiles = FALSE; /* Used for something like "copy c*.exe d*.exe" */ BOOL bMultipleSource = FALSE, bMultipleDest = FALSE;
/* Show help/usage info */ if (!_tcsncmp(param, _T("/?"), 2)) { ConOutResPaging(TRUE, STRING_COPY_HELP2); return 0; }
nErrorLevel = 0;
/* Get the env variable value if it exists */ evar = cmd_alloc(512 * sizeof(TCHAR)); if (evar == NULL) size = 0; else size = GetEnvironmentVariable (_T("COPYCMD"), evar, 512);
if (size > 512) { TCHAR *old_evar = evar; evar = cmd_realloc(evar,size * sizeof(TCHAR) ); if (evar!=NULL) size = GetEnvironmentVariable (_T("COPYCMD"), evar, size); else { size=0; evar = old_evar; } }
/* check see if we did get any env variable */ if (size != 0) { int t = 0;
/* scan and set the flags */ for (t = 0; t < size; t++) { if (_tcsncicmp(_T("/A"),&evar[t],2) == 0) { dwFlags |=COPY_ASCII; t++; } else if (_tcsncicmp(_T("/B"),&evar[t],2) == 0) { dwFlags |= COPY_BINARY; t++; } else if (_tcsncicmp(_T("/D"),&evar[t],2) == 0) { dwFlags |= COPY_DECRYPT; t++; } else if (_tcsncicmp(_T("/V"),&evar[t],2) == 0) { dwFlags |= COPY_VERIFY; t++; } else if (_tcsncicmp(_T("/N"),&evar[t],2) == 0) { dwFlags |= COPY_SHORTNAME; t++; } else if (_tcsncicmp(_T("/Y"),&evar[t],2) == 0) { dwFlags |= COPY_NO_PROMPT; t++; } else if (_tcsncicmp(_T("/-Y"),&evar[t],3) == 0) { dwFlags |= COPY_PROMPT; t+=2; } else if (_tcsncicmp(_T("/Z"),&evar[t],2) == 0) { dwFlags |= COPY_PROMPT; t++; } } } cmd_free(evar);
/* Split the user input into array */ arg = split(param, &argc, FALSE, TRUE); nFiles = argc;
/* Read switches and count files */ for (i = 0; i < argc; i++) { if (*arg[i] == _T('/')) { if (_tcslen(arg[i]) >= 2) { switch (_totupper(arg[i][1])) { case _T('A'): dwFlags |= COPY_ASCII; break;
case _T('B'): dwFlags |= COPY_BINARY; break;
case _T('D'): dwFlags |= COPY_DECRYPT; break;
case _T('V'): dwFlags |= COPY_VERIFY; break;
case _T('N'): dwFlags |= COPY_SHORTNAME; break;
case _T('Y'): dwFlags |= COPY_NO_PROMPT; dwFlags &= ~COPY_PROMPT; break;
case _T('-'): if (_tcslen(arg[i]) >= 3) { if (_totupper(arg[i][2]) == _T('Y')) { dwFlags &= ~COPY_NO_PROMPT; dwFlags |= COPY_PROMPT; } }
break;
case _T('Z'): dwFlags |= COPY_RESTART; break;
default: /* Invalid switch */ ConOutResPrintf(STRING_ERROR_INVALID_SWITCH, _totupper(arg[i][1])); nErrorLevel = 1; freep (arg); return 1; break; } } /* If it was a switch, subtract from total arguments */ nFiles--; } else { /* If it isn't a switch then it is the source or destination */ if (nSrc == -1) { nSrc = i; } else if (*arg[i] == _T('+')) { /* Next file should be appended */ bMoreFiles = TRUE; nFiles -= 1; } else if (bMoreFiles) { /* Add this file to the source string this way we can do all checks directly on source string later on */ TCHAR * ptr; int length = (_tcslen(arg[nSrc]) + _tcslen(arg[i]) + 2) * sizeof(TCHAR); ptr = cmd_alloc(length); if (ptr) { _tcscpy(ptr, arg[nSrc]); _tcscat(ptr, _T("|")); _tcscat(ptr, arg[i]); cmd_free(arg[nSrc]); arg[nSrc] = ptr; nFiles -= 1; }
bMoreFiles = FALSE; } else if (nDes == -1) { nDes = i; } } }
/* keep quiet within batch files */ if (bc != NULL) { dwFlags |= COPY_NO_PROMPT; dwFlags &= ~COPY_PROMPT; }
if (nFiles < 1) { /* There are not enough files, there has to be at least 1 */ ConOutResPuts(STRING_ERROR_REQ_PARAM_MISSING); freep(arg); return 1; }
if (nFiles > 2) { /* There are too many file names in command */ ConErrResPrintf(STRING_ERROR_TOO_MANY_PARAMETERS,_T("")); nErrorLevel = 1; freep(arg); return 1; }
if ((_tcschr(arg[nSrc], _T('|')) != NULL) || (_tcschr(arg[nSrc], _T('*')) != NULL) || (_tcschr(arg[nSrc], _T('?')) != NULL) || IsExistingDirectory(arg[nSrc])) { bMultipleSource = TRUE; }
/* Reuse the number of files variable */ nFiles = 0;
/* Check if no destination argument is passed */ if (nDes == -1) { /* If no destination was entered then just use the current directory as the destination */ GetCurrentDirectory(ARRAYSIZE(szDestPath), szDestPath); } else { /* Check if the destination is 'x:' */ if ((arg[nDes][1] == _T(':')) && (arg[nDes][2] == _T('\0'))) { GetRootPath(arg[nDes], szDestPath, ARRAYSIZE(szDestPath)); } else { /* If the user entered two file names then form the full string path */ GetFullPathName(arg[nDes], ARRAYSIZE(szDestPath), szDestPath, NULL); }
/* Make sure there is an ending slash to the path if the dest is a folder */ if ((_tcschr(szDestPath, _T('*')) == NULL) && IsExistingDirectory(szDestPath)) { bMultipleDest = TRUE; if (szDestPath[_tcslen(szDestPath) - 1] != _T('\\')) _tcscat(szDestPath, _T("\\")); }
/* Check if the destination uses wildcards */ if ((_tcschr(arg[nDes], _T('*')) != NULL) || (_tcschr(arg[nDes], _T('?')) != NULL)) { bMultipleDest = TRUE; } }
if (nDes != -1) /* Append files only when there is a destination */ { if (bMultipleSource && !bMultipleDest) { /* We have multiple source files, but not multiple destination files. This means we are appending the source files. */ bAppend = TRUE; if (_tcschr(arg[nSrc], _T('|')) != NULL) appendPointer = arg[nSrc]; } }
/* Save the name the user entered */ UseThisName = _tcsrchr(szDestPath,_T('\\')); if (UseThisName) { /* Split the name from the path */ *UseThisName++ = _T('\0');
/* Check if the dest path ends with '\*' or '\' */ if (((UseThisName[0] == _T('*')) && (UseThisName[1] == _T('\0'))) || (UseThisName[0] == _T('\0'))) { /* In this case we will be using the same name as the source file for the destination file because destination is a folder */ bSrcName = TRUE; UseThisName = NULL; } } else { /* Something's seriously wrong! */ UseThisName = szDestPath; }
do { /* Get the full string of the path to the source file */ if (_tcschr(arg[nSrc], _T('|')) != NULL) { /* Reset the source path */ szSrcPath[0] = _T('\0');
/* Loop through the source file name and copy all the chars one at a time until we reach the separator */ while(TRUE) { if (appendPointer[0] == _T('|')) { /* Skip the | and go to the next file name */ appendPointer++; break; } else if (appendPointer[0] == _T('\0')) { bDone = TRUE; break; }
_tcsncat(szSrcPath, appendPointer, 1); appendPointer++; }
if (_tcschr(arg[nSrc], _T(',')) != NULL) { /* Only time there is a , in the source is when they are using touch Cant have a destination and can only have on ,, at the end of the string Cant have more than one file name */ szTouch = _tcsstr(arg[nSrc], _T("|")); if (_tcsncmp(szTouch,_T("|,,\0"), 4) || (nDes != -1)) { ConErrResPrintf(STRING_ERROR_INVALID_PARAM_FORMAT,arg[nSrc]); nErrorLevel = 1; freep (arg); return 1; } bTouch = TRUE; bDone = TRUE; } } else { bDone = TRUE; _tcscpy(szSrcPath, arg[nSrc]); }
/* "x:" is not a valid source path format. */ if ((szSrcPath[1] == _T(':')) && (szSrcPath[2] == _T('\0'))) { ConOutPrintf(_T("%s\n"), szSrcPath); ConOutFormatMessage(ERROR_FILE_NOT_FOUND, szSrcPath); nErrorLevel = 1; break; }
/* From this point on, we can assume that the shortest path is 3 letters long and that would be [DriveLetter]:\ */
/* Check if the path has a wildcard */ bHasWildcard = (_tcschr(szSrcPath, _T('*')) != NULL);
/* If there is no * in the path name and it is a folder then we will need to add a wildcard to the pathname so FindFirstFile comes up with all the files in that folder */ if (!bHasWildcard && IsExistingDirectory(szSrcPath)) { /* If it doesnt have a \ at the end already then on needs to be added */ if (szSrcPath[_tcslen(szSrcPath) - 1] != _T('\\')) _tcscat(szSrcPath, _T("\\")); _tcscat(szSrcPath, _T("*")); bHasWildcard = TRUE; }
/* If the path ends with '\' add a wildcard at the end */ if (szSrcPath[_tcslen(szSrcPath) - 1] == _T('\\')) { _tcscat(szSrcPath, _T("*")); bHasWildcard = TRUE; }
/* Get a list of all the files */ hFile = FindFirstFile(szSrcPath, &findBuffer);
/* If we could not open the file handle, print out the error */ if (hFile == INVALID_HANDLE_VALUE) { /* only print source name when more than one file */ if (bMultipleSource) ConOutPrintf(_T("%s\n"), szSrcPath);
ConOutFormatMessage(GetLastError(), szSrcPath); freep(arg); nErrorLevel = 1; return 1; }
/* Strip the paths back to the folder they are in */ for (i = (_tcslen(szSrcPath) - 1); i > -1; i--) { if (szSrcPath[i] != _T('\\')) szSrcPath[i] = _T('\0'); else break; }
do { /* Check Breaker */ if (CheckCtrlBreak(BREAK_INPUT)) { FindClose(hFile); freep(arg); return 1; }
/* Set the override to yes each new file */ nOverwrite = 1;
/* Ignore the . and .. files */ if (!_tcscmp(findBuffer.cFileName, _T(".")) || !_tcscmp(findBuffer.cFileName, _T("..")) || findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { continue; }
/* Copy the base folder over to a tmp string */ _tcscpy(tmpDestPath, szDestPath); _tcscat(tmpDestPath, _T("\\"));
/* Can't put a file into a folder that isn't there */ if (_tcscmp(tmpDestPath, _T("\\\\.\\")) && !IsExistingDirectory(tmpDestPath)) { FindClose(hFile); ConOutFormatMessage(GetLastError(), szSrcPath); freep(arg); nErrorLevel = 1; return 1; }
/* Copy over the destination path name */ if (bSrcName) _tcscat(tmpDestPath, findBuffer.cFileName); else { /* If there is no wildcard, use the name the user entered */ if ((_tcschr(UseThisName, _T('*')) == NULL) && (_tcschr(UseThisName, _T('?')) == NULL)) { _tcscat(tmpDestPath, UseThisName); } else { TCHAR DoneFile[MAX_PATH];
BuildFileName(findBuffer.cFileName, UseThisName, DoneFile);
/* Add the filename to the tmp string path */ _tcscat(tmpDestPath, DoneFile); } }
/* Build the string path to the source file */ _tcscpy(tmpSrcPath,szSrcPath); _tcscat (tmpSrcPath, findBuffer.cFileName);
/* Check to see if the file is the same file */ if (!bTouch && !_tcscmp(tmpSrcPath, tmpDestPath)) { ConOutResPrintf(STRING_COPY_ERROR2);
nErrorLevel = 1; break; }
/* only print source name when more than one file */ if (bMultipleSource) ConOutPrintf(_T("%s\n"), tmpSrcPath);
/* Handle any overriding / prompting that needs to be done */ if (((!(dwFlags & COPY_NO_PROMPT) && IsExistingFile (tmpDestPath)) || dwFlags & COPY_PROMPT) && !bTouch) nOverwrite = CopyOverwrite(tmpDestPath); if (nOverwrite == PROMPT_NO || nOverwrite == PROMPT_BREAK) continue; if (nOverwrite == PROMPT_ALL || (nOverwrite == PROMPT_YES && bAppend)) dwFlags |= COPY_NO_PROMPT;
/* Tell whether the copy was successful or not */ if (copy(tmpSrcPath,tmpDestPath, bAppend, dwFlags, bTouch)) { nFiles++; } else { /* print out the error message */ ConOutResPrintf(STRING_COPY_ERROR3); ConOutFormatMessage (GetLastError(), szSrcPath); nErrorLevel = 1; }
/* Loop through all wildcard files */ } while (FindNextFile(hFile, &findBuffer));
FindClose(hFile);
/* Loop through all files in src string with a + */ } while (!bDone);
/* print out the number of files copied */ ConOutResPrintf(STRING_COPY_FILE, bAppend ? 1 : nFiles);
if (arg != NULL) freep(arg);
return 0;}
#endif /* INCLUDE_CMD_COPY */