update for HEAD-2003091401
[reactos.git] / subsys / system / cmd / del.c
1 /*
2  *  DEL.C - del internal command.
3  *
4  *
5  *  History:
6  *
7  *    06/29/98 (Rob Lake rlake@cs.mun.ca)
8  *        rewrote del to support wildcards
9  *        added my name to the contributors
10  *
11  *    07/13/98 (Rob Lake)
12  *        fixed bug that caused del not to delete file with out
13  *        attribute. moved set, del, ren, and ver to there own files
14  *
15  *    27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
16  *        added config.h include
17  *
18  *    09-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
19  *        Fixed command line parsing bugs.
20  *
21  *    21-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
22  *        Started major rewrite using a new structure.
23  *
24  *    03-Feb-1999 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
25  *        First working version.
26  *
27  *    30-Mar-1999 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
28  *        Added quiet ("/Q"), wipe ("/W") and zap ("/Z") option.
29  *
30  *    06-Nov-1999 (Eric Kohl <ekohl@abo.rhein-zeiung.de>)
31  *        Little fix to keep DEL quiet inside batch files.
32  */
33
34 #include "config.h"
35
36 #ifdef INCLUDE_CMD_DEL
37
38 #include <windows.h>
39 #include <tchar.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <ctype.h>
43
44 #include "cmd.h"
45 #include "batch.h"
46
47
48 enum
49 {
50         DEL_ATTRIBUTES = 0x001,   /* /A : not implemented */
51         DEL_ERROR      = 0x002,   /* /E : not implemented */
52         DEL_NOTHING    = 0x004,   /* /N */
53         DEL_PROMPT     = 0x008,   /* /P : not implemented */
54         DEL_QUIET      = 0x010,   /* /Q */
55         DEL_SUBDIR     = 0x020,   /* /S : not implemented */
56         DEL_TOTAL      = 0x040,   /* /T */
57         DEL_WIPE       = 0x080,   /* /W */
58         DEL_EMPTYDIR   = 0x100,   /* /X : not implemented */
59         DEL_YES        = 0x200,   /* /Y : not implemented */
60         DEL_ZAP        = 0x400    /* /Z */
61 };
62
63
64
65 static BOOL
66 RemoveFile (LPTSTR lpFileName, DWORD dwFlags)
67 {
68         if (dwFlags & DEL_WIPE)
69         {
70
71                 /* FIXME: Wipe the given file */
72
73         }
74
75         return DeleteFile (lpFileName);
76 }
77
78
79 INT CommandDelete (LPTSTR cmd, LPTSTR param)
80 {
81         TCHAR szFullPath[MAX_PATH];
82         LPTSTR pFilePart;
83         LPTSTR *arg = NULL;
84         INT args;
85         INT i;
86         INT   nEvalArgs = 0; /* nunber of evaluated arguments */
87         DWORD dwFlags = 0;
88         DWORD dwFiles = 0;
89
90         HANDLE hFile;
91         WIN32_FIND_DATA f;
92
93         if (!_tcsncmp (param, _T("/?"), 2))
94         {
95                 ConOutPuts (_T("Deletes one or more files.\n"
96                                "\n"
97                                "DEL [/N /P /T /Q /W /Z] file ...\n"
98                                "DELETE [/N /P /T /Q /W /Z] file ...\n"
99                                "ERASE [/N /P /T /Q /W /Z] file ...\n"
100                                "\n"
101                                "  file  Specifies the file(s) to delete.\n"
102                                "\n"
103                                "  /N    Nothing.\n"
104                                "  /P    Prompts for confirmation before deleting each file.\n"
105                                "        (Not implemented yet!)\n"
106                                "  /T    Display total number of deleted files and freed disk space.\n"
107                                "  /Q    Quiet.\n"
108                                "  /W    Wipe. Overwrite the file with zeros before deleting it.\n"
109                                "  /Z    Zap (delete hidden, read-only and system files).\n"));
110
111                 return 0;
112         }
113
114         arg = split (param, &args, FALSE);
115
116         if (args > 0)
117         {
118                 /* check for options anywhere in command line */
119                 for (i = 0; i < args; i++)
120                 {
121                         if (*arg[i] == _T('/'))
122                         {
123                                 if (_tcslen (arg[i]) >= 2)
124                                 {
125                                         switch (_totupper (arg[i][1]))
126                                         {
127                                                 case _T('N'):
128                                                         dwFlags |= DEL_NOTHING;
129                                                         break;
130
131                                                 case _T('P'):
132                                                         dwFlags |= DEL_PROMPT;
133                                                         break;
134
135                                                 case _T('Q'):
136                                                         dwFlags |= DEL_QUIET;
137                                                         break;
138
139                                                 case _T('S'):
140                                                         dwFlags |= DEL_SUBDIR;
141                                                         break;
142
143                                                 case _T('T'):
144                                                         dwFlags |= DEL_TOTAL;
145                                                         break;
146
147                                                 case _T('W'):
148                                                         dwFlags |= DEL_WIPE;
149                                                         break;
150
151                                                 case _T('Z'):
152                                                         dwFlags |= DEL_ZAP;
153                                                         break;
154                                         }
155
156                                 }
157
158                                 nEvalArgs++;
159                         }
160                 }
161
162                 /* there are only options on the command line --> error!!! */
163                 if (args == nEvalArgs)
164                 {
165                         error_req_param_missing ();
166                         freep (arg);
167                         return 1;
168                 }
169
170                 /* keep quiet within batch files */
171                 if (bc != NULL)
172                         dwFlags |= DEL_QUIET;
173
174                 /* check for filenames anywhere in command line */
175                 for (i = 0; i < args; i++)
176                 {
177                         if (!_tcscmp (arg[i], _T("*")) ||
178                             !_tcscmp (arg[i], _T("*.*")))
179                         {
180                                 INT res;
181
182                                 res = FilePromptYN (_T("All files in directory will be deleted!\n"
183                                                        "Are you sure (Y/N)?"));
184                                 if ((res == PROMPT_NO) ||
185                                     (res == PROMPT_BREAK))
186                                         break;
187                         }
188
189                         if (*arg[i] != _T('/'))
190                         {
191 #ifdef _DEBUG
192                                 ConErrPrintf (_T("File: %s\n"), arg[i]);
193 #endif
194
195                                 if (_tcschr (arg[i], _T('*')) || _tcschr (arg[i], _T('?')))
196                                 {
197                                         /* wildcards in filespec */
198 #ifdef _DEBUG
199                                         ConErrPrintf (_T("Wildcards!\n\n"));
200 #endif
201
202                                         GetFullPathName (arg[i],
203                                                          MAX_PATH,
204                                                          szFullPath,
205                                                          &pFilePart);
206
207 #ifdef _DEBUG
208                                         ConErrPrintf (_T("Full path: %s\n"), szFullPath);
209                                         ConErrPrintf (_T("File part: %s\n"), pFilePart);
210 #endif
211
212                                         hFile = FindFirstFile (szFullPath, &f);
213                                         if (hFile == INVALID_HANDLE_VALUE)
214                                         {
215                                                 error_file_not_found ();
216                                                 freep (arg);
217                                                 return 0;
218                                         }
219
220                                         do
221                                         {
222                                                 /* ignore "." and ".." */
223                                                 if (!_tcscmp (f.cFileName, _T(".")) ||
224                                                         !_tcscmp (f.cFileName, _T("..")))
225                                                         continue;
226
227                                                 _tcscpy (pFilePart, f.cFileName);
228
229 #ifdef _DEBUG
230                                                 ConErrPrintf (_T("Full filename: %s\n"), szFullPath);
231 #endif
232
233                                                 if (!(dwFlags & DEL_QUIET) && !(dwFlags & DEL_TOTAL))
234                                                         ConErrPrintf (_T("Deleting: %s\n"), szFullPath);
235
236                                                 /* delete the file */
237                                                 if (!(dwFlags & DEL_NOTHING))
238                                                 {
239                                                         if (RemoveFile (szFullPath, dwFlags))
240                                                         {
241                                                                 dwFiles++;
242                                                         }
243                                                         else
244                                                         {
245                                                                 if (dwFlags & DEL_ZAP)
246                                                                 {
247                                                                         if (SetFileAttributes (szFullPath, 0))
248                                                                         {
249                                                                                 if (RemoveFile (szFullPath, dwFlags))
250                                                                                 {
251                                                                                         dwFiles++;
252                                                                                 }
253                                                                                 else
254                                                                                 {
255                                                                                         ErrorMessage (GetLastError(), _T(""));
256                                                                                 }
257                                                                         }
258                                                                         else
259                                                                         {
260                                                                                 ErrorMessage (GetLastError(), _T(""));
261                                                                         }
262                                                                 }
263                                                                 else
264                                                                 {
265                                                                         ErrorMessage (GetLastError(), _T(""));
266                                                                 }
267                                                         }
268                                                 }
269                                         }
270                                         while (FindNextFile (hFile, &f));
271                                         FindClose (hFile);
272                                 }
273                                 else
274                                 {
275                                         /* no wildcards in filespec */
276 #ifdef _DEBUG
277                                         ConErrPrintf (_T("No Wildcards!\n"));
278 #endif
279                                         GetFullPathName (arg[i],
280                                                          MAX_PATH,
281                                                          szFullPath,
282                                                          &pFilePart);
283 #ifdef _DEBUG
284                                         ConErrPrintf (_T("Full path: %s\n"), szFullPath);
285 #endif
286                                         if (!(dwFlags & DEL_QUIET) && !(dwFlags & DEL_TOTAL))
287                                                 ConOutPrintf (_T("Deleting %s\n"), szFullPath);
288
289                                         if (!(dwFlags & DEL_NOTHING))
290                                         {
291                                                 if (RemoveFile (szFullPath, dwFlags))
292                                                 {
293                                                         dwFiles++;
294                                                 }
295                                                 else
296                                                 {
297                                                         if (dwFlags & DEL_ZAP)
298                                                         {
299                                                                 if (SetFileAttributes (szFullPath, 0))
300                                                                 {
301                                                                         if (RemoveFile (szFullPath, dwFlags))
302                                                                         {
303                                                                                 dwFiles++;
304                                                                         }
305                                                                         else
306                                                                         {
307                                                                                 ErrorMessage (GetLastError(), _T(""));
308                                                                         }
309                                                                 }
310                                                                 else
311                                                                 {
312                                                                         ErrorMessage (GetLastError(), _T(""));
313                                                                 }
314                                                         }
315                                                         else
316                                                         {
317                                                                 ErrorMessage (GetLastError(), _T(""));
318                                                         }
319                                                 }
320                                         }
321                                 }
322                         }
323                 }
324         }
325         else
326         {
327                 /* only command given */
328                 error_req_param_missing ();
329                 freep (arg);
330                 return 1;
331         }
332
333         freep (arg);
334
335         if (!(dwFlags & DEL_QUIET))
336         {
337                 if (dwFiles == 0)
338                         ConOutPrintf (_T("    0 files deleted\n"));
339                 else
340                         ConOutPrintf (_T("    %lu file%s deleted\n"),
341                                       dwFiles,
342                                       (dwFiles == 1) ? _T("") : _T("s"));
343         }
344
345         return 0;
346 }
347
348 #endif