]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c
udk2010.up2.shell initial release.
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / Rm.c
1 /** @file
2 Main file for attrib shell level 2 function.
3
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "UefiShellLevel2CommandsLib.h"
16
17 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
18 {L"-q", TypeFlag},
19 {NULL, TypeMax}
20 };
21
22 BOOLEAN
23 EFIAPI
24 IsDirectoryEmpty (
25 IN EFI_HANDLE FileHandle
26 )
27 {
28 EFI_STATUS Status;
29 EFI_FILE_INFO *FileInfo;
30 BOOLEAN NoFile;
31 BOOLEAN RetVal;
32
33 RetVal = TRUE;
34 NoFile = FALSE;
35
36 for (Status = FileHandleFindFirstFile(FileHandle, &FileInfo)
37 ; !NoFile
38 ; Status = FileHandleFindNextFile(FileHandle, FileInfo, &NoFile)
39 ){
40 if (StrStr(FileInfo->FileName, L".") != FileInfo->FileName
41 &&StrStr(FileInfo->FileName, L"..") != FileInfo->FileName) {
42 RetVal = FALSE;
43 }
44 }
45 return (RetVal);
46 }
47
48 SHELL_STATUS
49 EFIAPI
50 CascadeDelete(
51 IN EFI_SHELL_FILE_INFO *Node,
52 IN CONST BOOLEAN Quiet
53 )
54 {
55 SHELL_STATUS ShellStatus;
56 EFI_SHELL_FILE_INFO *List;
57 EFI_SHELL_FILE_INFO *Node2;
58 EFI_STATUS Status;
59 SHELL_PROMPT_RESPONSE *Resp;
60
61 Resp = NULL;
62 ShellStatus = SHELL_SUCCESS;
63 List = NULL;
64 Status = EFI_SUCCESS;
65
66 if ((Node->Info->Attribute & EFI_FILE_READ_ONLY) == EFI_FILE_READ_ONLY) {
67 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DETELE_RO), gShellLevel2HiiHandle, Node->FullName);
68 return (SHELL_ACCESS_DENIED);
69 }
70
71 if ((Node->Info->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {
72 if (!IsDirectoryEmpty(Node->Handle)) {
73 if (!Quiet) {
74 Status = ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_RM_LOG_DELETE_CONF), gShellLevel2HiiHandle, Node->FullName);
75 Status = ShellPromptForResponse(ShellPromptResponseTypeYesNo, NULL, (VOID**)&Resp);
76 ASSERT_EFI_ERROR(Status);
77 ASSERT(Resp != NULL);
78 if (EFI_ERROR(Status) || *Resp != ShellPromptResponseYes) {
79 SHELL_FREE_NON_NULL(Resp);
80 return (SHELL_ABORTED);
81 }
82 SHELL_FREE_NON_NULL(Resp);
83 }
84 //
85 // empty out the directory
86 //
87 Status = gEfiShellProtocol->FindFilesInDir(Node->Handle, &List);
88 if (EFI_ERROR(Status)) {
89 if (List!=NULL) {
90 gEfiShellProtocol->FreeFileList(&List);
91 }
92 return (SHELL_DEVICE_ERROR);
93 }
94 for (Node2 = (EFI_SHELL_FILE_INFO *)GetFirstNode(&List->Link)
95 ; !IsNull(&List->Link, &Node2->Link)
96 ; Node2 = (EFI_SHELL_FILE_INFO *)GetNextNode(&List->Link, &Node2->Link)
97 ){
98 //
99 // skip the directory traversing stuff...
100 //
101 if (StrCmp(Node2->FileName, L".") == 0 || StrCmp(Node2->FileName, L"..") == 0) {
102 continue;
103 }
104 Node2->Status = gEfiShellProtocol->OpenFileByName (Node2->FullName, &Node2->Handle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE);
105 ShellStatus = CascadeDelete(Node2, Quiet);
106 if (ShellStatus != SHELL_SUCCESS) {
107 if (List!=NULL) {
108 gEfiShellProtocol->FreeFileList(&List);
109 }
110 return (ShellStatus);
111 }
112 }
113 if (List!=NULL) {
114 gEfiShellProtocol->FreeFileList(&List);
115 }
116 }
117 }
118
119 if (!(StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0)) {
120 //
121 // now delete the current node...
122 //
123 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE), gShellLevel2HiiHandle, Node->FullName);
124 Status = gEfiShellProtocol->DeleteFile(Node->Handle);
125 Node->Handle = NULL;
126 }
127
128 //
129 // We cant allow for the warning here!
130 //
131 if (Status != EFI_SUCCESS){
132 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR), gShellLevel2HiiHandle, Status);
133 return (SHELL_ACCESS_DENIED);
134 } else {
135 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_COMP), gShellLevel2HiiHandle);
136 return (SHELL_SUCCESS);
137 }
138 }
139
140 BOOLEAN
141 EFIAPI
142 IsValidDeleteTarget(
143 IN CONST EFI_SHELL_FILE_INFO *List,
144 IN CONST EFI_SHELL_FILE_INFO *Node,
145 IN CONST LIST_ENTRY *Package
146 )
147 {
148 CONST CHAR16 *TempLocation;
149 CHAR16 *Temp2;
150 UINTN Size;
151
152 TempLocation = StrStr(Node->FullName, L":");
153 if (StrLen(TempLocation) == 2) {
154 //
155 // Deleting the root directory is invalid.
156 //
157 return (FALSE);
158 }
159 TempLocation = ShellGetCurrentDir(NULL);
160 Size = 0;
161 Temp2 = NULL;
162 StrnCatGrow(&Temp2, &Size, TempLocation, 0);
163 if (StrStr(Temp2, Node->FullName) != NULL) {
164 FreePool(Temp2);
165 return (FALSE);
166 }
167 FreePool(Temp2);
168
169 return (TRUE);
170 }
171
172 /**
173 Function for 'rm' command.
174
175 @param[in] ImageHandle Handle to the Image (NULL if Internal).
176 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
177 **/
178 SHELL_STATUS
179 EFIAPI
180 ShellCommandRunRm (
181 IN EFI_HANDLE ImageHandle,
182 IN EFI_SYSTEM_TABLE *SystemTable
183 )
184 {
185 EFI_STATUS Status;
186 LIST_ENTRY *Package;
187 CHAR16 *ProblemParam;
188 CONST CHAR16 *Param;
189 SHELL_STATUS ShellStatus;
190 UINTN ParamCount;
191 EFI_SHELL_FILE_INFO *FileList;
192 EFI_SHELL_FILE_INFO *Node;
193
194 ProblemParam = NULL;
195 ShellStatus = SHELL_SUCCESS;
196 ParamCount = 0;
197 FileList = NULL;
198
199 //
200 // initialize the shell lib (we must be in non-auto-init...)
201 //
202 Status = ShellInitialize();
203 ASSERT_EFI_ERROR(Status);
204
205 //
206 // parse the command line
207 //
208 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
209 if (EFI_ERROR(Status)) {
210 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
211 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
212 FreePool(ProblemParam);
213 ShellStatus = SHELL_INVALID_PARAMETER;
214 } else {
215 ASSERT(FALSE);
216 }
217 } else {
218 //
219 // check for "-?"
220 //
221 if (ShellCommandLineGetFlag(Package, L"-?")) {
222 ASSERT(FALSE);
223 }
224 if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
225 //
226 // we insufficient parameters
227 //
228 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
229 ShellStatus = SHELL_INVALID_PARAMETER;
230 } else {
231 //
232 // get a list with each file specified by parameters
233 // if parameter is a directory then add all the files below it to the list
234 //
235 for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)
236 ; Param != NULL
237 ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)
238 ){
239 Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
240 if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {
241 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, (CHAR16*)Param);
242 ShellStatus = SHELL_NOT_FOUND;
243 break;
244 }
245 }
246
247 if (ShellStatus == SHELL_SUCCESS){
248 //
249 // loop through the list and make sure we are not aborting...
250 //
251 for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)
252 ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
253 ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
254 ){
255 //
256 // skip the directory traversing stuff...
257 //
258 if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
259 continue;
260 }
261
262 //
263 // do the deleting of nodes
264 //
265 if (EFI_ERROR(Node->Status)){
266 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR2), gShellLevel2HiiHandle, Node->Status);
267 ShellStatus = SHELL_ACCESS_DENIED;
268 break;
269 }
270 if (!IsValidDeleteTarget(FileList, Node, Package)) {
271 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR3), gShellLevel2HiiHandle, Node->FullName);
272 ShellStatus = SHELL_INVALID_PARAMETER;
273 break;
274 }
275
276 ShellStatus = CascadeDelete(Node, ShellCommandLineGetFlag(Package, L"-q"));
277 }
278 }
279 //
280 // Free the fileList
281 //
282 if (FileList != NULL) {
283 Status = ShellCloseFileMetaArg(&FileList);
284 }
285 FileList = NULL;
286 }
287
288 //
289 // free the command line package
290 //
291 ShellCommandLineFreeVarList (Package);
292 }
293
294 return (ShellStatus);
295 }
296