Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmove.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
1.7.6.1
|