ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

replace.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.