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

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

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