Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencopy.c
Go to the documentation of this file.
00001 /* 00002 * COPY.C -- copy internal command. 00003 * 00004 * 00005 * History: 00006 * 00007 * 01-Aug-98 (Rob Lake z63rrl@morgan.ucs.mun.ca) 00008 * started 00009 * 00010 * 13-Aug-1998 (John P. Price) 00011 * fixed memory leak problem in copy function. 00012 * fixed copy function so it would work with wildcards in the source 00013 * 00014 * 13-Dec-1998 (Eric Kohl) 00015 * Added COPY command to CMD. 00016 * 00017 * 26-Jan-1998 (Eric Kohl) 00018 * Replaced CRT io functions by Win32 io functions. 00019 * 00020 * 27-Oct-1998 (Eric Kohl) 00021 * Disabled prompting when used in batch mode. 00022 * 00023 * 03-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>) 00024 * Remove all hardcode string to En.rc 00025 * 00026 * 13-Jul-2005 (Brandon Turner) <turnerb7@msu.edu>) 00027 * Rewrite to clean up copy and support wildcard. 00028 * 00029 * 20-Jul-2005 (Brandon Turner) <turnerb7@msu.edu>) 00030 * Add touch syntax. "copy arp.exe+,," 00031 * Copy command is now completed. 00032 */ 00033 00034 #include <precomp.h> 00035 00036 #ifdef INCLUDE_CMD_COPY 00037 00038 enum 00039 { 00040 COPY_ASCII = 0x001, /* /A */ 00041 COPY_DECRYPT = 0x004, /* /D */ 00042 COPY_VERIFY = 0x008, /* /V : Dummy, Never will be Impleneted */ 00043 COPY_SHORTNAME = 0x010, /* /N : Dummy, Never will be Impleneted */ 00044 COPY_NO_PROMPT = 0x020, /* /Y */ 00045 COPY_PROMPT = 0x040, /* /-Y */ 00046 COPY_RESTART = 0x080, /* /Z */ 00047 COPY_BINARY = 0x100, /* /B */ 00048 }; 00049 00050 INT 00051 copy(TCHAR source[MAX_PATH], 00052 TCHAR dest[MAX_PATH], 00053 INT append, 00054 DWORD lpdwFlags, 00055 BOOL bTouch) 00056 { 00057 FILETIME srctime,NewFileTime; 00058 HANDLE hFileSrc; 00059 HANDLE hFileDest; 00060 LPBYTE buffer; 00061 DWORD dwAttrib; 00062 DWORD dwRead; 00063 DWORD dwWritten; 00064 BOOL bEof = FALSE; 00065 TCHAR TrueDest[MAX_PATH]; 00066 TCHAR TempSrc[MAX_PATH]; 00067 TCHAR * FileName; 00068 SYSTEMTIME CurrentTime; 00069 00070 /* Check Breaker */ 00071 if(CheckCtrlBreak(BREAK_INPUT)) 00072 return 0; 00073 00074 TRACE ("checking mode\n"); 00075 00076 if(bTouch) 00077 { 00078 hFileSrc = CreateFile (source, GENERIC_WRITE, FILE_SHARE_READ, 00079 NULL, OPEN_EXISTING, 0, NULL); 00080 if (hFileSrc == INVALID_HANDLE_VALUE) 00081 { 00082 ConOutResPrintf(STRING_COPY_ERROR1, source); 00083 nErrorLevel = 1; 00084 return 0; 00085 } 00086 00087 GetSystemTime(&CurrentTime); 00088 SystemTimeToFileTime(&CurrentTime, &NewFileTime); 00089 if(SetFileTime(hFileSrc,(LPFILETIME) NULL, (LPFILETIME) NULL, &NewFileTime)) 00090 { 00091 CloseHandle(hFileSrc); 00092 nErrorLevel = 1; 00093 return 1; 00094 00095 } 00096 else 00097 { 00098 CloseHandle(hFileSrc); 00099 return 0; 00100 } 00101 } 00102 00103 dwAttrib = GetFileAttributes (source); 00104 00105 hFileSrc = CreateFile (source, GENERIC_READ, FILE_SHARE_READ, 00106 NULL, OPEN_EXISTING, 0, NULL); 00107 if (hFileSrc == INVALID_HANDLE_VALUE) 00108 { 00109 ConOutResPrintf(STRING_COPY_ERROR1, source); 00110 nErrorLevel = 1; 00111 return 0; 00112 } 00113 00114 TRACE ("getting time\n"); 00115 00116 GetFileTime (hFileSrc, &srctime, NULL, NULL); 00117 00118 TRACE ("copy: flags has %s\n", 00119 lpdwFlags & COPY_ASCII ? "ASCII" : "BINARY"); 00120 00121 /* Check to see if /D or /Z are true, if so we need a middle 00122 man to copy the file too to allow us to use CopyFileEx later */ 00123 if(lpdwFlags & COPY_DECRYPT) 00124 { 00125 GetEnvironmentVariable(_T("TEMP"),TempSrc,MAX_PATH); 00126 _tcscat(TempSrc,_T("\\")); 00127 FileName = _tcsrchr(source,_T('\\')); 00128 FileName++; 00129 _tcscat(TempSrc,FileName); 00130 /* This is needed to be on the end to prevent an error 00131 if the user did "copy /D /Z foo bar then it would be copied 00132 too %TEMP%\foo here and when %TEMP%\foo when it sets it up 00133 for COPY_RESTART, this would mean it is copying to itself 00134 which would error when it tried to open the handles for ReadFile 00135 and WriteFile */ 00136 _tcscat(TempSrc,_T(".decrypt")); 00137 if(!CopyFileEx(source, TempSrc, NULL, NULL, FALSE, COPY_FILE_ALLOW_DECRYPTED_DESTINATION)) 00138 { 00139 nErrorLevel = 1; 00140 return 0; 00141 } 00142 _tcscpy(source, TempSrc); 00143 } 00144 00145 00146 if(lpdwFlags & COPY_RESTART) 00147 { 00148 _tcscpy(TrueDest, dest); 00149 GetEnvironmentVariable(_T("TEMP"),dest,MAX_PATH); 00150 _tcscat(dest,_T("\\")); 00151 FileName = _tcsrchr(TrueDest,_T('\\')); 00152 FileName++; 00153 _tcscat(dest,FileName); 00154 } 00155 00156 00157 if (!IsExistingFile (dest)) 00158 { 00159 TRACE ("opening/creating\n"); 00160 hFileDest = 00161 CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 00162 } 00163 else if (!append) 00164 { 00165 TRACE ("SetFileAttributes (%s, FILE_ATTRIBUTE_NORMAL);\n", debugstr_aw(dest)); 00166 SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL); 00167 00168 TRACE ("DeleteFile (%s);\n", debugstr_aw(dest)); 00169 DeleteFile (dest); 00170 00171 hFileDest = CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 00172 } 00173 else 00174 { 00175 LONG lFilePosHigh = 0; 00176 00177 if (!_tcscmp (dest, source)) 00178 { 00179 CloseHandle (hFileSrc); 00180 return 0; 00181 } 00182 00183 TRACE ("opening/appending\n"); 00184 SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL); 00185 00186 hFileDest = 00187 CreateFile (dest, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 00188 00189 /* Move to end of file to start writing */ 00190 SetFilePointer (hFileDest, 0, &lFilePosHigh,FILE_END); 00191 } 00192 00193 00194 if (hFileDest == INVALID_HANDLE_VALUE) 00195 { 00196 CloseHandle (hFileSrc); 00197 ConOutResPuts(STRING_ERROR_PATH_NOT_FOUND); 00198 nErrorLevel = 1; 00199 return 0; 00200 } 00201 00202 /* A page-aligned buffer usually give more speed */ 00203 buffer = (LPBYTE)VirtualAlloc(NULL, BUFF_SIZE, MEM_COMMIT, PAGE_READWRITE); 00204 if (buffer == NULL) 00205 { 00206 CloseHandle (hFileDest); 00207 CloseHandle (hFileSrc); 00208 ConOutResPuts(STRING_ERROR_OUT_OF_MEMORY); 00209 nErrorLevel = 1; 00210 return 0; 00211 } 00212 00213 do 00214 { 00215 ReadFile (hFileSrc, buffer, BUFF_SIZE, &dwRead, NULL); 00216 if (lpdwFlags & COPY_ASCII) 00217 { 00218 LPBYTE pEof = memchr(buffer, 0x1A, dwRead); 00219 if (pEof != NULL) 00220 { 00221 bEof = TRUE; 00222 dwRead = pEof-buffer+1; 00223 break; 00224 } 00225 } 00226 00227 if (dwRead == 0) 00228 break; 00229 00230 WriteFile (hFileDest, buffer, dwRead, &dwWritten, NULL); 00231 if (dwWritten != dwRead || CheckCtrlBreak(BREAK_INPUT)) 00232 { 00233 ConOutResPuts(STRING_COPY_ERROR3); 00234 00235 VirtualFree (buffer, 0, MEM_RELEASE); 00236 CloseHandle (hFileDest); 00237 CloseHandle (hFileSrc); 00238 nErrorLevel = 1; 00239 return 0; 00240 } 00241 } 00242 while (!bEof); 00243 00244 TRACE ("setting time\n"); 00245 SetFileTime (hFileDest, &srctime, NULL, NULL); 00246 00247 if ((lpdwFlags & COPY_ASCII) && !bEof) 00248 { 00249 /* we're dealing with ASCII files! */ 00250 buffer[0] = 0x1A; 00251 TRACE ("appending ^Z\n"); 00252 WriteFile (hFileDest, buffer, sizeof(CHAR), &dwWritten, NULL); 00253 } 00254 00255 VirtualFree (buffer, 0, MEM_RELEASE); 00256 CloseHandle (hFileDest); 00257 CloseHandle (hFileSrc); 00258 00259 TRACE ("setting mode\n"); 00260 SetFileAttributes (dest, dwAttrib); 00261 00262 /* Now finish off the copy if needed with CopyFileEx */ 00263 if(lpdwFlags & COPY_RESTART) 00264 { 00265 if(!CopyFileEx(dest, TrueDest, NULL, NULL, FALSE, COPY_FILE_RESTARTABLE)) 00266 { 00267 nErrorLevel = 1; 00268 DeleteFile(dest); 00269 return 0; 00270 } 00271 /* Take care of file in the temp folder */ 00272 DeleteFile(dest); 00273 00274 } 00275 00276 if(lpdwFlags & COPY_DECRYPT) 00277 DeleteFile(TempSrc); 00278 00279 return 1; 00280 } 00281 00282 00283 static INT CopyOverwrite (LPTSTR fn) 00284 { 00285 /*ask the user if they want to override*/ 00286 INT res; 00287 ConOutResPrintf(STRING_COPY_HELP1, fn); 00288 res = FilePromptYNA (0); 00289 return res; 00290 } 00291 00292 /* The following lines of copy were written by someone else 00293 (most likely Eric Kohl) and it was taken from ren.c */ 00294 static void 00295 BuildFileName( 00296 LPTSTR pszSource, 00297 LPTSTR pszTarget, 00298 LPTSTR pszOutput) 00299 { 00300 /* build destination file name */ 00301 while (*pszTarget != 0) 00302 { 00303 if (*pszTarget == _T('*')) 00304 { 00305 pszTarget++; 00306 while ((*pszSource != 0) && (*pszSource != *pszTarget)) 00307 { 00308 *pszOutput++ = *pszSource++; 00309 } 00310 } 00311 else if (*pszTarget == _T('?')) 00312 { 00313 pszTarget++; 00314 if (*pszSource != 0) 00315 { 00316 *pszOutput++ = *pszSource++; 00317 } 00318 } 00319 else 00320 { 00321 *pszOutput++ = *pszTarget++; 00322 if (*pszSource != 0) 00323 pszSource++; 00324 } 00325 } 00326 00327 *pszOutput = 0; 00328 } 00329 00330 INT cmd_copy(LPTSTR param) 00331 { 00332 LPTSTR *arg; 00333 INT argc, i, nFiles, nOverwrite = 0, nSrc = -1, nDes = -1; 00334 /* this is the path up to the folder of the src and dest ie C:\windows\ */ 00335 TCHAR szDestPath[MAX_PATH]; 00336 TCHAR szSrcPath[MAX_PATH]; 00337 DWORD dwFlags = 0; 00338 /* If this is the type of copy where we are adding files */ 00339 BOOL bAppend = FALSE; 00340 WIN32_FIND_DATA findBuffer; 00341 HANDLE hFile = NULL; 00342 BOOL bTouch = FALSE; 00343 /* Used when something like "copy c*.exe d*.exe" during the process of 00344 figuring out the new name */ 00345 /* Pointer to keep track of how far through the append input(file1+file2+file3) we are */ 00346 TCHAR * appendPointer = _T("\0"); 00347 /* The full path to src and dest. This has drive letter, folders, and filename */ 00348 TCHAR tmpDestPath[MAX_PATH]; 00349 TCHAR tmpSrcPath[MAX_PATH]; 00350 /* A bool on weather or not the destination name will be taking from the input */ 00351 BOOL bSrcName = FALSE; 00352 /* Seems like a waste but it is a pointer used to copy from input to PreserveName */ 00353 TCHAR * UseThisName; 00354 /* for CMDCOPY env */ 00355 TCHAR *evar; 00356 int size; 00357 TCHAR * szTouch; 00358 BOOL bHasWildcard, bDone = FALSE, bMoreFiles = FALSE; 00359 BOOL bMultipleSource = FALSE, bMultipleDest = FALSE; 00360 00361 00362 /* Show help/usage info */ 00363 if (!_tcsncmp(param, _T("/?"), 2)) 00364 { 00365 ConOutResPaging(TRUE, STRING_COPY_HELP2); 00366 return 0; 00367 } 00368 00369 nErrorLevel = 0; 00370 00371 /* Get the envor value if it exists */ 00372 evar = cmd_alloc(512 * sizeof(TCHAR)); 00373 if (evar == NULL) 00374 size = 0; 00375 else 00376 size = GetEnvironmentVariable (_T("COPYCMD"), evar, 512); 00377 00378 if (size > 512) 00379 { 00380 evar = cmd_realloc(evar,size * sizeof(TCHAR) ); 00381 if (evar!=NULL) 00382 size = GetEnvironmentVariable (_T("COPYCMD"), evar, size); 00383 else 00384 size=0; 00385 } 00386 00387 /* check see if we did get any env variable */ 00388 if (size != 0) 00389 { 00390 int t = 0; 00391 00392 /* scan and set the flags */ 00393 for (t = 0; t < size; t++) 00394 { 00395 if (_tcsncicmp(_T("/A"),&evar[t],2) == 0) 00396 { 00397 dwFlags |=COPY_ASCII; 00398 t++; 00399 } 00400 else if (_tcsncicmp(_T("/B"),&evar[t],2) == 0) 00401 { 00402 dwFlags |= COPY_BINARY; 00403 t++; 00404 } 00405 else if (_tcsncicmp(_T("/D"),&evar[t],2) == 0) 00406 { 00407 dwFlags |= COPY_DECRYPT; 00408 t++; 00409 } 00410 else if (_tcsncicmp(_T("/V"),&evar[t],2) == 0) 00411 { 00412 dwFlags |= COPY_VERIFY; 00413 t++; 00414 } 00415 else if (_tcsncicmp(_T("/N"),&evar[t],2) == 0) 00416 { 00417 dwFlags |= COPY_SHORTNAME; 00418 t++; 00419 } 00420 else if (_tcsncicmp(_T("/Y"),&evar[t],2) == 0) 00421 { 00422 dwFlags |= COPY_NO_PROMPT; 00423 t++; 00424 } 00425 else if (_tcsncicmp(_T("/-Y"),&evar[t],3) == 0) 00426 { 00427 dwFlags |= COPY_PROMPT; 00428 t+=2; 00429 } 00430 else if (_tcsncicmp(_T("/Z"),&evar[t],2) == 0) 00431 { 00432 dwFlags |= COPY_PROMPT; 00433 t++; 00434 } 00435 } 00436 } 00437 cmd_free(evar); 00438 00439 00440 /* Split the user input into array */ 00441 arg = split(param, &argc, FALSE, TRUE); 00442 nFiles = argc; 00443 00444 /* Read switches and count files */ 00445 for (i = 0; i < argc; i++) 00446 { 00447 if (*arg[i] == _T('/')) 00448 { 00449 if (_tcslen(arg[i]) >= 2) 00450 { 00451 switch (_totupper(arg[i][1])) 00452 { 00453 case _T('A'): 00454 dwFlags |= COPY_ASCII; 00455 break; 00456 00457 case _T('B'): 00458 dwFlags |= COPY_BINARY; 00459 break; 00460 00461 case _T('D'): 00462 dwFlags |= COPY_DECRYPT; 00463 break; 00464 00465 case _T('V'): 00466 dwFlags |= COPY_VERIFY; 00467 break; 00468 00469 case _T('N'): 00470 dwFlags |= COPY_SHORTNAME; 00471 break; 00472 00473 case _T('Y'): 00474 dwFlags |= COPY_NO_PROMPT; 00475 dwFlags &= ~COPY_PROMPT; 00476 break; 00477 00478 case _T('-'): 00479 if(_tcslen(arg[i]) >= 3) 00480 if(_totupper(arg[i][2]) == _T('Y')) 00481 { 00482 dwFlags &= ~COPY_NO_PROMPT; 00483 dwFlags |= COPY_PROMPT; 00484 } 00485 00486 break; 00487 00488 case _T('Z'): 00489 dwFlags |= COPY_RESTART; 00490 break; 00491 00492 default: 00493 /* Invalid switch */ 00494 ConOutResPrintf(STRING_ERROR_INVALID_SWITCH, _totupper(arg[i][1])); 00495 nErrorLevel = 1; 00496 freep (arg); 00497 return 1; 00498 break; 00499 } 00500 } 00501 /* If it was a switch, subtract from total arguments */ 00502 nFiles--; 00503 } 00504 else 00505 { 00506 /* If it isn't a switch then it is the source or destination */ 00507 if (nSrc == -1) 00508 { 00509 nSrc = i; 00510 } 00511 else if (*arg[i] == _T('+')) 00512 { 00513 /* Next file should be appended */ 00514 bMoreFiles = TRUE; 00515 nFiles -= 1; 00516 } 00517 else if (bMoreFiles) 00518 { 00519 /* Add this file to the source string 00520 this way we can do all checks 00521 directly on source string later on */ 00522 TCHAR * ptr; 00523 int length = (_tcslen(arg[nSrc]) + _tcslen(arg[i]) + 2) * sizeof(TCHAR); 00524 ptr = cmd_alloc(length); 00525 if (ptr) 00526 { 00527 _tcscpy(ptr, arg[nSrc]); 00528 _tcscat(ptr, _T("|")); 00529 _tcscat(ptr, arg[i]); 00530 cmd_free(arg[nSrc]); 00531 arg[nSrc] = ptr; 00532 nFiles -= 1; 00533 } 00534 00535 bMoreFiles = FALSE; 00536 } 00537 else if(nDes == -1) 00538 { 00539 nDes = i; 00540 } 00541 } 00542 } 00543 00544 /* keep quiet within batch files */ 00545 if (bc != NULL) 00546 { 00547 dwFlags |= COPY_NO_PROMPT; 00548 dwFlags &= ~COPY_PROMPT; 00549 } 00550 00551 if (nFiles < 1) 00552 { 00553 /* There are not enough files, there has to be at least 1 */ 00554 ConOutResPuts(STRING_ERROR_REQ_PARAM_MISSING); 00555 freep(arg); 00556 return 1; 00557 } 00558 00559 if (nFiles > 2) 00560 { 00561 /* There are too many file names in command */ 00562 ConErrResPrintf(STRING_ERROR_TOO_MANY_PARAMETERS,_T("")); 00563 nErrorLevel = 1; 00564 freep(arg); 00565 return 1; 00566 } 00567 00568 if ((_tcschr(arg[nSrc], _T('|')) != NULL) || 00569 (_tcschr(arg[nSrc], _T('*')) != NULL) || 00570 (_tcschr(arg[nSrc], _T('?')) != NULL) || 00571 IsExistingDirectory(arg[nSrc])) 00572 { 00573 bMultipleSource = TRUE; 00574 } 00575 00576 /* Reusing the number of files variable */ 00577 nFiles = 0; 00578 00579 /* Check if no destination argument is passed */ 00580 if (nDes == -1) 00581 { 00582 /* If no destination was entered then just use 00583 the current directory as the destination */ 00584 GetCurrentDirectory(MAX_PATH, szDestPath); 00585 } 00586 else 00587 { 00588 /* Check if the destination is 'x:' */ 00589 if ((arg[nDes][1] == _T(':')) && (arg[nDes][2] == _T('\0'))) 00590 { 00591 GetRootPath(arg[nDes], szDestPath, MAX_PATH); 00592 } 00593 else 00594 { 00595 /* If the user entered two file names then form the full string path */ 00596 GetFullPathName(arg[nDes], MAX_PATH, szDestPath, NULL); 00597 } 00598 00599 /* Make sure there is an ending slash to the path if the dest is a folder */ 00600 if ((_tcschr(szDestPath, _T('*')) == NULL) && 00601 IsExistingDirectory(szDestPath)) 00602 { 00603 bMultipleDest = TRUE; 00604 if (szDestPath[_tcslen(szDestPath) - 1] != _T('\\')) 00605 _tcscat(szDestPath, _T("\\")); 00606 } 00607 00608 /* Check if the destination uses wildcards */ 00609 if ((_tcschr(arg[nDes], _T('*')) != NULL) || 00610 (_tcschr(arg[nDes], _T('?')) != NULL)) 00611 { 00612 bMultipleDest = TRUE; 00613 } 00614 } 00615 00616 if (nDes != -1) /* you can only append files when there is a destination */ 00617 { 00618 if (bMultipleSource && !bMultipleDest) 00619 { 00620 /* We have multiple source files, but not multiple destination 00621 files. This means we are appending the soruce files. */ 00622 bAppend = TRUE; 00623 if (_tcschr(arg[nSrc], _T('|')) != NULL) 00624 appendPointer = arg[nSrc]; 00625 } 00626 } 00627 00628 /* Save the name the user entered */ 00629 UseThisName = _tcsrchr(szDestPath,_T('\\')); 00630 if (UseThisName) 00631 { 00632 /* Split the name from the path */ 00633 *UseThisName++ = _T('\0'); 00634 00635 /* Check if the dest path ends with '\*' or '\' */ 00636 if (((UseThisName[0] == _T('*')) && (UseThisName[1] == _T('\0'))) || 00637 (UseThisName[0] == _T('\0'))) 00638 { 00639 /* In this case we will be using the same name as the source file 00640 for the destination file because destination is a folder */ 00641 bSrcName = TRUE; 00642 UseThisName = NULL; 00643 } 00644 } 00645 else 00646 { 00647 /* Something's seriously wrong! */ 00648 UseThisName = szDestPath; 00649 } 00650 00651 do 00652 { 00653 /* Get the full string of the path to the source file */ 00654 if (_tcschr(arg[nSrc], _T('|')) != NULL) 00655 { 00656 /* Reset the source path */ 00657 szSrcPath[0] = _T('\0'); 00658 00659 /* Loop through the source file name and copy all 00660 the chars one at a time until it gets too + */ 00661 while(TRUE) 00662 { 00663 if (appendPointer[0] == _T('|')) 00664 { 00665 /* Skip the | and go to the next file name */ 00666 appendPointer++; 00667 break; 00668 } 00669 else if (appendPointer[0] == _T('\0')) 00670 { 00671 bDone = TRUE; 00672 break; 00673 } 00674 00675 _tcsncat(szSrcPath, appendPointer, 1); 00676 appendPointer++; 00677 } 00678 00679 if (_tcschr(arg[nSrc], _T(',')) != NULL) 00680 { 00681 /* Only time there is a , in the source is when they are using touch 00682 Cant have a destination and can only have on ,, at the end of the string 00683 Cant have more then one file name */ 00684 szTouch = _tcsstr(arg[nSrc], _T("|")); 00685 if (_tcsncmp(szTouch,_T("|,,\0"), 4) || (nDes != -1)) 00686 { 00687 ConErrResPrintf(STRING_ERROR_INVALID_PARAM_FORMAT,arg[nSrc]); 00688 nErrorLevel = 1; 00689 freep (arg); 00690 return 1; 00691 } 00692 bTouch = TRUE; 00693 bDone = TRUE; 00694 } 00695 } 00696 else 00697 { 00698 bDone = TRUE; 00699 _tcscpy(szSrcPath, arg[nSrc]); 00700 } 00701 00702 /* "x:" is not a valid source path format. */ 00703 if ((szSrcPath[1] == _T(':')) && (szSrcPath[2] == _T('\0'))) 00704 { 00705 ConOutPrintf(_T("%s\n"), szSrcPath); 00706 ConOutFormatMessage(ERROR_FILE_NOT_FOUND, szSrcPath); 00707 nErrorLevel = 1; 00708 break; 00709 } 00710 00711 00712 /* From this point on, we can assume that the shortest path is 3 letters long 00713 and that would be [DriveLetter]:\ */ 00714 00715 /* Check if the path has a wildcard */ 00716 bHasWildcard = (_tcschr(szSrcPath, _T('*')) != NULL); 00717 00718 /* If there is no * in the path name and it is a folder then we will 00719 need to add a wildcard to the pathname so FindFirstFile comes up 00720 with all the files in that folder */ 00721 if (!bHasWildcard && IsExistingDirectory(szSrcPath)) 00722 { 00723 /* If it doesnt have a \ at the end already then on needs to be added */ 00724 if (szSrcPath[_tcslen(szSrcPath) - 1] != _T('\\')) 00725 _tcscat(szSrcPath, _T("\\")); 00726 _tcscat(szSrcPath, _T("*")); 00727 bHasWildcard = TRUE; 00728 } 00729 00730 /* If the path ends with '\' add a wildcard at the end */ 00731 if (szSrcPath[_tcslen(szSrcPath) - 1] == _T('\\')) 00732 { 00733 _tcscat(szSrcPath, _T("*")); 00734 bHasWildcard = TRUE; 00735 } 00736 00737 /* Get a list of all the files */ 00738 hFile = FindFirstFile(szSrcPath, &findBuffer); 00739 00740 /* If it couldnt open the file handle, print out the error */ 00741 if (hFile == INVALID_HANDLE_VALUE) 00742 { 00743 /* only print source name when more then one file */ 00744 if (bMultipleSource) 00745 ConOutPrintf(_T("%s\n"), szSrcPath); 00746 00747 ConOutFormatMessage(GetLastError(), szSrcPath); 00748 freep(arg); 00749 nErrorLevel = 1; 00750 return 1; 00751 } 00752 00753 /* Strip the paths back to the folder they are in */ 00754 for (i = (_tcslen(szSrcPath) - 1); i > -1; i--) 00755 if (szSrcPath[i] != _T('\\')) 00756 szSrcPath[i] = _T('\0'); 00757 else 00758 break; 00759 00760 do 00761 { 00762 /* Check Breaker */ 00763 if (CheckCtrlBreak(BREAK_INPUT)) 00764 { 00765 freep(arg); 00766 return 1; 00767 } 00768 00769 /* Set the override to yes each new file */ 00770 nOverwrite = 1; 00771 00772 /* Ignore the . and .. files */ 00773 if (!_tcscmp(findBuffer.cFileName, _T(".")) || 00774 !_tcscmp(findBuffer.cFileName, _T("..")) || 00775 findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 00776 { 00777 continue; 00778 } 00779 00780 /* Copy the base folder over to a tmp string */ 00781 _tcscpy(tmpDestPath, szDestPath); 00782 _tcscat(tmpDestPath, _T("\\")); 00783 00784 /* Can't put a file into a folder that isnt there */ 00785 if (_tcscmp(tmpDestPath, _T("\\\\.\\")) && 00786 !IsExistingDirectory(tmpDestPath)) 00787 { 00788 ConOutFormatMessage(GetLastError(), szSrcPath); 00789 freep(arg); 00790 nErrorLevel = 1; 00791 return 1; 00792 } 00793 00794 /* Copy over the destination path name */ 00795 if (bSrcName) 00796 _tcscat(tmpDestPath, findBuffer.cFileName); 00797 else 00798 { 00799 /* If there is no wildcard you can use the name the user entered */ 00800 if ((_tcschr(UseThisName, _T('*')) == NULL) && 00801 (_tcschr(UseThisName, _T('?')) == NULL)) 00802 { 00803 _tcscat(tmpDestPath, UseThisName); 00804 } 00805 else 00806 { 00807 TCHAR DoneFile[MAX_PATH]; 00808 00809 BuildFileName(findBuffer.cFileName, 00810 UseThisName, 00811 DoneFile); 00812 00813 00814 /* Add the filename to the tmp string path */ 00815 _tcscat(tmpDestPath, DoneFile); 00816 } 00817 } 00818 00819 /* Build the string path to the source file */ 00820 _tcscpy(tmpSrcPath,szSrcPath); 00821 _tcscat (tmpSrcPath, findBuffer.cFileName); 00822 00823 /* Check to see if the file is the same file */ 00824 if(!bTouch && !_tcscmp(tmpSrcPath, tmpDestPath)) 00825 { 00826 ConOutResPrintf(STRING_COPY_ERROR2); 00827 00828 nErrorLevel = 1; 00829 break; 00830 } 00831 00832 /* only print source name when more then one file */ 00833 if (bMultipleSource) 00834 ConOutPrintf(_T("%s\n"), tmpSrcPath); 00835 00836 /* Handle any overriding / prompting that needs to be done */ 00837 if (((!(dwFlags & COPY_NO_PROMPT) && IsExistingFile (tmpDestPath)) || dwFlags & COPY_PROMPT) && !bTouch) 00838 nOverwrite = CopyOverwrite(tmpDestPath); 00839 if (nOverwrite == PROMPT_NO || nOverwrite == PROMPT_BREAK) 00840 continue; 00841 if (nOverwrite == PROMPT_ALL || (nOverwrite == PROMPT_YES && bAppend)) 00842 dwFlags |= COPY_NO_PROMPT; 00843 00844 /* Tell weather the copy was successful or not */ 00845 if(copy(tmpSrcPath,tmpDestPath, bAppend, dwFlags, bTouch)) 00846 { 00847 nFiles++; 00848 //LoadString(CMD_ModuleHandle, STRING_MOVE_ERROR1, szMsg, RC_STRING_MAX_SIZE); 00849 } 00850 else 00851 { 00852 /* print out the error message */ 00853 ConOutResPrintf(STRING_COPY_ERROR3); 00854 ConOutFormatMessage (GetLastError(), szSrcPath); 00855 nErrorLevel = 1; 00856 } 00857 00858 /* Loop through all wildcard files */ 00859 } while (FindNextFile(hFile, &findBuffer)); 00860 00861 /* Loop through all files in src string with a + */ 00862 } while(!bDone); 00863 00864 /* print out the number of files copied */ 00865 ConOutResPrintf(STRING_COPY_FILE, bAppend ? 1 : nFiles); 00866 00867 if (hFile) FindClose(hFile); 00868 00869 if (arg != NULL) 00870 freep(arg); 00871 00872 return 0; 00873 } 00874 00875 #endif /* INCLUDE_CMD_COPY */ Generated on Sun May 27 2012 04:18:11 for ReactOS by
1.7.6.1
|