*
* 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>
enum
{
- COPY_ASCII = 0x001, /* /A */
- COPY_DECRYPT = 0x004, /* /D : Not Impleneted */
+ COPY_ASCII = 0x001, /* /A */
+ COPY_DECRYPT = 0x004, /* /D */
COPY_VERIFY = 0x008, /* /V : Dummy, Never will be Impleneted */
- COPY_SHORTNAME = 0x010, /* /N : Not Impleneted */
+ COPY_SHORTNAME = 0x010, /* /N : Dummy, Never will be Impleneted */
COPY_NO_PROMPT = 0x020, /* /Y */
COPY_PROMPT = 0x040, /* /-Y */
- COPY_RESTART = 0x080, /* /Z : Not Impleneted */
- COPY_BINARY = 0x100, /* /B */
+ COPY_RESTART = 0x080, /* /Z */
+ COPY_BINARY = 0x100, /* /B */
};
#define BUFF_SIZE 16384 /* 16k = max buffer size */
-int copy (LPTSTR source, LPTSTR dest, int append, DWORD lpdwFlags)
+int copy (TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
{
TCHAR szMsg[RC_STRING_MAX_SIZE];
FILETIME srctime;
DWORD dwWritten;
DWORD i;
BOOL bEof = FALSE;
+ TCHAR TrueDest[MAX_PATH];
+ TCHAR TempSrc[MAX_PATH];
+ TCHAR * FileName;
+
#ifdef _DEBUG
DebugPrintf (_T("checking mode\n"));
#endif
+ if(bTouch)
+ {
+ hFileSrc = CreateFile (source, GENERIC_WRITE, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, NULL);
+ if (hFileSrc == INVALID_HANDLE_VALUE)
+ {
+ LoadString(CMD_ModuleHandle, STRING_COPY_ERROR1, szMsg, RC_STRING_MAX_SIZE);
+ ConOutPrintf(szMsg, source);
+ nErrorLevel = 1;
+ return 0;
+ }
+
+ FILETIME NewFileTime;
+ SYSTEMTIME CurrentTime;
+
+ GetSystemTime(&CurrentTime);
+ SystemTimeToFileTime(&CurrentTime, &NewFileTime);
+ if(SetFileTime(hFileSrc,(LPFILETIME) NULL, (LPFILETIME) NULL, &NewFileTime))
+ {
+ CloseHandle(hFileSrc);
+ return 1;
+
+ }
+ else
+ {
+ CloseHandle(hFileSrc);
+ return 0;
+ }
+ }
+
dwAttrib = GetFileAttributes (source);
hFileSrc = CreateFile (source, GENERIC_READ, FILE_SHARE_READ,
nErrorLevel = 1;
return 0;
}
-
+
#ifdef _DEBUG
DebugPrintf (_T("getting time\n"));
#endif
#ifdef _DEBUG
DebugPrintf (_T("copy: flags has %s\n"),
- *lpdwFlags & ASCII ? "ASCII" : "BINARY");
+ lpdwFlags & COPY_ASCII ? "ASCII" : "BINARY");
#endif
+ /* 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))
+ {
+ 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))
{
#ifdef _DEBUG
if (hFileDest == INVALID_HANDLE_VALUE)
{
CloseHandle (hFileSrc);
- error_path_not_found ();
+ ConOutResPuts(STRING_ERROR_PATH_NOT_FOUND);
nErrorLevel = 1;
return 0;
}
{
CloseHandle (hFileDest);
CloseHandle (hFileSrc);
- error_out_of_memory ();
+ ConOutResPuts(STRING_ERROR_OUT_OF_MEMORY);
nErrorLevel = 1;
return 0;
}
#endif
SetFileAttributes (dest, dwAttrib);
+ /* 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;
}
INT res;
LoadString(CMD_ModuleHandle, STRING_COPY_HELP1, szMsg, RC_STRING_MAX_SIZE);
ConOutPrintf(szMsg,fn);
- res = FilePromptYNA ("");
+ res = FilePromptYNA (_T(""));
return res;
}
BOOL bAppend = FALSE;
WIN32_FIND_DATA findBuffer;
HANDLE hFile;
+ BOOL bTouch = FALSE;
/* Used when something like "copy c*.exe d*.exe" during the process of
figuring out the new name */
TCHAR tmpName[MAX_PATH] = _T("");
TCHAR * UseThisName;
/* Stores the name( i.e. blah.txt or blah*.txt) which later we might need */
TCHAR PreserveName[MAX_PATH];
- /* for CMDCOPY env */
- TCHAR *evar;
- int size;
+ /* for CMDCOPY env */
+ TCHAR *evar;
+ int size;
+ TCHAR * szTouch;
+ BOOL bDone = FALSE;
/*Show help/usage info*/
nErrorLevel = 0;
/* Get the envor value if it exists */
- evar = malloc(512);
+ evar = malloc(512 * sizeof(TCHAR));
if (evar==NULL) size = 0;
-
- size = GetEnvironmentVariable (_T("COPYCMD"), evar, 512);
- if ((size > 1) && (size > 512))
+ else
+ {
+ size = GetEnvironmentVariable (_T("COPYCMD"), evar, 512);
+ }
+ if (size > 512)
{
evar = realloc(evar,size * sizeof(TCHAR) );
if (evar!=NULL)
{
if (_tcsncicmp(_T("/A"),&evar[t],2)==0)
{
- evar[t]=_T(' ');
- evar[t+1]=_T(' ');
+ dwFlags |=COPY_ASCII;
+ t++;
}
else if (_tcsncicmp(_T("/B"),&evar[t],2)==0)
{
dwFlags |= COPY_BINARY;
- evar[t]=_T(' ');
- evar[t+1]=_T(' ');
+ t++;
}
else if (_tcsncicmp(_T("/D"),&evar[t],2)==0)
{
dwFlags |= COPY_DECRYPT;
- evar[t]=_T(' ');
- evar[t+1]=_T(' ');
+ t++;
}
else if (_tcsncicmp(_T("/V"),&evar[t],2)==0)
{
dwFlags |= COPY_VERIFY;
- evar[t]=_T(' ');
- evar[t+1]=_T(' ');
+ t++;
}
else if (_tcsncicmp(_T("/N"),&evar[t],2)==0)
{
dwFlags |= COPY_SHORTNAME;
- evar[t]=_T(' ');
- evar[t+1]=_T(' ');
+ t++;
}
else if (_tcsncicmp(_T("/Y"),&evar[t],2)==0)
{
dwFlags |= COPY_NO_PROMPT;
- evar[t]=_T(' ');
- evar[t+1]=_T(' ');
+ t++;
}
else if (_tcsncicmp(_T("/-Y"),&evar[t],3)==0)
{
dwFlags |= COPY_PROMPT;
- evar[t]=_T(' ');
- evar[t+1]=_T(' ');
- evar[t+2]=_T(' ');
+ t+=2;
}
else if (_tcsncicmp(_T("/Z"),&evar[t],2)==0)
{
dwFlags |= COPY_PROMPT;
- evar[t]=_T(' ');
- evar[t+1]=_T(' ');
+ t++;
}
}
}
default:
/* invaild switch */
- error_invalid_switch(_totupper(arg[i][1]));
+ LoadString(CMD_ModuleHandle, STRING_ERROR_INVALID_SWITCH, szMsg, RC_STRING_MAX_SIZE);
+ ConOutPrintf(szMsg, _totupper(arg[i][1]));
+
return 1;
break;
}
{
/*if it isnt a switch then it is the source or destination*/
if(nSrc == -1)
+ {
nSrc = i;
+ }
+ else if(*arg[i] == _T('+') || *arg[i] == _T(','))
+ {
+ /* Add these onto the source string
+ this way we can do all checks
+ directly on source string later on */
+ _tcscat(arg[nSrc],arg[i]);
+ nFiles--;
+ }
else if(nDes == -1)
+ {
nDes = i;
+ }
}
}
if(nFiles < 1)
{
/* There is not enough files, there has to be at least 1 */
- error_req_param_missing();
+ ConOutResPuts(STRING_ERROR_REQ_PARAM_MISSING);
+ freep (arg);
return 1;
}
if(nFiles > 2)
{
/* there is too many file names in command */
- error_too_many_parameters("");
- nErrorLevel = 1;
+ LoadString(CMD_ModuleHandle, STRING_ERROR_TOO_MANY_PARAMETERS, szMsg, RC_STRING_MAX_SIZE);
+ ConErrPrintf(szMsg,_T(""));
+ nErrorLevel = 1;
+ freep (arg);
return 1;
}
- if((nDes != -1) &&
- ((_tcschr (arg[nSrc], _T('+')) != NULL) ||
+ if(((_tcschr (arg[nSrc], _T('+')) != NULL) ||
(_tcschr (arg[nSrc], _T('*')) != NULL && _tcschr (arg[nDes], _T('*')) == NULL) ||
(IsExistingDirectory (arg[nSrc]) && (_tcschr (arg[nDes], _T('*')) == NULL && !IsExistingDirectory (arg[nDes])))
))
do
{
-
/* Set up the string that is the path to the destination */
if(nDes != -1)
{
- /* Check to make sure if they entered c:, if they do then GFPN
- return current directory even though msdn says it will return c:\ */
- if(_tcslen(arg[nDes]) == 2)
+ if(_tcslen(arg[nDes]) == 2 && arg[nDes][1] == _T(':'))
{
- if(arg[nDes][1] == _T(':'))
- {
- _tcscpy (szDestPath, arg[nDes]);
- _tcscat (szDestPath, _T("\\"));
- }
+ GetRootPath(arg[nDes],szDestPath,MAX_PATH);
}
else
/* If the user entered two file names then form the full string path*/
/* Get the full string of the path to the source file*/
if(_tcschr (arg[nSrc], _T('+')) != NULL)
{
-
_tcscpy(tmpName,_T("\0"));
/* Loop through the source file name and copy all
the chars one at a time until it gets too + */
while(TRUE)
{
-
if(!_tcsncmp (appendPointer,_T("+"),1) || !_tcsncmp (appendPointer,_T("\0"),1))
{
/* Now that the pointer is on the + we
need to go to the start of the next filename */
if(!_tcsncmp (appendPointer,_T("+"),1))
appendPointer++;
+ else
+ bDone = TRUE;
break;
+
}
+
_tcsncat(tmpName,appendPointer,1);
appendPointer++;
+
}
/* Finish the string off with a null char */
_tcsncat(tmpName,_T("\0"),1);
- /* Check to make sure if they entered c:, if they do then GFPN
- return current directory even though msdn says it will return c:\ */
+
+ 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 then one file name */
+ szTouch = _tcsstr (arg[nSrc], _T("+"));
+ if(_tcsncmp (szTouch,_T("+,,\0"),4) || nDes != -1)
+ {
+ LoadString(CMD_ModuleHandle, STRING_ERROR_INVALID_PARAM_FORMAT, szMsg, RC_STRING_MAX_SIZE);
+ ConErrPrintf(szMsg,arg[nSrc]);
+ nErrorLevel = 1;
+ freep (arg);
+ return 1;
+ }
+ bTouch = TRUE;
+ bDone = TRUE;
+ }
+
if(_tcslen(tmpName) == 2)
{
if(tmpName[1] == _T(':'))
{
- _tcscpy (szSrcPath, tmpName);
- _tcscat (szSrcPath, _T("\\"));
+
+ GetRootPath(tmpName,szSrcPath,MAX_PATH);
}
}
else
}
else
{
- /* Check to make sure if they entered c:, if they do then GFPN
- return current directory even though msdn says it will return c:\ */
- if(_tcslen(arg[nSrc]) == 2)
+ bDone = TRUE;
+ if(_tcslen(arg[nSrc]) == 2 && arg[nSrc][1] == _T(':'))
{
- if(arg[nSrc][1] == _T(':'))
- {
- _tcscpy (szSrcPath, arg[nSrc]);
- _tcscat (szSrcPath, _T("\\"));
- }
+ GetRootPath(arg[nSrc],szSrcPath,MAX_PATH);
}
else
/* Get the full path of the source file */
/* Get a list of all the files */
hFile = FindFirstFile (szSrcPath, &findBuffer);
-
+
/* We need to figure out what the name of the file in the is going to be */
if((szDestPath[_tcslen(szDestPath) - 1] == _T('*') && szDestPath[_tcslen(szDestPath) - 2] == _T('\\')) ||
else
break;
-
do
{
/* Set the override to yes each new file */
{
ConOutFormatMessage (GetLastError(), szSrcPath);
freep (arg);
- nErrorLevel = 1;
+ nErrorLevel = 1;
return 1;
}
{
ConOutFormatMessage (GetLastError (), szSrcPath);
freep (arg);
- nErrorLevel = 1;
+ nErrorLevel = 1;
return 1;
}
/* Copy over the destination path name */
}
}
-
+
/* 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(!_tcscmp (tmpSrcPath, tmpDestPath))
+ if(!bTouch && !_tcscmp (tmpSrcPath, tmpDestPath))
continue;
-
+
/* Handle any overriding / prompting that needs to be done */
- if((!(dwFlags & COPY_NO_PROMPT) && IsExistingFile (tmpDestPath)) || dwFlags & COPY_PROMPT)
+ if(((!(dwFlags & COPY_NO_PROMPT) && IsExistingFile (tmpDestPath)) || dwFlags & COPY_PROMPT) && !bTouch)
nOverwrite = Overwrite(tmpDestPath);
if(nOverwrite == PROMPT_NO || nOverwrite == PROMPT_BREAK)
continue;
if(nOverwrite == PROMPT_ALL || (nOverwrite == PROMPT_YES && bAppend))
dwFlags |= COPY_NO_PROMPT;
-
+
/* Tell weather the copy was successful or not */
- if(copy(tmpSrcPath,tmpDestPath, bAppend, dwFlags))
+ if(copy(tmpSrcPath,tmpDestPath, bAppend, dwFlags, bTouch))
{
nFiles++;
/* only print source name when more then one file */
if(_tcschr (arg[nSrc], _T('+')) != NULL || _tcschr (arg[nSrc], _T('*')) != NULL)
- ConOutPrintf("%s\n",findBuffer.cFileName);
+ ConOutPrintf(_T("%s\n"),findBuffer.cFileName);
//LoadString(CMD_ModuleHandle, STRING_MOVE_ERROR1, szMsg, RC_STRING_MAX_SIZE);
}
else
/* print out the error message */
LoadString(CMD_ModuleHandle, STRING_COPY_ERROR3, szMsg, RC_STRING_MAX_SIZE);
ConOutPrintf(szMsg);
- nErrorLevel = 1;
+ ConOutFormatMessage (GetLastError(), szSrcPath);
+ nErrorLevel = 1;
}
-
+
/* Loop through all wildcard files */
}while(FindNextFile (hFile, &findBuffer));
/* Loop through all files in src string with a + */
- }while(_tcsncmp (appendPointer,_T("\0"),1));
-
+ }while(!bDone);
+
/* print out the number of files copied */
LoadString(CMD_ModuleHandle, STRING_COPY_FILE, szMsg, RC_STRING_MAX_SIZE);
ConOutPrintf(szMsg, nFiles);
-
- CloseHandle(hFile);
- freep (arg);
+
+ CloseHandle(hFile);
+ if (arg!=NULL)
+ free(arg);
+
return 0;
}