Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendel.c
Go to the documentation of this file.
00001 /* 00002 * DEL.C - del internal command. 00003 * 00004 * 00005 * History: 00006 * 00007 * 06/29/98 (Rob Lake rlake@cs.mun.ca) 00008 * rewrote del to support wildcards 00009 * added my name to the contributors 00010 * 00011 * 07/13/98 (Rob Lake) 00012 * fixed bug that caused del not to delete file with out 00013 * attribute. moved set, del, ren, and ver to there own files 00014 * 00015 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>) 00016 * added config.h include 00017 * 00018 * 09-Dec-1998 (Eric Kohl) 00019 * Fixed command line parsing bugs. 00020 * 00021 * 21-Jan-1999 (Eric Kohl) 00022 * Started major rewrite using a new structure. 00023 * 00024 * 03-Feb-1999 (Eric Kohl) 00025 * First working version. 00026 * 00027 * 30-Mar-1999 (Eric Kohl) 00028 * Added quiet ("/Q"), wipe ("/W") and zap ("/Z") option. 00029 * 00030 * 06-Nov-1999 (Eric Kohl) 00031 * Little fix to keep DEL quiet inside batch files. 00032 * 00033 * 28-Jan-2004 (Michael Fritscher <michael@fritscher.net>) 00034 * Added prompt ("/P"), yes ("/Y") and wipe("/W") option. 00035 * 00036 * 22-Jun-2005 (Brandon Turner <turnerb7@msu.edu>) 00037 * Added exclusive deletion "del * -abc.txt -text*.txt" 00038 * 00039 * 22-Jun-2005 (Brandon Turner <turnerb7@msu.edu>) 00040 * Implemented /A example "del /A:H /A:-R *.exe -ping.exe" 00041 * 00042 * 07-Aug-2005 00043 * Removed the exclusive deletion (see two comments above) because '-' is a valid file name character. 00044 * Optimized the recursive deletion in directories. 00045 * Preload some nice strings. 00046 */ 00047 00048 #include <precomp.h> 00049 00050 #ifdef INCLUDE_CMD_DEL 00051 00052 00053 enum 00054 { 00055 DEL_ATTRIBUTES = 0x001, /* /A */ 00056 DEL_NOTHING = 0x004, /* /N */ 00057 DEL_PROMPT = 0x008, /* /P */ 00058 DEL_QUIET = 0x010, /* /Q */ 00059 DEL_SUBDIR = 0x020, /* /S */ 00060 DEL_TOTAL = 0x040, /* /T */ 00061 DEL_WIPE = 0x080, /* /W */ 00062 DEL_EMPTYDIR = 0x100, /* /X : not implemented */ 00063 DEL_YES = 0x200, /* /Y */ 00064 DEL_FORCE = 0x800 /* /F */ 00065 }; 00066 00067 enum 00068 { 00069 ATTR_ARCHIVE = 0x001, /* /A:A */ 00070 ATTR_HIDDEN = 0x002, /* /A:H */ 00071 ATTR_SYSTEM = 0x004, /* /A:S */ 00072 ATTR_READ_ONLY = 0x008, /* /A:R */ 00073 ATTR_N_ARCHIVE = 0x010, /* /A:-A */ 00074 ATTR_N_HIDDEN = 0x020, /* /A:-H */ 00075 ATTR_N_SYSTEM = 0x040, /* /A:-S */ 00076 ATTR_N_READ_ONLY = 0x080 /* /A:-R */ 00077 }; 00078 00079 static TCHAR szDeleteWipe[RC_STRING_MAX_SIZE]; 00080 static TCHAR CMDPath[MAX_PATH]; 00081 00082 static BOOLEAN StringsLoaded = FALSE; 00083 00084 static VOID LoadStrings(VOID) 00085 { 00086 LoadString( CMD_ModuleHandle, STRING_DELETE_WIPE, szDeleteWipe, RC_STRING_MAX_SIZE); 00087 GetModuleFileName(NULL, CMDPath, MAX_PATH); 00088 StringsLoaded = TRUE; 00089 } 00090 00091 static BOOL 00092 RemoveFile (LPTSTR lpFileName, DWORD dwFlags, WIN32_FIND_DATA* f) 00093 { 00094 /*This function is called by CommandDelete and 00095 does the actual process of deleting the single 00096 file*/ 00097 if(CheckCtrlBreak(BREAK_INPUT)) 00098 return 1; 00099 00100 /*check to see if it is read only and if this is done based on /A 00101 if it is done by file name, access is denied. However, if it is done 00102 using the /A switch you must un-read only the file and allow it to be 00103 deleted*/ 00104 if((dwFlags & DEL_ATTRIBUTES) || (dwFlags & DEL_FORCE)) 00105 { 00106 if(f->dwFileAttributes & FILE_ATTRIBUTE_READONLY) 00107 { 00108 /*setting file to normal, not saving old attrs first 00109 because the file is going to be deleted anyways 00110 so the only thing that matters is that it isnt 00111 read only.*/ 00112 SetFileAttributes(lpFileName,FILE_ATTRIBUTE_NORMAL); 00113 } 00114 } 00115 00116 if (dwFlags & DEL_WIPE) 00117 { 00118 00119 HANDLE file; 00120 DWORD temp; 00121 #define BufferSize 65536 00122 BYTE buffer[BufferSize]; 00123 LONGLONG i; 00124 LARGE_INTEGER FileSize; 00125 00126 FileSize.u.HighPart = f->nFileSizeHigh; 00127 FileSize.u.LowPart = f->nFileSizeLow; 00128 00129 for(i = 0; i < BufferSize; i++) 00130 { 00131 buffer[i]=rand() % 256; 00132 } 00133 file = CreateFile (lpFileName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL); 00134 if (file != INVALID_HANDLE_VALUE) 00135 { 00136 for(i = 0; i < (FileSize.QuadPart - BufferSize); i += BufferSize) 00137 { 00138 WriteFile (file, buffer, BufferSize, &temp, NULL); 00139 ConOutPrintf (_T("%I64d%% %s\r"),(i * (LONGLONG)100)/FileSize.QuadPart,szDeleteWipe); 00140 } 00141 WriteFile (file, buffer, (DWORD)(FileSize.QuadPart - i), &temp, NULL); 00142 ConOutPrintf (_T("100%% %s\n"),szDeleteWipe); 00143 CloseHandle (file); 00144 } 00145 } 00146 00147 return DeleteFile (lpFileName); 00148 } 00149 00150 00151 static DWORD 00152 DeleteFiles(LPTSTR FileName, DWORD* dwFlags, DWORD dwAttrFlags) 00153 { 00154 TCHAR szFullPath[MAX_PATH]; 00155 TCHAR szFileName[MAX_PATH]; 00156 LPTSTR pFilePart; 00157 HANDLE hFile; 00158 WIN32_FIND_DATA f; 00159 BOOL bExclusion; 00160 INT res; 00161 DWORD dwFiles = 0; 00162 00163 _tcscpy(szFileName, FileName); 00164 00165 if(_tcschr (szFileName, _T('*')) == NULL && 00166 IsExistingDirectory (szFileName)) 00167 { 00168 /* If it doesnt have a \ at the end already then on needs to be added */ 00169 if(szFileName[_tcslen(szFileName) - 1] != _T('\\')) 00170 _tcscat (szFileName, _T("\\")); 00171 /* Add a wildcard after the \ */ 00172 _tcscat (szFileName, _T("*")); 00173 } 00174 00175 if(!_tcscmp (szFileName, _T("*")) || 00176 !_tcscmp (szFileName, _T("*.*")) || 00177 (szFileName[_tcslen(szFileName) - 2] == _T('\\') && szFileName[_tcslen(szFileName) - 1] == _T('*'))) 00178 { 00179 /* well, the user wants to delete everything but if they didnt yes DEL_YES, DEL_QUIET, or DEL_PROMPT 00180 then we are going to want to make sure that in fact they want to do that. */ 00181 00182 if (!((*dwFlags & DEL_YES) || (*dwFlags & DEL_QUIET) || (*dwFlags & DEL_PROMPT))) 00183 { 00184 res = FilePromptYNA (STRING_DEL_HELP2); 00185 if ((res == PROMPT_NO) || (res == PROMPT_BREAK)) 00186 return 0x80000000; 00187 if(res == PROMPT_ALL) 00188 *dwFlags |= DEL_YES; 00189 } 00190 } 00191 00192 GetFullPathName (szFileName, 00193 MAX_PATH, 00194 szFullPath, 00195 &pFilePart); 00196 00197 hFile = FindFirstFile(szFullPath, &f); 00198 if (hFile != INVALID_HANDLE_VALUE) 00199 { 00200 do 00201 { 00202 bExclusion = FALSE; 00203 00204 /*if it is going to be excluded by - no need to check attrs*/ 00205 if(*dwFlags & DEL_ATTRIBUTES && !bExclusion) 00206 { 00207 00208 /*save if file attr check if user doesnt care about that attr anyways*/ 00209 if(dwAttrFlags & ATTR_ARCHIVE && !(f.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)) 00210 bExclusion = TRUE; 00211 if(dwAttrFlags & ATTR_HIDDEN && !(f.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) 00212 bExclusion = TRUE; 00213 if(dwAttrFlags & ATTR_SYSTEM && !(f.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) 00214 bExclusion = TRUE; 00215 if(dwAttrFlags & ATTR_READ_ONLY && !(f.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) 00216 bExclusion = TRUE; 00217 if(dwAttrFlags & ATTR_N_ARCHIVE && (f.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)) 00218 bExclusion = TRUE; 00219 if(dwAttrFlags & ATTR_N_HIDDEN && (f.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) 00220 bExclusion = TRUE; 00221 if(dwAttrFlags & ATTR_N_SYSTEM && (f.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) 00222 bExclusion = TRUE; 00223 if(dwAttrFlags & ATTR_N_READ_ONLY && (f.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) 00224 bExclusion = TRUE; 00225 } 00226 if(bExclusion) 00227 continue; 00228 00229 /* ignore directories */ 00230 if (f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 00231 continue; 00232 00233 00234 _tcscpy (pFilePart, f.cFileName); 00235 00236 /* We cant delete ourselves */ 00237 if(!_tcscmp (CMDPath,szFullPath)) 00238 continue; 00239 00240 00241 TRACE("Full filename: %s\n", debugstr_aw(szFullPath)); 00242 00243 /* ask for deleting */ 00244 if (*dwFlags & DEL_PROMPT) 00245 { 00246 ConErrResPrintf(STRING_DEL_ERROR5, szFullPath); 00247 00248 res = FilePromptYN (STRING_DEL_ERROR6); 00249 00250 if ((res == PROMPT_NO) || (res == PROMPT_BREAK)) 00251 { 00252 nErrorLevel = 0; 00253 continue; 00254 } 00255 } 00256 00257 /*user cant ask it to be quiet and tell you what it did*/ 00258 if (!(*dwFlags & DEL_QUIET) && !(*dwFlags & DEL_TOTAL)) 00259 { 00260 ConErrResPrintf(STRING_DEL_ERROR7, szFullPath); 00261 } 00262 00263 /* delete the file */ 00264 if(*dwFlags & DEL_NOTHING) 00265 continue; 00266 00267 if(RemoveFile (szFullPath, *dwFlags, &f)) 00268 dwFiles++; 00269 else 00270 { 00271 ErrorMessage (GetLastError(), _T("")); 00272 // FindClose(hFile); 00273 // return -1; 00274 } 00275 } 00276 while (FindNextFile (hFile, &f)); 00277 FindClose (hFile); 00278 } 00279 else error_sfile_not_found(szFullPath); 00280 return dwFiles; 00281 } 00282 00283 static DWORD 00284 ProcessDirectory(LPTSTR FileName, DWORD* dwFlags, DWORD dwAttrFlags) 00285 { 00286 TCHAR szFullPath[MAX_PATH]; 00287 LPTSTR pFilePart; 00288 LPTSTR pSearchPart; 00289 HANDLE hFile; 00290 WIN32_FIND_DATA f; 00291 DWORD dwFiles = 0; 00292 00293 GetFullPathName (FileName, 00294 MAX_PATH, 00295 szFullPath, 00296 &pFilePart); 00297 00298 dwFiles = DeleteFiles(szFullPath, dwFlags, dwAttrFlags); 00299 if (dwFiles & 0x80000000) 00300 return dwFiles; 00301 00302 if (*dwFlags & DEL_SUBDIR) 00303 { 00304 /* Get just the file name */ 00305 pSearchPart = _tcsrchr(FileName,_T('\\')); 00306 if(pSearchPart != NULL) 00307 pSearchPart++; 00308 else 00309 pSearchPart = FileName; 00310 00311 /* Get the full path to the file */ 00312 GetFullPathName (FileName,MAX_PATH,szFullPath,NULL); 00313 00314 /* strip the filename off of it */ 00315 pFilePart = _tcsrchr(szFullPath, _T('\\')); 00316 if (pFilePart == NULL) 00317 { 00318 pFilePart = szFullPath; 00319 } 00320 else 00321 { 00322 pFilePart++; 00323 } 00324 00325 _tcscpy(pFilePart, _T("*")); 00326 00327 hFile = FindFirstFile(szFullPath, &f); 00328 if (hFile != INVALID_HANDLE_VALUE) 00329 { 00330 do 00331 { 00332 if (!(f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || 00333 !_tcscmp(f.cFileName, _T(".")) || 00334 !_tcscmp(f.cFileName, _T(".."))) 00335 continue; 00336 00337 _tcscpy(pFilePart, f.cFileName); 00338 _tcscat(pFilePart, _T("\\")); 00339 _tcscat(pFilePart, pSearchPart); 00340 00341 dwFiles +=ProcessDirectory(szFullPath, dwFlags, dwAttrFlags); 00342 if (dwFiles & 0x80000000) 00343 { 00344 break; 00345 } 00346 } 00347 while (FindNextFile (hFile, &f)); 00348 FindClose (hFile); 00349 } 00350 } 00351 return dwFiles; 00352 } 00353 00354 00355 00356 INT CommandDelete (LPTSTR param) 00357 { 00358 /*cmd is the command that was given, in this case it will always be "del" or "delete" 00359 param is whatever is given after the command*/ 00360 00361 LPTSTR *arg = NULL; 00362 INT args; 00363 INT i; 00364 INT nEvalArgs = 0; /* nunber of evaluated arguments */ 00365 DWORD dwFlags = 0; 00366 DWORD dwAttrFlags = 0; 00367 DWORD dwFiles = 0; 00368 LONG ch; 00369 TCHAR szOrginalArg[MAX_PATH]; 00370 00371 /*checks the first two chars of param to see if it is /? 00372 this however allows the following command to not show help 00373 "del frog.txt /?" */ 00374 00375 if (!StringsLoaded) 00376 { 00377 LoadStrings(); 00378 } 00379 00380 if (!_tcsncmp (param, _T("/?"), 2)) 00381 { 00382 ConOutResPaging(TRUE,STRING_DEL_HELP1); 00383 return 0; 00384 } 00385 00386 nErrorLevel = 0; 00387 00388 arg = split (param, &args, FALSE, FALSE); 00389 00390 if (args == 0) 00391 { 00392 /* only command given */ 00393 error_req_param_missing (); 00394 freep (arg); 00395 return 1; 00396 } 00397 /* check for options anywhere in command line */ 00398 for (i = 0; i < args; i++) 00399 { 00400 if (*arg[i] == _T('/')) 00401 { 00402 /*found a command, but check to make sure it has something after it*/ 00403 if (_tcslen (arg[i]) >= 2) 00404 { 00405 ch = _totupper (arg[i][1]); 00406 if (ch == _T('N')) 00407 { 00408 dwFlags |= DEL_NOTHING; 00409 } 00410 else if (ch == _T('P')) 00411 { 00412 dwFlags |= DEL_PROMPT; 00413 } 00414 else if (ch == _T('Q')) 00415 { 00416 dwFlags |= DEL_QUIET; 00417 } 00418 else if (ch == _T('F')) 00419 { 00420 dwFlags |= DEL_FORCE; 00421 } 00422 else if (ch == _T('S')) 00423 { 00424 dwFlags |= DEL_SUBDIR; 00425 } 00426 else if (ch == _T('T')) 00427 { 00428 dwFlags |= DEL_TOTAL; 00429 } 00430 else if (ch == _T('W')) 00431 { 00432 dwFlags |= DEL_WIPE; 00433 } 00434 else if (ch == _T('Y')) 00435 { 00436 dwFlags |= DEL_YES; 00437 } 00438 else if (ch == _T('A')) 00439 { 00440 00441 dwFlags |= DEL_ATTRIBUTES; 00442 /*the proper syntax for /A has a min of 4 chars 00443 i.e. /A:R or /A:-H */ 00444 if (_tcslen (arg[i]) < 4) 00445 { 00446 error_invalid_parameter_format(arg[i]); 00447 return 0; 00448 } 00449 ch = _totupper (arg[i][3]); 00450 if (_tcslen (arg[i]) == 4) 00451 { 00452 if(ch == _T('A')) 00453 { 00454 dwAttrFlags |= ATTR_ARCHIVE; 00455 } 00456 if(ch == _T('H')) 00457 { 00458 dwAttrFlags |= ATTR_HIDDEN; 00459 } 00460 if(ch == _T('S')) 00461 { 00462 dwAttrFlags |= ATTR_SYSTEM; 00463 } 00464 if(ch == _T('R')) 00465 { 00466 dwAttrFlags |= ATTR_READ_ONLY; 00467 } 00468 } 00469 if (_tcslen (arg[i]) == 5) 00470 { 00471 if(ch == _T('-')) 00472 { 00473 ch = _totupper (arg[i][4]); 00474 if(ch == _T('A')) 00475 { 00476 dwAttrFlags |= ATTR_N_ARCHIVE; 00477 } 00478 if(ch == _T('H')) 00479 { 00480 dwAttrFlags |= ATTR_N_HIDDEN; 00481 } 00482 if(ch == _T('S')) 00483 { 00484 dwAttrFlags |= ATTR_N_SYSTEM; 00485 } 00486 if(ch == _T('R')) 00487 { 00488 dwAttrFlags |= ATTR_N_READ_ONLY; 00489 } 00490 } 00491 } 00492 } 00493 } 00494 00495 nEvalArgs++; 00496 } 00497 } 00498 00499 /* there are only options on the command line --> error!!! 00500 there is the same number of args as there is flags, so none of the args were filenames*/ 00501 if (args == nEvalArgs) 00502 { 00503 error_req_param_missing (); 00504 freep (arg); 00505 return 1; 00506 } 00507 00508 /* keep quiet within batch files */ 00509 if (bc != NULL) 00510 dwFlags |= DEL_QUIET; 00511 00512 /* check for filenames anywhere in command line */ 00513 for (i = 0; i < args && !(dwFiles & 0x80000000); i++) 00514 { 00515 00516 /*this checks to see if it isnt a flag, if it isnt, we assume it is a file name*/ 00517 if((*arg[i] == _T('/')) || (*arg[i] == _T('-'))) 00518 continue; 00519 00520 /* We want to make a copies of the argument */ 00521 if(_tcslen(arg[i]) == 2 && arg[i][1] == _T(':')) 00522 { 00523 /* Check for C: D: ... */ 00524 GetRootPath(arg[i],szOrginalArg,MAX_PATH); 00525 } 00526 else 00527 { 00528 _tcscpy(szOrginalArg,arg[i]); 00529 } 00530 dwFiles += ProcessDirectory(szOrginalArg, &dwFlags, dwAttrFlags); 00531 00532 } 00533 00534 freep (arg); 00535 00536 /*Based on MS cmd, we only tell what files are being deleted when /S is used */ 00537 if (dwFlags & DEL_TOTAL) 00538 { 00539 dwFiles &= 0x7fffffff; 00540 if (dwFiles < 2) 00541 { 00542 ConOutResPrintf(STRING_DEL_HELP3, dwFiles); 00543 } 00544 else 00545 { 00546 ConOutResPrintf(STRING_DEL_HELP4, dwFiles); 00547 } 00548 } 00549 00550 return 0; 00551 } 00552 00553 00554 #endif Generated on Sat May 26 2012 04:17:02 for ReactOS by
1.7.6.1
|