]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c
ShellPkg: Fix several GCC compiler warnings
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / Cp.c
1 /** @file
2 Main file for cp 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 // this is later in the file.
18 SHELL_STATUS
19 EFIAPI
20 ValidateAndCopyFiles(
21 IN CONST EFI_SHELL_FILE_INFO *FileList,
22 IN CONST CHAR16 *DestDir,
23 IN BOOLEAN SilentMode,
24 IN BOOLEAN RecursiveMode,
25 IN VOID **Resp
26 );
27
28 /**
29 Function to Copy one file to another location
30
31 If the destination exists the user will be prompted and the result put into *resp
32
33 @param[in] Source pointer to source file name
34 @param[in] Dest pointer to destination file name
35 @param[out] Resp pointer to response from question. Pass back on looped calling
36 @param[in] SilentMode whether to run in quiet mode or not
37
38 @retval SHELL_SUCCESS The source file was copied to the destination
39 **/
40 SHELL_STATUS
41 EFIAPI
42 CopySingleFile(
43 IN CONST CHAR16 *Source,
44 IN CONST CHAR16 *Dest,
45 OUT VOID **Resp,
46 IN BOOLEAN SilentMode
47 )
48 {
49 VOID *Response;
50 UINTN ReadSize;
51 SHELL_FILE_HANDLE SourceHandle;
52 SHELL_FILE_HANDLE DestHandle;
53 EFI_STATUS Status;
54 VOID *Buffer;
55 CHAR16 *TempName;
56 UINTN Size;
57 EFI_SHELL_FILE_INFO *List;
58 SHELL_STATUS ShellStatus;
59
60
61 ASSERT(Resp != NULL);
62
63 SourceHandle = NULL;
64 DestHandle = NULL;
65 Response = *Resp;
66 List = NULL;
67
68 ReadSize = PcdGet16(PcdShellFileOperationSize);
69 // Why bother copying a file to itself
70 if (StrCmp(Source, Dest) == 0) {
71 return (SHELL_SUCCESS);
72 }
73
74 //
75 // Open destination file without create
76 //
77 Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
78
79 //
80 // close file
81 //
82 if (DestHandle != NULL) {
83 ShellCloseFile(&DestHandle);
84 DestHandle = NULL;
85 }
86
87 //
88 // if the destination file existed check response and possibly prompt user
89 //
90 if (!EFI_ERROR(Status)) {
91 if (Response == NULL && !SilentMode) {
92 Status = ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_CP_PROMPT), gShellLevel2HiiHandle, &Response);
93 }
94 //
95 // possibly return based on response
96 //
97 if (!SilentMode) {
98 switch (*(SHELL_PROMPT_RESPONSE*)Response) {
99 case ShellPromptResponseNo:
100 //
101 // return success here so we dont stop the process
102 //
103 return (SHELL_SUCCESS);
104 case ShellPromptResponseCancel:
105 *Resp = Response;
106 //
107 // indicate to stop everything
108 //
109 return (SHELL_ABORTED);
110 case ShellPromptResponseAll:
111 *Resp = Response;
112 case ShellPromptResponseYes:
113 break;
114 default:
115 return SHELL_ABORTED;
116 }
117 }
118 }
119
120 if (ShellIsDirectory(Source) == EFI_SUCCESS) {
121 Status = ShellCreateDirectory(Dest, &DestHandle);
122 if (EFI_ERROR(Status)) {
123 return (SHELL_ACCESS_DENIED);
124 }
125
126 //
127 // Now copy all the files under the directory...
128 //
129 TempName = NULL;
130 Size = 0;
131 StrnCatGrow(&TempName, &Size, Source, 0);
132 StrnCatGrow(&TempName, &Size, L"\\*", 0);
133 ShellOpenFileMetaArg((CHAR16*)TempName, EFI_FILE_MODE_READ, &List);
134 TempName = NULL;
135 StrnCatGrow(&TempName, &Size, Dest, 0);
136 StrnCatGrow(&TempName, &Size, L"\\", 0);
137 ShellStatus = ValidateAndCopyFiles(List, TempName, SilentMode, TRUE, Resp);
138 ShellCloseFileMetaArg(&List);
139 FreePool(TempName);
140 Size = 0;
141 } else {
142 //
143 // open file with create enabled
144 //
145 Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
146 if (EFI_ERROR(Status)) {
147 return (SHELL_ACCESS_DENIED);
148 }
149
150 //
151 // open source file
152 //
153 Status = ShellOpenFileByName(Source, &SourceHandle, EFI_FILE_MODE_READ, 0);
154 ASSERT_EFI_ERROR(Status);
155
156 //
157 // copy data between files
158 //
159 Buffer = AllocateZeroPool(ReadSize);
160 ASSERT(Buffer != NULL);
161 while (ReadSize == PcdGet16(PcdShellFileOperationSize) && !EFI_ERROR(Status)) {
162 Status = ShellReadFile(SourceHandle, &ReadSize, Buffer);
163 ASSERT_EFI_ERROR(Status);
164 Status = ShellWriteFile(DestHandle, &ReadSize, Buffer);
165 }
166 }
167
168 //
169 // close files
170 //
171 if (DestHandle != NULL) {
172 ShellCloseFile(&DestHandle);
173 DestHandle = NULL;
174 }
175 if (SourceHandle != NULL) {
176 ShellCloseFile(&SourceHandle);
177 SourceHandle = NULL;
178 }
179
180 //
181 // return
182 //
183 return (SHELL_SUCCESS);
184 }
185
186 /**
187 function to take a list of files to copy and a destination location and do
188 the verification and copying of those files to that location. This function
189 will report any errors to the user and halt.
190
191 The key is to have this function called ONLY once. this allows for the parameter
192 verification to happen correctly.
193
194 @param[in] FileList A LIST_ENTRY* based list of files to move
195 @param[in] DestDir the destination location
196
197 @retval SHELL_SUCCESS the files were all moved.
198 @retval SHELL_INVALID_PARAMETER a parameter was invalid
199 @retval SHELL_SECURITY_VIOLATION a security violation ocurred
200 @retval SHELL_WRITE_PROTECTED the destination was write protected
201 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
202 **/
203 SHELL_STATUS
204 EFIAPI
205 ValidateAndCopyFiles(
206 IN CONST EFI_SHELL_FILE_INFO *FileList,
207 IN CONST CHAR16 *DestDir,
208 IN BOOLEAN SilentMode,
209 IN BOOLEAN RecursiveMode,
210 IN VOID **Resp
211 )
212 {
213 CHAR16 *HiiOutput;
214 CHAR16 *HiiResultOk;
215 CONST EFI_SHELL_FILE_INFO *Node;
216 SHELL_STATUS ShellStatus;
217 CHAR16 *DestPath;
218 VOID *Response;
219 UINTN PathLen;
220 CONST CHAR16 *Cwd;
221 CONST CHAR16 *TempLocation;
222 UINTN NewSize;
223
224 if (Resp == NULL) {
225 Response = NULL;
226 } else {
227 Response = *Resp;
228 }
229
230 DestPath = NULL;
231 ShellStatus = SHELL_SUCCESS;
232 PathLen = 0;
233 Cwd = ShellGetCurrentDir(NULL);
234
235 ASSERT(FileList != NULL);
236 ASSERT(DestDir != NULL);
237
238 //
239 // If we are trying to copy multiple files... make sure we got a directory for the target...
240 //
241 if (EFI_ERROR(ShellIsDirectory(DestDir)) && FileList->Link.ForwardLink != FileList->Link.BackLink) {
242 //
243 // Error for destination not a directory
244 //
245 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir);
246 return (SHELL_INVALID_PARAMETER);
247 }
248 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
249 ; !IsNull(&FileList->Link, &Node->Link)
250 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
251 ){
252 //
253 // skip the directory traversing stuff...
254 //
255 if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
256 continue;
257 }
258
259 NewSize = StrSize(DestDir);
260 NewSize += StrSize(Node->FileName);
261 NewSize += StrSize(Cwd);
262 if (NewSize > PathLen) {
263 PathLen = NewSize;
264 }
265
266 //
267 // Make sure got -r if required
268 //
269 if (!RecursiveMode && !EFI_ERROR(ShellIsDirectory(Node->FullName))) {
270 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_REQ), gShellLevel2HiiHandle);
271 return (SHELL_INVALID_PARAMETER);
272 }
273
274 //
275 // make sure got dest as dir if needed
276 //
277 if (!EFI_ERROR(ShellIsDirectory(Node->FullName)) && EFI_ERROR(ShellIsDirectory(DestDir))) {
278 //
279 // Error for destination not a directory
280 //
281 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir);
282 return (SHELL_INVALID_PARAMETER);
283 }
284 }
285
286 HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_CP_OUTPUT), NULL);
287 HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL);
288 DestPath = AllocatePool(PathLen);
289
290 //
291 // Go through the list of files to copy...
292 //
293 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
294 ; !IsNull(&FileList->Link, &Node->Link)
295 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
296 ){
297 if (ShellGetExecutionBreakFlag()) {
298 break;
299 }
300 ASSERT(Node->FileName != NULL);
301 ASSERT(Node->FullName != NULL);
302
303 //
304 // skip the directory traversing stuff...
305 //
306 if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
307 continue;
308 }
309
310 if (FileList->Link.ForwardLink == FileList->Link.BackLink // 1 item
311 && EFI_ERROR(ShellIsDirectory(DestDir)) // not an existing directory
312 ) {
313 ASSERT(StrStr(DestDir, L":") == NULL);
314 //
315 // simple copy of a single file
316 //
317 StrCpy(DestPath, Cwd);
318 if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') {
319 StrCat(DestPath, L"\\");
320 } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') {
321 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
322 }
323 StrCat(DestPath, DestDir);
324 } else {
325 //
326 // we have multiple files or a directory in the DestDir
327 //
328 if (StrStr(DestDir, L":") == NULL) {
329 StrCpy(DestPath, Cwd);
330 if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') {
331 StrCat(DestPath, L"\\");
332 } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') {
333 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
334 }
335 StrCat(DestPath, DestDir);
336 if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') {
337 StrCat(DestPath, L"\\");
338 } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') {
339 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
340 }
341 StrCat(DestPath, Node->FileName);
342
343 } else {
344 StrCpy(DestPath, DestDir);
345 if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') {
346 StrCat(DestPath, L"\\");
347 } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') {
348 ((CHAR16*)DestDir)[StrLen(DestDir)-1] = CHAR_NULL;
349 }
350 StrCat(DestPath, Node->FileName);
351 }
352 }
353
354 //
355 // Make sure the path exists
356 //
357 if (EFI_ERROR(VerifyIntermediateDirectories(DestPath))) {
358 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_WNF), gShellLevel2HiiHandle);
359 ShellStatus = SHELL_DEVICE_ERROR;
360 break;
361 }
362
363 if ( !EFI_ERROR(ShellIsDirectory(Node->FullName))
364 && !EFI_ERROR(ShellIsDirectory(DestPath))
365 && StrniCmp(Node->FullName, DestPath, StrLen(DestPath)) == NULL
366 ){
367 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_PARENT), gShellLevel2HiiHandle);
368 ShellStatus = SHELL_INVALID_PARAMETER;
369 break;
370 }
371 if (StringNoCaseCompare(&Node->FullName, &DestPath) == 0) {
372 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle);
373 ShellStatus = SHELL_INVALID_PARAMETER;
374 break;
375 }
376
377 if ((TempLocation = StrniCmp(Node->FullName, DestPath, StrLen(Node->FullName))) == 0
378 && (DestPath[StrLen(Node->FullName)] == CHAR_NULL || DestPath[StrLen(Node->FullName)] == L'\\')
379 ) {
380 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle);
381 ShellStatus = SHELL_INVALID_PARAMETER;
382 break;
383 }
384
385 CleanPath(DestPath);
386
387 ShellPrintEx(-1, -1, HiiOutput, Node->FullName, DestPath);
388
389 //
390 // copy single file...
391 //
392 ShellStatus = CopySingleFile(Node->FullName, DestPath, &Response, SilentMode);
393 if (ShellStatus != SHELL_SUCCESS) {
394 break;
395 }
396 }
397 if (ShellStatus == SHELL_SUCCESS && Resp == NULL) {
398 ShellPrintEx(-1, -1, L"%s", HiiResultOk);
399 }
400
401 SHELL_FREE_NON_NULL(DestPath);
402 SHELL_FREE_NON_NULL(HiiOutput);
403 SHELL_FREE_NON_NULL(HiiResultOk);
404 if (Resp != NULL) {
405 SHELL_FREE_NON_NULL(Response);
406 }
407
408 return (ShellStatus);
409 }
410
411 SHELL_STATUS
412 EFIAPI
413 ProcessValidateAndCopyFiles(
414 IN EFI_SHELL_FILE_INFO *FileList,
415 IN CONST CHAR16 *DestDir,
416 IN BOOLEAN SilentMode,
417 IN BOOLEAN RecursiveMode
418 )
419 {
420 SHELL_STATUS ShellStatus;
421 EFI_SHELL_FILE_INFO *List;
422 EFI_STATUS Status;
423 EFI_FILE_INFO *FileInfo;
424
425 List = NULL;
426
427 Status = ShellOpenFileMetaArg((CHAR16*)DestDir, EFI_FILE_MODE_READ, &List);
428 if (List != NULL && List->Link.ForwardLink != List->Link.BackLink) {
429 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, DestDir);
430 ShellStatus = SHELL_INVALID_PARAMETER;
431 ShellCloseFileMetaArg(&List);
432 } else if (List != NULL) {
433 ASSERT(List != NULL);
434 ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink) != NULL);
435 ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName != NULL);
436 FileInfo = NULL;
437 FileInfo = gEfiShellProtocol->GetFileInfo(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->Handle);
438 ASSERT(FileInfo != NULL);
439 if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) == 0) {
440 ShellStatus = ValidateAndCopyFiles(FileList, ((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName, SilentMode, RecursiveMode, NULL);
441 } else {
442 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_ERROR), gShellLevel2HiiHandle);
443 ShellStatus = SHELL_ACCESS_DENIED;
444 }
445 SHELL_FREE_NON_NULL(FileInfo);
446 ShellCloseFileMetaArg(&List);
447 } else {
448 ShellStatus = ValidateAndCopyFiles(FileList, DestDir, SilentMode, RecursiveMode, NULL);
449 }
450
451 return (ShellStatus);
452 }
453
454 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
455 {L"-r", TypeFlag},
456 {L"-q", TypeFlag},
457 {NULL, TypeMax}
458 };
459
460 /**
461 Function for 'cp' command.
462
463 @param[in] ImageHandle Handle to the Image (NULL if Internal).
464 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
465 **/
466 SHELL_STATUS
467 EFIAPI
468 ShellCommandRunCp (
469 IN EFI_HANDLE ImageHandle,
470 IN EFI_SYSTEM_TABLE *SystemTable
471 )
472 {
473 EFI_STATUS Status;
474 LIST_ENTRY *Package;
475 CHAR16 *ProblemParam;
476 SHELL_STATUS ShellStatus;
477 UINTN ParamCount;
478 UINTN LoopCounter;
479 EFI_SHELL_FILE_INFO *FileList;
480 BOOLEAN SilentMode;
481 BOOLEAN RecursiveMode;
482 CONST CHAR16 *Cwd;
483
484 ProblemParam = NULL;
485 ShellStatus = SHELL_SUCCESS;
486 ParamCount = 0;
487 FileList = NULL;
488
489 //
490 // initialize the shell lib (we must be in non-auto-init...)
491 //
492 Status = ShellInitialize();
493 ASSERT_EFI_ERROR(Status);
494
495 Status = CommandInit();
496 ASSERT_EFI_ERROR(Status);
497
498 //
499 // parse the command line
500 //
501 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
502 if (EFI_ERROR(Status)) {
503 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
504 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
505 FreePool(ProblemParam);
506 ShellStatus = SHELL_INVALID_PARAMETER;
507 } else {
508 ASSERT(FALSE);
509 }
510 } else {
511 //
512 // check for "-?"
513 //
514 if (ShellCommandLineGetFlag(Package, L"-?")) {
515 ASSERT(FALSE);
516 }
517
518 //
519 // Initialize SilentMode and RecursiveMode
520 //
521 if (gEfiShellProtocol->BatchIsActive()) {
522 SilentMode = TRUE;
523 } else {
524 SilentMode = ShellCommandLineGetFlag(Package, L"-q");
525 }
526 RecursiveMode = ShellCommandLineGetFlag(Package, L"-r");
527
528 switch (ParamCount = ShellCommandLineGetCount(Package)) {
529 case 0:
530 case 1:
531 //
532 // we have insufficient parameters
533 //
534 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
535 ShellStatus = SHELL_INVALID_PARAMETER;
536 break;
537 case 2:
538 //
539 // must have valid CWD for single parameter...
540 //
541 Cwd = ShellGetCurrentDir(NULL);
542 if (Cwd == NULL){
543 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
544 ShellStatus = SHELL_INVALID_PARAMETER;
545 } else {
546 Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
547 if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {
548 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));
549 ShellStatus = SHELL_NOT_FOUND;
550 } else {
551 ShellStatus = ProcessValidateAndCopyFiles(FileList, Cwd, SilentMode, RecursiveMode);
552 }
553 }
554
555 break;
556 default:
557 //
558 // Make a big list of all the files...
559 //
560 for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount && ShellStatus == SHELL_SUCCESS ; LoopCounter++) {
561 if (ShellGetExecutionBreakFlag()) {
562 break;
563 }
564 Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
565 if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {
566 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));
567 ShellStatus = SHELL_NOT_FOUND;
568 }
569 }
570 //
571 // now copy them all...
572 //
573 if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
574 ShellStatus = ProcessValidateAndCopyFiles(FileList, ShellCommandCleanPath((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount)), SilentMode, RecursiveMode);
575 Status = ShellCloseFileMetaArg(&FileList);
576 if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
577 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1), ShellStatus|MAX_BIT);
578 ShellStatus = SHELL_ACCESS_DENIED;
579 }
580 }
581
582 break;
583 } // switch on parameter count
584
585 if (FileList != NULL) {
586 ShellCloseFileMetaArg(&FileList);
587 }
588
589 //
590 // free the command line package
591 //
592 ShellCommandLineFreeVarList (Package);
593 }
594
595 if (ShellGetExecutionBreakFlag()) {
596 return (SHELL_ABORTED);
597 }
598
599 return (ShellStatus);
600 }
601