Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenreplace.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Command shell 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: base/shell/cmd/replace.c 00005 * PURPOSE: Implements 'replace' cmd command 00006 * PROGRAMMERS: Samuel Erdtman (samuel@erdtman.se) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include <precomp.h> 00012 00013 #ifdef INCLUDE_CMD_REPLACE 00014 00015 /* GLOBALS *******************************************************************/ 00016 00017 enum 00018 { 00019 REPLACE_ADD = 0x001, /* /A */ 00020 REPLACE_CONFIRM = 0x002, /* /P */ 00021 REPLACE_READ_ONLY = 0x004, /* /R */ 00022 REPLACE_SUBDIR = 0x008, /* /S */ 00023 REPLACE_DISK = 0x010, /* /W */ 00024 REPLACE_UPDATE = 0x020, /* /U */ 00025 }; 00026 00027 /* FUNCTIONS *****************************************************************/ 00028 00029 /*just makes a print out if there is a problem with the switches*/ 00030 void invalid_switch(LPTSTR is) 00031 { 00032 ConOutResPrintf(STRING_REPLACE_ERROR1,is); 00033 ConOutResPaging(TRUE,STRING_REPLACE_HELP3); 00034 } 00035 00036 /*retrives the pathe dependen om the input file name*/ 00037 void getPath(TCHAR* out, LPTSTR in) 00038 { 00039 if(_tcslen(in) == 2 && in[1] == _T(':')) 00040 GetRootPath(in,out,MAX_PATH); 00041 else 00042 GetFullPathName (in, MAX_PATH, out, NULL); 00043 } 00044 00045 00046 /*makes the replace*/ 00047 INT replace(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], DWORD dwFlags, BOOL *doMore) 00048 { 00049 TCHAR d[MAX_PATH]; 00050 TCHAR s[MAX_PATH]; 00051 HANDLE hFileSrc, hFileDest; 00052 DWORD dwAttrib, dwRead, dwWritten; 00053 LPBYTE buffer; 00054 BOOL bEof = FALSE; 00055 FILETIME srcCreationTime, destCreationTime, srcLastAccessTime, destLastAccessTime; 00056 FILETIME srcLastWriteTime, destLastWriteTime; 00057 GetPathCase(source, s); 00058 GetPathCase(dest, d); 00059 s[0] = _totupper(s[0]); 00060 d[0] = _totupper(d[0]); 00061 // ConOutPrintf(_T("old-src: %s\n"), s); 00062 // ConOutPrintf(_T("old-dest: %s\n"), d); 00063 // ConOutPrintf(_T("src: %s\n"), source); 00064 // ConOutPrintf(_T("dest: %s\n"), dest); 00065 00066 /* Open up the sourcefile */ 00067 hFileSrc = CreateFile (source, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, 0, NULL); 00068 if (hFileSrc == INVALID_HANDLE_VALUE) 00069 { 00070 ConOutResPrintf(STRING_COPY_ERROR1, source); 00071 return 0; 00072 } 00073 00074 /* Get the time from source file to be used in the comparison with 00075 dest time if update switch is set */ 00076 GetFileTime (hFileSrc, &srcCreationTime, &srcLastAccessTime, &srcLastWriteTime); 00077 00078 /* Retrieve the source attributes so that they later on can be 00079 inserted in to the destination */ 00080 dwAttrib = GetFileAttributes (source); 00081 00082 if(IsExistingFile (dest)) 00083 { 00084 /* Resets the attributes to avoid probles with read only files, 00085 checks for read only has been made earlier */ 00086 SetFileAttributes(dest,FILE_ATTRIBUTE_NORMAL); 00087 /* Is the update flas set? The time has to be controled so that 00088 only older files are replaced */ 00089 if(dwFlags & REPLACE_UPDATE) 00090 { 00091 /* Read destination time */ 00092 hFileDest = CreateFile(dest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 00093 0, NULL); 00094 00095 if (hFileSrc == INVALID_HANDLE_VALUE) 00096 { 00097 ConOutResPrintf(STRING_COPY_ERROR1, dest); 00098 return 0; 00099 } 00100 00101 /* Compare time */ 00102 GetFileTime (hFileDest, &destCreationTime, &destLastAccessTime, &destLastWriteTime); 00103 if(!((srcLastWriteTime.dwHighDateTime > destLastWriteTime.dwHighDateTime) || 00104 ( srcLastWriteTime.dwHighDateTime == destLastWriteTime.dwHighDateTime && 00105 srcLastWriteTime.dwLowDateTime > destLastWriteTime.dwLowDateTime))) 00106 { 00107 CloseHandle (hFileSrc); 00108 CloseHandle (hFileDest); 00109 return 0; 00110 } 00111 CloseHandle (hFileDest); 00112 } 00113 /* Delete the old file */ 00114 DeleteFile (dest); 00115 } 00116 00117 /* Check confirm flag, and take appropriate action */ 00118 if(dwFlags & REPLACE_CONFIRM) 00119 { 00120 /* Output depending on add flag */ 00121 if(dwFlags & REPLACE_ADD) 00122 ConOutResPrintf(STRING_REPLACE_HELP9, dest); 00123 else 00124 ConOutResPrintf(STRING_REPLACE_HELP10, dest); 00125 if( !FilePromptYNA (0)) 00126 return 0; 00127 } 00128 00129 /* Output depending on add flag */ 00130 if(dwFlags & REPLACE_ADD) 00131 ConOutResPrintf(STRING_REPLACE_HELP11, dest); 00132 else 00133 ConOutResPrintf(STRING_REPLACE_HELP5, dest); 00134 00135 /* Make sure source and destination is not the same */ 00136 if(!_tcscmp(s, d)) 00137 { 00138 ConOutResPaging(TRUE, STRING_REPLACE_ERROR7); 00139 CloseHandle (hFileSrc); 00140 *doMore = FALSE; 00141 return 0; 00142 } 00143 00144 /* Open destination file to write to */ 00145 hFileDest = CreateFile (dest, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); 00146 if (hFileDest == INVALID_HANDLE_VALUE) 00147 { 00148 CloseHandle (hFileSrc); 00149 ConOutResPaging(TRUE, STRING_REPLACE_ERROR7); 00150 *doMore = FALSE; 00151 return 0; 00152 } 00153 00154 /* Get buffer for the copy process */ 00155 buffer = (LPBYTE)VirtualAlloc(NULL, BUFF_SIZE, MEM_COMMIT, PAGE_READWRITE); 00156 if (buffer == NULL) 00157 { 00158 CloseHandle (hFileDest); 00159 CloseHandle (hFileSrc); 00160 ConOutResPaging(TRUE, STRING_ERROR_OUT_OF_MEMORY); 00161 return 0; 00162 } 00163 00164 /* Put attribute and time to the new destination file */ 00165 SetFileAttributes (dest, dwAttrib); 00166 SetFileTime (hFileDest, &srcCreationTime, &srcLastAccessTime, &srcLastWriteTime); 00167 do 00168 { 00169 /* Read data from source */ 00170 ReadFile (hFileSrc, buffer, BUFF_SIZE, &dwRead, NULL); 00171 00172 /* Done? */ 00173 if (dwRead == 0) 00174 break; 00175 00176 /* Write to destination file */ 00177 WriteFile (hFileDest, buffer, dwRead, &dwWritten, NULL); 00178 00179 /* Done! or ctrl break! */ 00180 if (dwWritten != dwRead || CheckCtrlBreak(BREAK_INPUT)) 00181 { 00182 ConOutResPuts(STRING_COPY_ERROR3); 00183 cmd_free (buffer); 00184 CloseHandle (hFileDest); 00185 CloseHandle (hFileSrc); 00186 nErrorLevel = 1; 00187 return 0; 00188 } 00189 } 00190 while (!bEof); 00191 00192 /* Return memory and close files */ 00193 VirtualFree (buffer, 0, MEM_RELEASE); 00194 CloseHandle (hFileDest); 00195 CloseHandle (hFileSrc); 00196 00197 /* Return one file replaced */ 00198 return 1; 00199 } 00200 00201 00202 /* Function to iterate over source files and call replace for each of them */ 00203 INT recReplace(DWORD dwFlags, TCHAR szSrcPath[MAX_PATH], TCHAR szDestPath[MAX_PATH], BOOL *doMore) 00204 { 00205 TCHAR tmpDestPath[MAX_PATH], tmpSrcPath[MAX_PATH]; 00206 INT filesReplaced=0; 00207 INT_PTR i; 00208 DWORD dwAttrib = 0; 00209 HANDLE hFile; 00210 WIN32_FIND_DATA findBuffer; 00211 00212 /* Get file handel to the sourcefile(s) */ 00213 hFile = FindFirstFile (szSrcPath, &findBuffer); 00214 00215 /* Strip the paths back to the folder they are in, so that the diffrent 00216 filenames can be added if more than one */ 00217 for(i = (_tcslen(szSrcPath) - 1); i > -1; i--) 00218 if(szSrcPath[i] != _T('\\')) 00219 szSrcPath[i] = _T('\0'); 00220 else 00221 break; 00222 00223 /* Go through all the soursfiles and copy/replace them */ 00224 do 00225 { 00226 if(CheckCtrlBreak(BREAK_INPUT)) 00227 { 00228 return filesReplaced; 00229 } 00230 00231 /* Problem with file handler */ 00232 if(hFile == INVALID_HANDLE_VALUE) 00233 return filesReplaced; 00234 00235 /* We do not want to replace any .. . ocr directory */ 00236 if(!_tcscmp (findBuffer.cFileName, _T(".")) || 00237 !_tcscmp (findBuffer.cFileName, _T(".."))|| 00238 findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 00239 continue; 00240 00241 /* Add filename to destpath */ 00242 _tcscpy(tmpDestPath,szDestPath); 00243 _tcscat (tmpDestPath, findBuffer.cFileName); 00244 00245 dwAttrib = GetFileAttributes(tmpDestPath); 00246 /* Check add flag */ 00247 if(dwFlags & REPLACE_ADD) 00248 { 00249 if(IsExistingFile(tmpDestPath)) 00250 continue; 00251 else 00252 dwAttrib = 0; 00253 } 00254 else 00255 { 00256 if(!IsExistingFile(tmpDestPath)) 00257 continue; 00258 } 00259 00260 /* Check if file is read only, if so check if that should be ignored */ 00261 if(dwAttrib & FILE_ATTRIBUTE_READONLY) 00262 { 00263 if(!(dwFlags & REPLACE_READ_ONLY)) 00264 { 00265 ConOutResPrintf(STRING_REPLACE_ERROR5, tmpDestPath); 00266 *doMore = FALSE; 00267 break; 00268 } 00269 } 00270 00271 /* Add filename to sourcepath, insted of wildcards */ 00272 _tcscpy(tmpSrcPath,szSrcPath); 00273 _tcscat (tmpSrcPath, findBuffer.cFileName); 00274 00275 /* Make the replace */ 00276 if(replace(tmpSrcPath,tmpDestPath, dwFlags, doMore)) 00277 { 00278 filesReplaced++; 00279 } 00280 else if (!*doMore) 00281 { 00282 /* The file to be replaced was the same as the source */ 00283 filesReplaced = -1; 00284 break; 00285 } 00286 00287 /* Take next sourcefile if any */ 00288 }while(FindNextFile (hFile, &findBuffer)); 00289 00290 return filesReplaced; 00291 } 00292 00293 /* If /s switch is specifyed all subdirs has to be considered */ 00294 INT recFindSubDirs(DWORD dwFlags, 00295 TCHAR szSrcPath[MAX_PATH], 00296 TCHAR szDestPath[MAX_PATH], 00297 BOOL *doMore) 00298 { 00299 HANDLE hFile; 00300 WIN32_FIND_DATA findBuffer; 00301 TCHAR tmpDestPath[MAX_PATH], tmpSrcPath[MAX_PATH]; 00302 INT filesReplaced = 0; 00303 INT_PTR i; 00304 00305 /* Add a wildcard to dest end so the it will be easy to itterate 00306 over all the files and directorys in the dest directory */ 00307 _tcscat(szDestPath, _T("*")); 00308 00309 /* Get the first file in the directory */ 00310 hFile = FindFirstFile (szDestPath, &findBuffer); 00311 00312 /* Remove the star added earlyer to dest path */ 00313 for(i = (_tcslen(szDestPath) - 1); i > -1; i--) 00314 if(szDestPath[i] != _T('\\')) 00315 szDestPath[i] = _T('\0'); 00316 else 00317 break; 00318 00319 /* Iterate over all filed directories in the dest dir */ 00320 do 00321 { 00322 /* Save the source path so that it will not be wrecked */ 00323 _tcscpy(tmpSrcPath,szSrcPath); 00324 /* Check for reading problems */ 00325 if(hFile == INVALID_HANDLE_VALUE) 00326 { 00327 ConOutFormatMessage (GetLastError(), tmpSrcPath); 00328 return filesReplaced; 00329 } 00330 00331 /* Check if the we should enter the dir or if it is a file 00332 or . or .. if so thake the next object to process */ 00333 if(!_tcscmp (findBuffer.cFileName, _T(".")) || 00334 !_tcscmp (findBuffer.cFileName, _T(".."))|| 00335 IsExistingFile(findBuffer.cFileName)) 00336 continue; 00337 /* Add the destpath and the new dir path to tempDestPath */ 00338 _tcscpy(tmpDestPath,szDestPath); 00339 _tcscat (tmpDestPath, findBuffer.cFileName); 00340 /* Make sure that we have a directory */ 00341 if(IsExistingDirectory(tmpDestPath)) 00342 { 00343 /* Add a \ to the end or the path */ 00344 if(szDestPath[_tcslen(tmpDestPath) - 1] != _T('\\')) 00345 _tcscat(tmpDestPath, _T("\\")); 00346 /* Call the function to replace files in the new directory */ 00347 filesReplaced += recReplace(dwFlags, tmpSrcPath, tmpDestPath, doMore); 00348 /* If there were problems break e.g. read-only file */ 00349 if(!*doMore) 00350 break; 00351 _tcscpy(tmpSrcPath,szSrcPath); 00352 /* Controle the next level of subdirs */ 00353 filesReplaced += recFindSubDirs(dwFlags,tmpSrcPath,tmpDestPath, doMore); 00354 if(!*doMore) 00355 break; 00356 } 00357 /* Get the next handle */ 00358 } while(FindNextFile (hFile, &findBuffer)); 00359 00360 return filesReplaced; 00361 } 00362 00363 INT cmd_replace (LPTSTR param) 00364 { 00365 LPTSTR *arg; 00366 INT argc, i,filesReplaced = 0, nFiles, srcIndex = -1, destIndex = -1; 00367 DWORD dwFlags = 0; 00368 TCHAR szDestPath[MAX_PATH], szSrcPath[MAX_PATH], tmpSrcPath[MAX_PATH]; 00369 BOOL doMore = TRUE; 00370 00371 /* Help wanted? */ 00372 if (!_tcsncmp (param, _T("/?"), 2)) 00373 { 00374 ConOutResPaging(TRUE,STRING_REPLACE_HELP1); 00375 return 0; 00376 } 00377 00378 /* Divide the argument in to an array of c-strings */ 00379 arg = split (param, &argc, FALSE, FALSE); 00380 nFiles = argc; 00381 00382 /* Read options */ 00383 for (i = 0; i < argc; i++) 00384 { 00385 if (arg[i][0] == _T('/')) 00386 { 00387 if (_tcslen(arg[i]) == 2) 00388 { 00389 switch (_totupper(arg[i][1])) 00390 { 00391 case _T('A'): 00392 dwFlags |= REPLACE_ADD; 00393 break; 00394 case _T('P'): 00395 dwFlags |= REPLACE_CONFIRM; 00396 break; 00397 case _T('R'): 00398 dwFlags |= REPLACE_READ_ONLY; 00399 break; 00400 case _T('S'): 00401 dwFlags |= REPLACE_SUBDIR; 00402 break; 00403 case _T('W'): 00404 dwFlags |= REPLACE_DISK; 00405 break; 00406 case _T('U'): 00407 dwFlags |= REPLACE_UPDATE; 00408 break; 00409 default: 00410 invalid_switch(arg[i]); 00411 return 0; 00412 } 00413 } 00414 else 00415 { 00416 invalid_switch(arg[i]); 00417 freep(arg); 00418 return 0; 00419 } 00420 nFiles--; 00421 } 00422 else 00423 { 00424 if(srcIndex == -1) 00425 { 00426 srcIndex = i; 00427 } 00428 else if(destIndex == -1) 00429 { 00430 destIndex = i; 00431 } 00432 else 00433 { 00434 invalid_switch(arg[i]); 00435 freep(arg); 00436 return 0; 00437 } 00438 } 00439 } 00440 00441 /* See so that at least source is there */ 00442 if (nFiles < 1) 00443 { 00444 ConOutResPaging(TRUE,STRING_REPLACE_HELP2); 00445 ConOutResPaging(TRUE,STRING_REPLACE_HELP3); 00446 freep(arg); 00447 return 1; 00448 } 00449 /* Check so that not both update and add switch is added and subdir */ 00450 if((dwFlags & REPLACE_UPDATE || dwFlags & REPLACE_SUBDIR) && (dwFlags & REPLACE_ADD)) 00451 { 00452 ConOutResPaging(TRUE,STRING_REPLACE_ERROR4); 00453 ConOutResPaging(TRUE,STRING_REPLACE_HELP7); 00454 freep(arg); 00455 return 1; 00456 } 00457 00458 /* If we have a destination get the full path */ 00459 if(destIndex != -1) 00460 { 00461 if(_tcslen(arg[destIndex]) == 2 && arg[destIndex][1] == ':') 00462 GetRootPath(arg[destIndex],szDestPath,MAX_PATH); 00463 else 00464 { 00465 /* Check for wildcards in destination directory */ 00466 if (_tcschr (arg[destIndex], _T('*')) != NULL || 00467 _tcschr (arg[destIndex], _T('?')) != NULL) 00468 { 00469 ConOutResPrintf(STRING_REPLACE_ERROR2,arg[destIndex]); 00470 ConOutResPaging(TRUE,STRING_REPLACE_HELP3); 00471 freep(arg); 00472 return 1; 00473 } 00474 getPath(szDestPath, arg[destIndex]); 00475 /* Make sure that destination exists */ 00476 if(!IsExistingDirectory(szDestPath)) 00477 { 00478 ConOutResPrintf(STRING_REPLACE_ERROR2, szDestPath); 00479 ConOutResPaging(TRUE,STRING_REPLACE_HELP3); 00480 freep(arg); 00481 return 1; 00482 } 00483 } 00484 } 00485 else 00486 { 00487 /* Dest is current dir */ 00488 GetCurrentDirectory(MAX_PATH,szDestPath); 00489 } 00490 00491 /* Get the full source path */ 00492 if(!(_tcslen(arg[srcIndex]) == 2 && arg[srcIndex][1] == ':')) 00493 getPath(szSrcPath, arg[srcIndex]); 00494 else 00495 _tcscpy(szSrcPath,arg[srcIndex]); 00496 00497 /* Source does not have wildcards */ 00498 if (_tcschr (arg[srcIndex], _T('*')) == NULL && 00499 _tcschr (arg[srcIndex], _T('?')) == NULL) 00500 { 00501 /* Check so that source is not a directory, because that is not allowed */ 00502 if(IsExistingDirectory(szSrcPath)) 00503 { 00504 ConOutResPrintf(STRING_REPLACE_ERROR6, szSrcPath); 00505 ConOutResPaging(TRUE,STRING_REPLACE_HELP3); 00506 freep(arg); 00507 return 1; 00508 } 00509 /* Check if the file exists */ 00510 if(!IsExistingFile(szSrcPath)) 00511 { 00512 ConOutResPaging(TRUE,STRING_REPLACE_HELP3); 00513 freep(arg); 00514 return 1; 00515 } 00516 } 00517 /* /w switch is set so wait for any key to be pressed */ 00518 if(dwFlags & REPLACE_DISK) 00519 { 00520 msg_pause(); 00521 cgetchar(); 00522 } 00523 00524 /* Add an extra \ to the destination path if needed */ 00525 if(szDestPath[_tcslen(szDestPath) - 1] != _T('\\')) 00526 _tcscat(szDestPath, _T("\\")); 00527 00528 /* Save source path */ 00529 _tcscpy(tmpSrcPath,szSrcPath); 00530 /* Replace in dest dir */ 00531 filesReplaced += recReplace(dwFlags, tmpSrcPath, szDestPath, &doMore); 00532 /* If subdir switch is set replace in the subdirs to */ 00533 if(dwFlags & REPLACE_SUBDIR && doMore) 00534 { 00535 filesReplaced += recFindSubDirs(dwFlags, szSrcPath, szDestPath, &doMore); 00536 } 00537 00538 /* If source == dest write no more */ 00539 if(filesReplaced != -1) 00540 { 00541 /* No files replaced */ 00542 if(filesReplaced==0) 00543 { 00544 /* Add switch dependent output */ 00545 if(dwFlags & REPLACE_ADD) 00546 ConOutResPaging(TRUE,STRING_REPLACE_HELP7); 00547 else 00548 ConOutResPaging(TRUE,STRING_REPLACE_HELP3); 00549 } 00550 /* Some files replaced */ 00551 else 00552 { 00553 /* Add switch dependent output */ 00554 if(dwFlags & REPLACE_ADD) 00555 ConOutResPrintf(STRING_REPLACE_HELP8, filesReplaced); 00556 else 00557 ConOutResPrintf(STRING_REPLACE_HELP4, filesReplaced); 00558 } 00559 } 00560 /* Return memory */ 00561 freep(arg); 00562 return 1; 00563 } 00564 #endif /* INCLUDE_CMD_REPLACE */ Generated on Sat May 26 2012 04:17:06 for ReactOS by
1.7.6.1
|