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