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

move.c
Go to the documentation of this file.
00001 /*
00002 *  MOVE.C - move internal command.
00003 *
00004 *
00005 *  History:
00006 *
00007 *    14-Dec-1998 (Eric Kohl)
00008 *        Started.
00009 *
00010 *    18-Jan-1999 (Eric Kohl)
00011 *        Unicode safe!
00012 *        Preliminary version!!!
00013 *
00014 *    20-Jan-1999 (Eric Kohl)
00015 *        Redirection safe!
00016 *
00017 *    27-Jan-1999 (Eric Kohl)
00018 *        Added help text ("/?").
00019 *        Added more error checks.
00020 *
00021 *    03-Feb-1999 (Eric Kohl)
00022 *        Added "/N" option.
00023 *
00024 *    30-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>)
00025 *        Remove all hardcode string to En.rc
00026 *
00027 *    24-Jun-2005 (Brandon Turner) <turnerb7@msu.edu>)
00028 *        Fixed bug to allow MS style wildcards + code clean up
00029 *        added /y and /-y
00030 */
00031 
00032 #include <precomp.h>
00033 
00034 #ifdef INCLUDE_CMD_MOVE
00035 
00036 enum
00037 {
00038     MOVE_NOTHING  = 0x001,   /* /N  */
00039     MOVE_OVER_YES = 0x002,   /* /Y  */
00040     MOVE_OVER_NO  = 0x004,   /* /-Y */
00041 };
00042 
00043 enum
00044 {   /* Move status flags */
00045     MOVE_SOURCE_IS_DIR = 0x001,
00046     MOVE_SOURCE_IS_FILE = 0x002,
00047     MOVE_DEST_IS_DIR = 0x004,
00048     MOVE_DEST_IS_FILE = 0x008,
00049     MOVE_SOURCE_HAS_WILD = 0x010, /*  source has wildcard */
00050     MOVE_SRC_CURRENT_IS_DIR = 0x020, /* source is file but at the current round we found a directory */
00051     MOVE_DEST_EXISTS = 0x040,
00052     MOVE_PATHS_ON_DIF_VOL = 0x080 /* source and destination paths are on different volume */
00053 };
00054 
00055 static INT MoveOverwrite (LPTSTR fn)
00056 {
00057     /*ask the user if they want to override*/
00058     INT res;
00059     ConOutResPrintf(STRING_MOVE_HELP1, fn);
00060     res = FilePromptYNA (0);
00061     return res;
00062 }
00063 
00064 void GetDirectory (LPTSTR wholepath, LPTSTR directory, BOOL CheckExisting)
00065 {
00066     /* returns only directory part of path with backslash */
00067     /* TODO: make code unc aware */
00068     /* Is there a better alternative to this? */
00069     LPTSTR last;
00070     if (CheckExisting && IsExistingDirectory(wholepath))
00071     {
00072         _tcscpy(directory, wholepath);
00073     }
00074     else if ((last = _tcsrchr(wholepath,_T('\\'))) != NULL)
00075     {
00076         _tcsncpy(directory, wholepath, last - wholepath + 1);
00077         directory[last - wholepath + 1] = 0;
00078     }
00079     else
00080     {
00081         GetRootPath(wholepath,directory, MAX_PATH);
00082     }
00083 }
00084 
00085 
00086 INT cmd_move (LPTSTR param)
00087 {
00088     LPTSTR *arg;
00089     INT argc, i, nFiles;
00090     LPTSTR pszDest;
00091     TCHAR szDestPath[MAX_PATH];
00092     TCHAR szFullDestPath[MAX_PATH];
00093     TCHAR szSrcDirPath[MAX_PATH];
00094     TCHAR szSrcPath[MAX_PATH];
00095     TCHAR szFullSrcPath[MAX_PATH];
00096     DWORD dwFlags = 0;
00097     INT nOverwrite = 0;
00098     WIN32_FIND_DATA findBuffer;
00099     HANDLE hFile;
00100     
00101     /* used only when source and destination  directories are on different volume*/
00102     HANDLE hDestFile;
00103     WIN32_FIND_DATA findDestBuffer;
00104     TCHAR szMoveDest[MAX_PATH];
00105     TCHAR szMoveSrc[MAX_PATH];
00106     LPTSTR pszDestDirPointer;
00107     LPTSTR pszSrcDirPointer;
00108     INT nDirLevel = 0;
00109     
00110     LPTSTR pszFile;
00111     BOOL OnlyOneFile;
00112     BOOL FoundFile;
00113     BOOL MoveStatus;
00114     DWORD dwMoveFlags = 0;
00115     DWORD dwMoveStatusFlags = 0;
00116 
00117 
00118     if (!_tcsncmp (param, _T("/?"), 2))
00119     {
00120 #if 0
00121         ConOutPuts (_T("Moves files and renames files and directories.\n\n"
00122             "To move one or more files:\n"
00123             "MOVE [/N][/Y|/-Y][drive:][path]filename1[,...] destination\n"
00124             "\n"
00125             "To rename a directory:\n"
00126             "MOVE [/N][/Y|/-Y][drive:][path]dirname1 dirname2\n"
00127             "\n"
00128             "  [drive:][path]filename1  Specifies the location and name of the file\n"
00129             "                           or files you want to move.\n"
00130             "  /N                       Nothing. Don everthing but move files or direcories.\n"
00131             "  /Y\n"
00132             "  /-Y\n"
00133             "..."));
00134 #else
00135         ConOutResPaging(TRUE,STRING_MOVE_HELP2);
00136 #endif
00137         return 0;
00138     }
00139 
00140     nErrorLevel = 0;
00141     arg = splitspace(param, &argc);
00142 
00143     /* read options */
00144     for (i = 0; i < argc; i++)
00145     {
00146         if (!_tcsicmp(arg[i], _T("/N")))
00147             dwFlags |= MOVE_NOTHING;
00148         else if (!_tcsicmp(arg[i], _T("/Y")))
00149             dwFlags |= MOVE_OVER_YES;
00150         else if (!_tcsicmp(arg[i], _T("/-Y")))
00151             dwFlags |= MOVE_OVER_NO;
00152         else
00153             break;
00154     }
00155     nFiles = argc - i;
00156 
00157     if (nFiles < 1)
00158     {
00159         /* there must be at least one pathspec */
00160         error_req_param_missing();
00161         freep(arg);
00162         return 1;
00163     }
00164 
00165     if (nFiles > 2)
00166     {
00167         /* there are more than two pathspecs */
00168         error_too_many_parameters(param);
00169         freep(arg);
00170         return 1;
00171     }
00172 
00173     /* If no destination is given, default to current directory */
00174     pszDest = (nFiles == 1) ? _T(".") : arg[i + 1];
00175 
00176     /* check for wildcards in source and destination */
00177     if (_tcschr(pszDest, _T('*')) != NULL || _tcschr(pszDest, _T('?')) != NULL)
00178     {
00179         /* '*'/'?' in dest, this doesnt happen.  give folder name instead*/
00180         error_invalid_parameter_format(pszDest);
00181         freep(arg);
00182         return 1;
00183     }
00184     if (_tcschr(arg[i], _T('*')) != NULL || _tcschr(arg[i], _T('?')) != NULL)
00185     {
00186         dwMoveStatusFlags |= MOVE_SOURCE_HAS_WILD;
00187     }
00188     
00189     
00190     /* get destination */
00191     GetFullPathName (pszDest, MAX_PATH, szDestPath, NULL);
00192     TRACE ("Destination: %s\n", debugstr_aw(szDestPath));
00193     
00194     /* get source folder */
00195     GetFullPathName(arg[i], MAX_PATH, szSrcDirPath, &pszFile);
00196     if (pszFile != NULL)
00197         *pszFile = _T('\0');
00198     TRACE ("Source Folder: %s\n", debugstr_aw(szSrcDirPath));
00199     
00200     hFile = FindFirstFile (arg[i], &findBuffer);
00201     if (hFile == INVALID_HANDLE_VALUE)
00202     {
00203         ErrorMessage (GetLastError (), arg[i]);
00204         freep (arg);
00205         return 1;
00206         
00207     }
00208 
00209     /* check for special cases "." and ".." and if found skip them */
00210     FoundFile = TRUE;
00211     while(FoundFile &&
00212           (_tcscmp(findBuffer.cFileName,_T(".")) == 0 ||
00213            _tcscmp(findBuffer.cFileName,_T("..")) == 0))
00214         FoundFile = FindNextFile (hFile, &findBuffer);
00215     
00216     if (!FoundFile)
00217     {
00218         /* what? we don't have anything to move? */
00219         error_file_not_found();
00220         FindClose(hFile);
00221         freep(arg);
00222         return 1;
00223     }
00224     
00225     OnlyOneFile = TRUE;
00226     /* check if there can be found files as files have first priority */
00227     if (findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
00228         dwMoveStatusFlags |= MOVE_SOURCE_IS_DIR;
00229     else
00230         dwMoveStatusFlags |= MOVE_SOURCE_IS_FILE;
00231     while(OnlyOneFile && FindNextFile(hFile,&findBuffer))
00232     {
00233         if (!(findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
00234         {
00235             ConOutPrintf(_T(""));
00236             if (dwMoveStatusFlags & MOVE_SOURCE_IS_FILE) OnlyOneFile = FALSE;
00237             else
00238             {   /* this has been done this way so that we don't disturb other settings if they have been set before this */
00239                 dwMoveStatusFlags |= MOVE_SOURCE_IS_FILE;
00240                 dwMoveStatusFlags &= ~MOVE_SOURCE_IS_DIR;
00241             }
00242         }
00243     }
00244     FindClose(hFile);
00245 
00246     TRACE ("Do we have only one file: %s\n", OnlyOneFile ? "TRUE" : "FALSE");
00247 
00248     /* we have to start again to be sure we don't miss any files or folders*/
00249     hFile = FindFirstFile (arg[i], &findBuffer);
00250     if (hFile == INVALID_HANDLE_VALUE)
00251     {
00252         ErrorMessage (GetLastError (), arg[i]);
00253         freep (arg);
00254         return 1;
00255         
00256     }
00257     
00258     /* check for special cases "." and ".." and if found skip them */
00259     FoundFile = TRUE;
00260     while(FoundFile &&
00261           (_tcscmp(findBuffer.cFileName,_T(".")) == 0 ||
00262            _tcscmp(findBuffer.cFileName,_T("..")) == 0))
00263         FoundFile = FindNextFile (hFile, &findBuffer);
00264     
00265     if (!FoundFile)
00266     {
00267         /* huh? somebody removed files and/or folders which were there */
00268         error_file_not_found();
00269         FindClose(hFile);
00270         freep(arg);
00271         return 1;
00272     }
00273     
00274     /* check if source and destination paths are on different volumes */
00275     if (szSrcDirPath[0] != szDestPath[0])
00276         dwMoveStatusFlags |= MOVE_PATHS_ON_DIF_VOL;
00277     
00278     /* move it */
00279     do
00280     {
00281         TRACE ("Found file/directory: %s\n", debugstr_aw(findBuffer.cFileName));
00282         nOverwrite = 1;
00283         dwMoveFlags = 0;
00284         dwMoveStatusFlags &= ~MOVE_DEST_IS_FILE &
00285                             ~MOVE_DEST_IS_DIR &
00286                             ~MOVE_SRC_CURRENT_IS_DIR &
00287                             ~MOVE_DEST_EXISTS;
00288         _tcscpy(szFullSrcPath,szSrcDirPath);
00289         if(szFullSrcPath[_tcslen(szFullSrcPath) -  1] != _T('\\'))
00290             _tcscat (szFullSrcPath, _T("\\"));
00291         _tcscat(szFullSrcPath,findBuffer.cFileName);
00292         _tcscpy(szSrcPath, szFullSrcPath);
00293         
00294         if (IsExistingDirectory(szSrcPath))
00295         {
00296             /* source is directory */
00297             
00298             if (dwMoveStatusFlags & MOVE_SOURCE_IS_FILE)
00299             {
00300                 dwMoveStatusFlags |= MOVE_SRC_CURRENT_IS_DIR; /* source is file but at the current round we found a directory */
00301                 continue;
00302             }
00303             TRACE ("Source is dir: %s\n", debugstr_aw(szSrcPath));
00304             dwMoveFlags = MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED;
00305         }
00306         
00307         /* if source is file we don't need to do anything special */
00308         
00309         if (IsExistingDirectory(szDestPath))
00310         {
00311             /* destination is existing directory */
00312             TRACE ("Destination is directory: %s\n", debugstr_aw(szDestPath));
00313             
00314             dwMoveStatusFlags |= MOVE_DEST_IS_DIR;
00315             
00316             /*build the dest string(accounts for *)*/
00317             _tcscpy (szFullDestPath, szDestPath);
00318             /*check to see if there is an ending slash, if not add one*/
00319             if(szFullDestPath[_tcslen(szFullDestPath) -  1] != _T('\\'))
00320                 _tcscat (szFullDestPath, _T("\\"));
00321             _tcscat (szFullDestPath, findBuffer.cFileName);
00322             
00323             if (IsExistingFile(szFullDestPath) || IsExistingDirectory(szFullDestPath))
00324                 dwMoveStatusFlags |= MOVE_DEST_EXISTS;
00325             
00326             dwMoveFlags |= MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED;
00327             
00328         }
00329         if (IsExistingFile(szDestPath))
00330         {
00331             /* destination is a file */
00332             TRACE ("Destination is file: %s\n", debugstr_aw(szDestPath));
00333             
00334             dwMoveStatusFlags |= MOVE_DEST_IS_FILE | MOVE_DEST_EXISTS;
00335             _tcscpy (szFullDestPath, szDestPath);
00336             
00337             dwMoveFlags |= MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED;
00338             
00339         }
00340         
00341         TRACE ("Move Status Flags: 0x%X\n",dwMoveStatusFlags);
00342         
00343         if (dwMoveStatusFlags & MOVE_SOURCE_IS_DIR &&
00344             dwMoveStatusFlags & MOVE_DEST_IS_DIR &&
00345             dwMoveStatusFlags & MOVE_SOURCE_HAS_WILD)
00346         {
00347             /* We are not allowed to have existing source and destination dir when there is wildcard in source */
00348             error_syntax(NULL);
00349             FindClose(hFile);
00350             freep(arg);
00351             return 1;
00352         }
00353             
00354         if (!(dwMoveStatusFlags & (MOVE_DEST_IS_FILE | MOVE_DEST_IS_DIR)))
00355         {
00356             /* destination doesn't exist */
00357             _tcscpy (szFullDestPath, szDestPath);
00358             if (dwMoveStatusFlags & MOVE_SOURCE_IS_FILE) dwMoveStatusFlags |= MOVE_DEST_IS_FILE;
00359             if (dwMoveStatusFlags & MOVE_SOURCE_IS_DIR) dwMoveStatusFlags |= MOVE_DEST_IS_DIR;
00360             
00361             dwMoveFlags |= MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED;
00362         }
00363         
00364         if (dwMoveStatusFlags & MOVE_SOURCE_IS_FILE &&
00365             dwMoveStatusFlags & MOVE_DEST_IS_FILE &&
00366             !OnlyOneFile)
00367         {
00368             /*source has many files but there is only one destination file*/
00369             error_invalid_parameter_format(pszDest);
00370             FindClose(hFile);
00371             freep (arg);
00372             return 1;
00373         }
00374         
00375         /*checks to make sure user wanted/wants the override*/
00376         if((dwFlags & MOVE_OVER_NO) &&
00377            (dwMoveStatusFlags & MOVE_DEST_EXISTS))
00378             continue;
00379         if(!(dwFlags & MOVE_OVER_YES) &&
00380             (dwMoveStatusFlags & MOVE_DEST_EXISTS))
00381             nOverwrite = MoveOverwrite (szFullDestPath);
00382         if (nOverwrite == PROMPT_NO || nOverwrite == PROMPT_BREAK)
00383             continue;
00384         if (nOverwrite == PROMPT_ALL)
00385             dwFlags |= MOVE_OVER_YES;
00386         
00387             
00388         ConOutPrintf (_T("%s => %s "), szSrcPath, szFullDestPath);
00389         
00390         /* are we really supposed to do something */
00391         if (dwFlags & MOVE_NOTHING)
00392             continue;
00393         
00394         /*move the file*/
00395         if (!(dwMoveStatusFlags & MOVE_SOURCE_IS_DIR &&
00396             dwMoveStatusFlags & MOVE_PATHS_ON_DIF_VOL))
00397             /* we aren't moving source folder to different drive */
00398             MoveStatus = MoveFileEx (szSrcPath, szFullDestPath, dwMoveFlags);
00399         else
00400         {   /* we are moving source folder to different drive */
00401             _tcscpy(szMoveDest, szFullDestPath);
00402             _tcscpy(szMoveSrc, szSrcPath);
00403             DeleteFile(szMoveDest);
00404             MoveStatus = CreateDirectory(szMoveDest, NULL); /* we use default security settings */
00405             if (MoveStatus)
00406             {
00407                 _tcscat(szMoveDest,_T("\\"));
00408                 _tcscat(szMoveSrc,_T("\\"));
00409                 nDirLevel = 0;
00410                 pszDestDirPointer = szMoveDest + _tcslen(szMoveDest);
00411                 pszSrcDirPointer = szMoveSrc + _tcslen(szMoveSrc);
00412                 _tcscpy(pszSrcDirPointer,_T("*.*"));
00413                 hDestFile = FindFirstFile(szMoveSrc, &findDestBuffer);
00414                 if (hDestFile == INVALID_HANDLE_VALUE)
00415                     MoveStatus = FALSE;
00416                 else
00417                 {
00418                     BOOL FirstTime = TRUE;
00419                     FoundFile = TRUE;
00420                     MoveStatus = FALSE;
00421                     while(FoundFile)
00422                     {
00423                         if (FirstTime)
00424                             FirstTime = FALSE;
00425                         else
00426                             FoundFile = FindNextFile (hDestFile, &findDestBuffer);
00427                         
00428                         if (!FoundFile)
00429                         {   /* Nothing to do in this folder so we stop working on it */
00430                             FindClose(hDestFile);
00431                             (pszSrcDirPointer)--;
00432                             (pszDestDirPointer)--;
00433                             _tcscpy(pszSrcDirPointer,_T(""));
00434                             _tcscpy(pszDestDirPointer,_T(""));
00435                             if (nDirLevel > 0)
00436                             {
00437                                 TCHAR szTempPath[MAX_PATH];
00438                                 INT_PTR nDiff;
00439 
00440                                 FoundFile = TRUE; /* we need to continue our seek for files */
00441                                 nDirLevel--;
00442                                 RemoveDirectory(szMoveSrc);
00443                                 GetDirectory(szMoveSrc,szTempPath,0);
00444                                 nDiff = _tcslen(szMoveSrc) - _tcslen(szTempPath);
00445                                 pszSrcDirPointer = pszSrcDirPointer - nDiff;
00446                                 _tcscpy(pszSrcDirPointer,_T(""));
00447                                 GetDirectory(szMoveDest,szTempPath,0);
00448                                 nDiff = _tcslen(szMoveDest) - _tcslen(szTempPath);
00449                                 pszDestDirPointer = pszDestDirPointer - nDiff;
00450                                 _tcscpy(pszDestDirPointer,_T(""));
00451                                 if(szMoveSrc[_tcslen(szMoveSrc) -  1] != _T('\\'))
00452                                     _tcscat (szMoveSrc, _T("\\"));
00453                                 if(szMoveDest[_tcslen(szMoveDest) -  1] != _T('\\'))
00454                                     _tcscat (szMoveDest, _T("\\"));
00455                                 pszDestDirPointer = szMoveDest + _tcslen(szMoveDest);
00456                                 pszSrcDirPointer = szMoveSrc + _tcslen(szMoveSrc);
00457                                 _tcscpy(pszSrcDirPointer,_T("*.*"));
00458                                 hDestFile = FindFirstFile(szMoveSrc, &findDestBuffer);
00459                                 if (hDestFile == INVALID_HANDLE_VALUE)
00460                                     continue;
00461                                 FirstTime = TRUE;
00462                             }
00463                             else
00464                             {
00465                                 MoveStatus = TRUE; /* we moved everything so lets tell user about it */
00466                                 RemoveDirectory(szMoveSrc);
00467                             }
00468                             continue;
00469                         }
00470                         
00471                         /* if we find "." or ".." we'll skip them */
00472                         if (_tcscmp(findDestBuffer.cFileName,_T(".")) == 0 ||
00473                             _tcscmp(findDestBuffer.cFileName,_T("..")) == 0)
00474                             continue;
00475                     
00476                         _tcscpy(pszSrcDirPointer, findDestBuffer.cFileName);
00477                         _tcscpy(pszDestDirPointer, findDestBuffer.cFileName);
00478                         if (IsExistingFile(szMoveSrc))
00479                         {
00480                             FoundFile = CopyFile(szMoveSrc, szMoveDest, FALSE);
00481                             if (!FoundFile) continue;
00482                             DeleteFile(szMoveSrc);
00483                         }
00484                         else
00485                         {
00486                             FindClose(hDestFile);
00487                             CreateDirectory(szMoveDest, NULL);
00488                             _tcscat(szMoveDest,_T("\\"));
00489                             _tcscat(szMoveSrc,_T("\\"));
00490                             nDirLevel++;
00491                             pszDestDirPointer = szMoveDest + _tcslen(szMoveDest);
00492                             pszSrcDirPointer = szMoveSrc + _tcslen(szMoveSrc);
00493                             _tcscpy(pszSrcDirPointer,_T("*.*"));
00494                             hDestFile = FindFirstFile(szMoveSrc, &findDestBuffer);
00495                             if (hDestFile == INVALID_HANDLE_VALUE)
00496                             {
00497                                 FoundFile = FALSE;
00498                                 continue;
00499                             }
00500                             FirstTime = TRUE;
00501                         }
00502                     }
00503                 }
00504             }
00505         }
00506         if (MoveStatus)
00507             ConOutResPrintf(STRING_MOVE_ERROR1);
00508         else
00509             ConOutResPrintf(STRING_MOVE_ERROR2);
00510     }
00511     while ((!OnlyOneFile || dwMoveStatusFlags & MOVE_SRC_CURRENT_IS_DIR ) &&
00512             !(dwMoveStatusFlags & MOVE_SOURCE_IS_DIR) &&
00513             FindNextFile (hFile, &findBuffer));
00514     FindClose (hFile);
00515     
00516     freep (arg);
00517     return 0;
00518 }
00519 
00520 #endif /* INCLUDE_CMD_MOVE */

Generated on Fri May 25 2012 04:16:30 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.