Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552/** DEL.C - del internal command.*** History:** 06/29/98 (Rob Lake rlake@cs.mun.ca)* rewrote del to support wildcards* added my name to the contributors** 07/13/98 (Rob Lake)* fixed bug that caused del not to delete file with out* attribute. moved set, del, ren, and ver to there own files** 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)* added config.h include** 09-Dec-1998 (Eric Kohl)* Fixed command line parsing bugs.** 21-Jan-1999 (Eric Kohl)* Started major rewrite using a new structure.** 03-Feb-1999 (Eric Kohl)* First working version.** 30-Mar-1999 (Eric Kohl)* Added quiet ("/Q"), wipe ("/W") and zap ("/Z") option.** 06-Nov-1999 (Eric Kohl)* Little fix to keep DEL quiet inside batch files.** 28-Jan-2004 (Michael Fritscher <michael@fritscher.net>)* Added prompt ("/P"), yes ("/Y") and wipe("/W") option.** 22-Jun-2005 (Brandon Turner <turnerb7@msu.edu>)* Added exclusive deletion "del * -abc.txt -text*.txt"** 22-Jun-2005 (Brandon Turner <turnerb7@msu.edu>)* Implemented /A example "del /A:H /A:-R *.exe -ping.exe"** 07-Aug-2005* Removed the exclusive deletion (see two comments above) because '-' is a valid file name character.* Optimized the recursive deletion in directories.* Preload some nice strings.*/
#include "precomp.h"
#ifdef INCLUDE_CMD_DEL
enum{ DEL_ATTRIBUTES = 0x001, /* /A */ DEL_NOTHING = 0x004, /* /N */ DEL_PROMPT = 0x008, /* /P */ DEL_QUIET = 0x010, /* /Q */ DEL_SUBDIR = 0x020, /* /S */ DEL_TOTAL = 0x040, /* /T */ DEL_WIPE = 0x080, /* /W */ DEL_EMPTYDIR = 0x100, /* /X : not implemented */ DEL_YES = 0x200, /* /Y */ DEL_FORCE = 0x800 /* /F */};
enum{ ATTR_ARCHIVE = 0x001, /* /A:A */ ATTR_HIDDEN = 0x002, /* /A:H */ ATTR_SYSTEM = 0x004, /* /A:S */ ATTR_READ_ONLY = 0x008, /* /A:R */ ATTR_N_ARCHIVE = 0x010, /* /A:-A */ ATTR_N_HIDDEN = 0x020, /* /A:-H */ ATTR_N_SYSTEM = 0x040, /* /A:-S */ ATTR_N_READ_ONLY = 0x080 /* /A:-R */};
static TCHAR szDeleteWipe[RC_STRING_MAX_SIZE];static TCHAR CMDPath[MAX_PATH];
static BOOLEAN StringsLoaded = FALSE;
static VOID LoadStrings(VOID){ LoadString(CMD_ModuleHandle, STRING_DELETE_WIPE, szDeleteWipe, ARRAYSIZE(szDeleteWipe)); GetModuleFileName(NULL, CMDPath, ARRAYSIZE(CMDPath)); StringsLoaded = TRUE;}
static BOOLRemoveFile (LPTSTR lpFileName, DWORD dwFlags, WIN32_FIND_DATA* f){ /*This function is called by CommandDelete and does the actual process of deleting the single file*/ if (CheckCtrlBreak(BREAK_INPUT)) return 1;
/*check to see if it is read only and if this is done based on /A if it is done by file name, access is denied. However, if it is done using the /A switch you must un-read only the file and allow it to be deleted*/ if ((dwFlags & DEL_ATTRIBUTES) || (dwFlags & DEL_FORCE)) { if (f->dwFileAttributes & FILE_ATTRIBUTE_READONLY) { /*setting file to normal, not saving old attrs first because the file is going to be deleted anyways so the only thing that matters is that it isn't read only.*/ SetFileAttributes(lpFileName,FILE_ATTRIBUTE_NORMAL); } }
if (dwFlags & DEL_WIPE) { HANDLE file; DWORD temp;#define BufferSize 65536 BYTE buffer[BufferSize]; LONGLONG i; LARGE_INTEGER FileSize;
FileSize.u.HighPart = f->nFileSizeHigh; FileSize.u.LowPart = f->nFileSizeLow;
for(i = 0; i < BufferSize; i++) { buffer[i]=rand() % 256; } file = CreateFile (lpFileName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL); if (file != INVALID_HANDLE_VALUE) { for(i = 0; i < (FileSize.QuadPart - BufferSize); i += BufferSize) { WriteFile (file, buffer, BufferSize, &temp, NULL); ConOutPrintf (_T("%I64d%% %s\r"),(i * (LONGLONG)100)/FileSize.QuadPart,szDeleteWipe); } WriteFile (file, buffer, (DWORD)(FileSize.QuadPart - i), &temp, NULL); ConOutPrintf (_T("100%% %s\n"),szDeleteWipe); CloseHandle (file); } }
return DeleteFile (lpFileName);}
static DWORDDeleteFiles(LPTSTR FileName, DWORD* dwFlags, DWORD dwAttrFlags){ TCHAR szFullPath[MAX_PATH]; TCHAR szFileName[MAX_PATH]; LPTSTR pFilePart; HANDLE hFile; WIN32_FIND_DATA f; BOOL bExclusion; INT res; DWORD dwFiles = 0;
_tcscpy(szFileName, FileName);
if (_tcschr (szFileName, _T('*')) == NULL && IsExistingDirectory (szFileName)) { /* If it doesnt have a \ at the end already then on needs to be added */ if (szFileName[_tcslen(szFileName) - 1] != _T('\\')) _tcscat (szFileName, _T("\\")); /* Add a wildcard after the \ */ _tcscat (szFileName, _T("*")); }
if (!_tcscmp (szFileName, _T("*")) || !_tcscmp (szFileName, _T("*.*")) || (szFileName[_tcslen(szFileName) - 2] == _T('\\') && szFileName[_tcslen(szFileName) - 1] == _T('*'))) { /* well, the user wants to delete everything but if they didnt yes DEL_YES, DEL_QUIET, or DEL_PROMPT then we are going to want to make sure that in fact they want to do that. */
if (!((*dwFlags & DEL_YES) || (*dwFlags & DEL_QUIET) || (*dwFlags & DEL_PROMPT))) { ConOutPrintf (_T("Delete %s, "),szFileName); res = FilePromptYNA (STRING_DEL_HELP2); if ((res == PROMPT_NO) || (res == PROMPT_BREAK)) return 0x80000000; if (res == PROMPT_ALL) *dwFlags |= DEL_YES; } }
GetFullPathName(szFileName, MAX_PATH, szFullPath, &pFilePart);
hFile = FindFirstFile(szFullPath, &f); if (hFile != INVALID_HANDLE_VALUE) { do { bExclusion = FALSE;
/*if it is going to be excluded by - no need to check attrs*/ if (*dwFlags & DEL_ATTRIBUTES && !bExclusion) { /*save if file attr check if user doesnt care about that attr anyways*/ if (dwAttrFlags & ATTR_ARCHIVE && !(f.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)) bExclusion = TRUE; if (dwAttrFlags & ATTR_HIDDEN && !(f.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) bExclusion = TRUE; if (dwAttrFlags & ATTR_SYSTEM && !(f.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) bExclusion = TRUE; if (dwAttrFlags & ATTR_READ_ONLY && !(f.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) bExclusion = TRUE; if (dwAttrFlags & ATTR_N_ARCHIVE && (f.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)) bExclusion = TRUE; if (dwAttrFlags & ATTR_N_HIDDEN && (f.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) bExclusion = TRUE; if (dwAttrFlags & ATTR_N_SYSTEM && (f.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) bExclusion = TRUE; if (dwAttrFlags & ATTR_N_READ_ONLY && (f.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) bExclusion = TRUE; } if (bExclusion) continue;
/* ignore directories */ if (f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
_tcscpy (pFilePart, f.cFileName);
/* We cant delete ourselves */ if (!_tcscmp (CMDPath,szFullPath)) continue;
TRACE("Full filename: %s\n", debugstr_aw(szFullPath));
/* ask for deleting */ if (*dwFlags & DEL_PROMPT) { ConErrResPrintf(STRING_DEL_ERROR5, szFullPath);
res = FilePromptYN (STRING_DEL_ERROR6);
if ((res == PROMPT_NO) || (res == PROMPT_BREAK)) { nErrorLevel = 0; continue; } }
/*user cant ask it to be quiet and tell you what it did*/ if (!(*dwFlags & DEL_QUIET) && !(*dwFlags & DEL_TOTAL)) { ConErrResPrintf(STRING_DEL_ERROR7, szFullPath); }
/* delete the file */ if (*dwFlags & DEL_NOTHING) continue;
if (RemoveFile (szFullPath, *dwFlags, &f)) { dwFiles++; } else { ErrorMessage (GetLastError(), NULL);// FindClose(hFile);// return -1; } } while (FindNextFile (hFile, &f)); FindClose (hFile); } else error_sfile_not_found(szFullPath); return dwFiles;}
static DWORDProcessDirectory(LPTSTR FileName, DWORD* dwFlags, DWORD dwAttrFlags){ TCHAR szFullPath[MAX_PATH]; LPTSTR pFilePart; LPTSTR pSearchPart; HANDLE hFile; WIN32_FIND_DATA f; DWORD dwFiles = 0;
/* Get the full path to the file */ GetFullPathName(FileName, MAX_PATH, szFullPath, &pFilePart);
/* Delete all the files in this directory */ dwFiles = DeleteFiles(szFullPath, dwFlags, dwAttrFlags); if (dwFiles & 0x80000000) return dwFiles;
if (*dwFlags & DEL_SUBDIR) { /* Get just the file name */ pSearchPart = _T("*"); if (!IsExistingDirectory(szFullPath)) { pSearchPart = _tcsrchr(FileName, _T('\\')); if (pSearchPart != NULL) pSearchPart++; else pSearchPart = FileName; }
/* If no wildcard or file was specified and this is a directory, then display all files in it */ if (pFilePart == NULL || IsExistingDirectory(szFullPath)) { pFilePart = &szFullPath[_tcslen(szFullPath)]; if (*(pFilePart-1) != _T('\\')) *pFilePart++ = _T('\\'); _tcscpy(pFilePart, _T("*")); } else { /* strip the filename off of it */ _tcscpy(pFilePart, _T("*")); }
/* Enumerate all the sub-directories */ hFile = FindFirstFile(szFullPath, &f); if (hFile != INVALID_HANDLE_VALUE) { do { if (!(f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || !_tcscmp(f.cFileName, _T(".")) || !_tcscmp(f.cFileName, _T(".."))) continue;
_tcscpy(pFilePart, f.cFileName); _tcscat(pFilePart, _T("\\")); _tcscat(pFilePart, pSearchPart);
dwFiles +=ProcessDirectory(szFullPath, dwFlags, dwAttrFlags); if (dwFiles & 0x80000000) { break; } } while (FindNextFile (hFile, &f)); FindClose (hFile); } }
return dwFiles;}
INT CommandDelete (LPTSTR param){ /*cmd is the command that was given, in this case it will always be "del" or "delete" param is whatever is given after the command*/
LPTSTR *arg = NULL; INT args; INT i; INT nEvalArgs = 0; /* number of evaluated arguments */ DWORD dwFlags = 0; DWORD dwAttrFlags = 0; DWORD dwFiles = 0; LONG ch; TCHAR szOriginalArg[MAX_PATH];
/*checks the first two chars of param to see if it is /? this however allows the following command to not show help "del frog.txt /?" */
if (!StringsLoaded) { LoadStrings(); }
if (!_tcsncmp (param, _T("/?"), 2)) { ConOutResPaging(TRUE,STRING_DEL_HELP1); return 0; }
nErrorLevel = 0;
arg = split (param, &args, FALSE, FALSE);
if (args == 0) { /* only command given */ error_req_param_missing (); freep (arg); return 1; } /* check for options anywhere in command line */ for (i = 0; i < args; i++) { if (*arg[i] == _T('/')) { /*found a command, but check to make sure it has something after it*/ if (_tcslen (arg[i]) >= 2) { ch = _totupper (arg[i][1]); if (ch == _T('N')) { dwFlags |= DEL_NOTHING; } else if (ch == _T('P')) { dwFlags |= DEL_PROMPT; } else if (ch == _T('Q')) { dwFlags |= DEL_QUIET; } else if (ch == _T('F')) { dwFlags |= DEL_FORCE; } else if (ch == _T('S')) { dwFlags |= DEL_SUBDIR; } else if (ch == _T('T')) { dwFlags |= DEL_TOTAL; } else if (ch == _T('W')) { dwFlags |= DEL_WIPE; } else if (ch == _T('Y')) { dwFlags |= DEL_YES; } else if (ch == _T('A')) { dwFlags |= DEL_ATTRIBUTES; /*the proper syntax for /A has a min of 4 chars i.e. /A:R or /A:-H */ if (_tcslen (arg[i]) < 4) { error_invalid_parameter_format(arg[i]); return 0; } ch = _totupper (arg[i][3]); if (_tcslen (arg[i]) == 4) { if (ch == _T('A')) { dwAttrFlags |= ATTR_ARCHIVE; } if (ch == _T('H')) { dwAttrFlags |= ATTR_HIDDEN; } if (ch == _T('S')) { dwAttrFlags |= ATTR_SYSTEM; } if (ch == _T('R')) { dwAttrFlags |= ATTR_READ_ONLY; } } if (_tcslen (arg[i]) == 5) { if (ch == _T('-')) { ch = _totupper (arg[i][4]); if (ch == _T('A')) { dwAttrFlags |= ATTR_N_ARCHIVE; } if (ch == _T('H')) { dwAttrFlags |= ATTR_N_HIDDEN; } if (ch == _T('S')) { dwAttrFlags |= ATTR_N_SYSTEM; } if (ch == _T('R')) { dwAttrFlags |= ATTR_N_READ_ONLY; } } } } }
nEvalArgs++; } }
/* there are only options on the command line --> error!!! there is the same number of args as there is flags, so none of the args were filenames*/ if (args == nEvalArgs) { error_req_param_missing (); freep (arg); return 1; }
/* keep quiet within batch files */ if (bc != NULL) dwFlags |= DEL_QUIET;
/* check for filenames anywhere in command line */ for (i = 0; i < args && !(dwFiles & 0x80000000); i++) { /*this checks to see if it is a flag; if it isn't, we assume it is a file name*/ if ((*arg[i] == _T('/')) || (*arg[i] == _T('-'))) continue;
/* We want to make a copies of the argument */ if (_tcslen(arg[i]) == 2 && arg[i][1] == _T(':')) { /* Check for C: D: ... */ GetRootPath(arg[i], szOriginalArg, MAX_PATH); } else { _tcscpy(szOriginalArg,arg[i]); } dwFiles += ProcessDirectory(szOriginalArg, &dwFlags, dwAttrFlags); }
freep (arg);
/*Based on MS cmd, we only tell what files are being deleted when /S is used */ if (dwFlags & DEL_TOTAL) { dwFiles &= 0x7fffffff; if (dwFiles < 2) { ConOutResPrintf(STRING_DEL_HELP3, dwFiles); } else { ConOutResPrintf(STRING_DEL_HELP4, dwFiles); } }
return 0;}
#endif