2 Main file for cp shell level 2 function.
4 Copyright (c) 2009 - 2013, 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
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.
15 #include "UefiShellLevel2CommandsLib.h"
16 #include <Guid/FileSystemInfo.h>
17 #include <Guid/FileSystemVolumeLabelInfo.h>
20 Function to take a list of files to copy and a destination location and do
21 the verification and copying of those files to that location. This function
22 will report any errors to the user and halt.
24 @param[in] FileList A LIST_ENTRY* based list of files to move.
25 @param[in] DestDir The destination location.
26 @param[in] SilentMode TRUE to eliminate screen output.
27 @param[in] RecursiveMode TRUE to copy directories.
28 @param[in] Resp The response to the overwrite query (if always).
30 @retval SHELL_SUCCESS the files were all moved.
31 @retval SHELL_INVALID_PARAMETER a parameter was invalid
32 @retval SHELL_SECURITY_VIOLATION a security violation ocurred
33 @retval SHELL_WRITE_PROTECTED the destination was write protected
34 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
39 IN CONST EFI_SHELL_FILE_INFO
*FileList
,
40 IN CONST CHAR16
*DestDir
,
41 IN BOOLEAN SilentMode
,
42 IN BOOLEAN RecursiveMode
,
47 Function to Copy one file to another location
49 If the destination exists the user will be prompted and the result put into *resp
51 @param[in] Source pointer to source file name
52 @param[in] Dest pointer to destination file name
53 @param[out] Resp pointer to response from question. Pass back on looped calling
54 @param[in] SilentMode whether to run in quiet mode or not
56 @retval SHELL_SUCCESS The source file was copied to the destination
61 IN CONST CHAR16
*Source
,
62 IN CONST CHAR16
*Dest
,
69 SHELL_FILE_HANDLE SourceHandle
;
70 SHELL_FILE_HANDLE DestHandle
;
75 EFI_SHELL_FILE_INFO
*List
;
76 SHELL_STATUS ShellStatus
;
77 UINT64 SourceFileSize
;
79 EFI_FILE_PROTOCOL
*DestVolumeFP
;
80 EFI_FILE_SYSTEM_INFO
*DestVolumeInfo
;
81 UINTN DestVolumeInfoSize
;
89 DestVolumeInfo
= NULL
;
90 ShellStatus
= SHELL_SUCCESS
;
92 ReadSize
= PcdGet32(PcdShellFileOperationSize
);
93 // Why bother copying a file to itself
94 if (StrCmp(Source
, Dest
) == 0) {
95 return (SHELL_SUCCESS
);
99 // if the destination file existed check response and possibly prompt user
101 if (ShellFileExists(Dest
) == EFI_SUCCESS
) {
102 if (Response
== NULL
&& !SilentMode
) {
103 Status
= ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel
, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR
), gShellLevel2HiiHandle
, &Response
);
106 // possibly return based on response
109 switch (*(SHELL_PROMPT_RESPONSE
*)Response
) {
110 case ShellPromptResponseNo
:
112 // return success here so we dont stop the process
114 return (SHELL_SUCCESS
);
115 case ShellPromptResponseCancel
:
118 // indicate to stop everything
120 return (SHELL_ABORTED
);
121 case ShellPromptResponseAll
:
123 case ShellPromptResponseYes
:
126 return SHELL_ABORTED
;
131 if (ShellIsDirectory(Source
) == EFI_SUCCESS
) {
132 Status
= ShellCreateDirectory(Dest
, &DestHandle
);
133 if (EFI_ERROR(Status
)) {
134 return (SHELL_ACCESS_DENIED
);
138 // Now copy all the files under the directory...
142 StrnCatGrow(&TempName
, &Size
, Source
, 0);
143 StrnCatGrow(&TempName
, &Size
, L
"\\*", 0);
144 if (TempName
!= NULL
) {
145 ShellOpenFileMetaArg((CHAR16
*)TempName
, EFI_FILE_MODE_READ
, &List
);
146 *TempName
= CHAR_NULL
;
147 StrnCatGrow(&TempName
, &Size
, Dest
, 0);
148 StrnCatGrow(&TempName
, &Size
, L
"\\", 0);
149 ShellStatus
= ValidateAndCopyFiles(List
, TempName
, SilentMode
, TRUE
, Resp
);
150 ShellCloseFileMetaArg(&List
);
151 SHELL_FREE_NON_NULL(TempName
);
155 Status
= ShellDeleteFileByName(Dest
);
158 // open file with create enabled
160 Status
= ShellOpenFileByName(Dest
, &DestHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, 0);
161 if (EFI_ERROR(Status
)) {
162 return (SHELL_ACCESS_DENIED
);
168 Status
= ShellOpenFileByName(Source
, &SourceHandle
, EFI_FILE_MODE_READ
, 0);
169 ASSERT_EFI_ERROR(Status
);
172 //get file size of source file and freespace available on destination volume
174 ShellGetFileSize(SourceHandle
, &SourceFileSize
);
175 ShellGetFileSize(DestHandle
, &DestFileSize
);
178 //if the destination file already exists then it will be replaced, meaning the sourcefile effectively needs less storage space
180 if(DestFileSize
< SourceFileSize
){
181 SourceFileSize
-= DestFileSize
;
187 //get the system volume info to check the free space
189 DestVolumeFP
= ConvertShellHandleToEfiFileProtocol(DestHandle
);
190 DestVolumeInfo
= NULL
;
191 DestVolumeInfoSize
= 0;
192 Status
= DestVolumeFP
->GetInfo(
194 &gEfiFileSystemInfoGuid
,
199 if (Status
== EFI_BUFFER_TOO_SMALL
) {
200 DestVolumeInfo
= AllocateZeroPool(DestVolumeInfoSize
);
201 Status
= DestVolumeFP
->GetInfo(
203 &gEfiFileSystemInfoGuid
,
210 //check if enough space available on destination drive to complete copy
212 if (DestVolumeInfo
!= NULL
&& (DestVolumeInfo
->FreeSpace
< SourceFileSize
)) {
214 //not enough space on destination directory to copy file
216 SHELL_FREE_NON_NULL(DestVolumeInfo
);
217 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_CPY_FAIL
), gShellLevel2HiiHandle
);
218 return(SHELL_VOLUME_FULL
);
221 // copy data between files
223 Buffer
= AllocateZeroPool(ReadSize
);
224 ASSERT(Buffer
!= NULL
);
225 while (ReadSize
== PcdGet32(PcdShellFileOperationSize
) && !EFI_ERROR(Status
)) {
226 Status
= ShellReadFile(SourceHandle
, &ReadSize
, Buffer
);
227 if (!EFI_ERROR(Status
)) {
228 Status
= ShellWriteFile(DestHandle
, &ReadSize
, Buffer
);
229 if (EFI_ERROR(Status
)) {
230 ShellStatus
= (SHELL_STATUS
) (Status
& (~MAX_BIT
));
231 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_CPY_WRITE_ERROR
), gShellLevel2HiiHandle
, Dest
);
235 ShellStatus
= (SHELL_STATUS
) (Status
& (~MAX_BIT
));
236 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_CPY_READ_ERROR
), gShellLevel2HiiHandle
, Source
);
241 SHELL_FREE_NON_NULL(DestVolumeInfo
);
247 if (DestHandle
!= NULL
) {
248 ShellCloseFile(&DestHandle
);
251 if (SourceHandle
!= NULL
) {
252 ShellCloseFile(&SourceHandle
);
263 function to take a list of files to copy and a destination location and do
264 the verification and copying of those files to that location. This function
265 will report any errors to the user and halt.
267 The key is to have this function called ONLY once. this allows for the parameter
268 verification to happen correctly.
270 @param[in] FileList A LIST_ENTRY* based list of files to move.
271 @param[in] DestDir The destination location.
272 @param[in] SilentMode TRUE to eliminate screen output.
273 @param[in] RecursiveMode TRUE to copy directories.
274 @param[in] Resp The response to the overwrite query (if always).
276 @retval SHELL_SUCCESS the files were all moved.
277 @retval SHELL_INVALID_PARAMETER a parameter was invalid
278 @retval SHELL_SECURITY_VIOLATION a security violation ocurred
279 @retval SHELL_WRITE_PROTECTED the destination was write protected
280 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
284 ValidateAndCopyFiles(
285 IN CONST EFI_SHELL_FILE_INFO
*FileList
,
286 IN CONST CHAR16
*DestDir
,
287 IN BOOLEAN SilentMode
,
288 IN BOOLEAN RecursiveMode
,
294 CONST EFI_SHELL_FILE_INFO
*Node
;
295 SHELL_STATUS ShellStatus
;
309 ShellStatus
= SHELL_SUCCESS
;
311 Cwd
= ShellGetCurrentDir(NULL
);
313 ASSERT(FileList
!= NULL
);
314 ASSERT(DestDir
!= NULL
);
317 // If we are trying to copy multiple files... make sure we got a directory for the target...
319 if (EFI_ERROR(ShellIsDirectory(DestDir
)) && FileList
->Link
.ForwardLink
!= FileList
->Link
.BackLink
) {
321 // Error for destination not a directory
323 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NOT_DIR
), gShellLevel2HiiHandle
, DestDir
);
324 return (SHELL_INVALID_PARAMETER
);
326 for (Node
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&FileList
->Link
)
327 ; !IsNull(&FileList
->Link
, &Node
->Link
)
328 ; Node
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&FileList
->Link
, &Node
->Link
)
331 // skip the directory traversing stuff...
333 if (StrCmp(Node
->FileName
, L
".") == 0 || StrCmp(Node
->FileName
, L
"..") == 0) {
337 NewSize
= StrSize(DestDir
);
338 NewSize
+= StrSize(Node
->FullName
);
339 NewSize
+= (Cwd
== NULL
)? 0 : StrSize(Cwd
);
340 if (NewSize
> PathLen
) {
345 // Make sure got -r if required
347 if (!RecursiveMode
&& !EFI_ERROR(ShellIsDirectory(Node
->FullName
))) {
348 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_DIR_REQ
), gShellLevel2HiiHandle
);
349 return (SHELL_INVALID_PARAMETER
);
353 // make sure got dest as dir if needed
355 if (!EFI_ERROR(ShellIsDirectory(Node
->FullName
)) && EFI_ERROR(ShellIsDirectory(DestDir
))) {
357 // Error for destination not a directory
359 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NOT_DIR
), gShellLevel2HiiHandle
, DestDir
);
360 return (SHELL_INVALID_PARAMETER
);
364 HiiOutput
= HiiGetString (gShellLevel2HiiHandle
, STRING_TOKEN (STR_CP_OUTPUT
), NULL
);
365 HiiResultOk
= HiiGetString (gShellLevel2HiiHandle
, STRING_TOKEN (STR_GEN_RES_OK
), NULL
);
366 DestPath
= AllocateZeroPool(PathLen
);
368 if (DestPath
== NULL
|| HiiOutput
== NULL
|| HiiResultOk
== NULL
) {
369 SHELL_FREE_NON_NULL(DestPath
);
370 SHELL_FREE_NON_NULL(HiiOutput
);
371 SHELL_FREE_NON_NULL(HiiResultOk
);
372 return (SHELL_OUT_OF_RESOURCES
);
376 // Go through the list of files to copy...
378 for (Node
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&FileList
->Link
)
379 ; !IsNull(&FileList
->Link
, &Node
->Link
)
380 ; Node
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&FileList
->Link
, &Node
->Link
)
382 if (ShellGetExecutionBreakFlag()) {
385 ASSERT(Node
->FileName
!= NULL
);
386 ASSERT(Node
->FullName
!= NULL
);
389 // skip the directory traversing stuff...
391 if (StrCmp(Node
->FileName
, L
".") == 0 || StrCmp(Node
->FileName
, L
"..") == 0) {
395 if (FileList
->Link
.ForwardLink
== FileList
->Link
.BackLink
// 1 item
396 && EFI_ERROR(ShellIsDirectory(DestDir
)) // not an existing directory
398 if (StrStr(DestDir
, L
":") == NULL
) {
400 // simple copy of a single file
403 StrCpy(DestPath
, Cwd
);
405 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_DIR_NF
), gShellLevel2HiiHandle
, DestDir
);
406 return (SHELL_INVALID_PARAMETER
);
408 if (DestPath
[StrLen(DestPath
)-1] != L
'\\' && DestDir
[0] != L
'\\') {
409 StrCat(DestPath
, L
"\\");
410 } else if (DestPath
[StrLen(DestPath
)-1] == L
'\\' && DestDir
[0] == L
'\\') {
411 ((CHAR16
*)DestPath
)[StrLen(DestPath
)-1] = CHAR_NULL
;
413 StrCat(DestPath
, DestDir
);
415 StrCpy(DestPath
, DestDir
);
419 // we have multiple files or a directory in the DestDir
423 // Check for leading slash
425 if (DestDir
[0] == L
'\\') {
427 // Copy to the root of CWD
430 StrCpy(DestPath
, Cwd
);
432 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_DIR_NF
), gShellLevel2HiiHandle
, DestDir
);
433 return (SHELL_INVALID_PARAMETER
);
435 while (PathRemoveLastItem(DestPath
));
436 StrCat(DestPath
, DestDir
+1);
437 StrCat(DestPath
, Node
->FileName
);
438 } else if (StrStr(DestDir
, L
":") == NULL
) {
440 StrCpy(DestPath
, Cwd
);
442 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_DIR_NF
), gShellLevel2HiiHandle
, DestDir
);
443 return (SHELL_INVALID_PARAMETER
);
445 if (DestPath
[StrLen(DestPath
)-1] != L
'\\' && DestDir
[0] != L
'\\') {
446 StrCat(DestPath
, L
"\\");
447 } else if (DestPath
[StrLen(DestPath
)-1] == L
'\\' && DestDir
[0] == L
'\\') {
448 ((CHAR16
*)DestPath
)[StrLen(DestPath
)-1] = CHAR_NULL
;
450 StrCat(DestPath
, DestDir
);
451 if (DestDir
[StrLen(DestDir
)-1] != L
'\\' && Node
->FileName
[0] != L
'\\') {
452 StrCat(DestPath
, L
"\\");
453 } else if (DestDir
[StrLen(DestDir
)-1] == L
'\\' && Node
->FileName
[0] == L
'\\') {
454 ((CHAR16
*)DestPath
)[StrLen(DestPath
)-1] = CHAR_NULL
;
456 StrCat(DestPath
, Node
->FileName
);
459 StrCpy(DestPath
, DestDir
);
460 if (DestDir
[StrLen(DestDir
)-1] != L
'\\' && Node
->FileName
[0] != L
'\\') {
461 StrCat(DestPath
, L
"\\");
462 } else if (DestDir
[StrLen(DestDir
)-1] == L
'\\' && Node
->FileName
[0] == L
'\\') {
463 ((CHAR16
*)DestDir
)[StrLen(DestDir
)-1] = CHAR_NULL
;
465 StrCat(DestPath
, Node
->FileName
);
470 // Make sure the path exists
472 if (EFI_ERROR(VerifyIntermediateDirectories(DestPath
))) {
473 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_DIR_WNF
), gShellLevel2HiiHandle
);
474 ShellStatus
= SHELL_DEVICE_ERROR
;
478 if ( !EFI_ERROR(ShellIsDirectory(Node
->FullName
))
479 && !EFI_ERROR(ShellIsDirectory(DestPath
))
480 && StrniCmp(Node
->FullName
, DestPath
, StrLen(DestPath
)) == NULL
482 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_SD_PARENT
), gShellLevel2HiiHandle
);
483 ShellStatus
= SHELL_INVALID_PARAMETER
;
486 if (StringNoCaseCompare(&Node
->FullName
, &DestPath
) == 0) {
487 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_SD_SAME
), gShellLevel2HiiHandle
);
488 ShellStatus
= SHELL_INVALID_PARAMETER
;
492 if ((StrniCmp(Node
->FullName
, DestPath
, StrLen(Node
->FullName
)) == 0)
493 && (DestPath
[StrLen(Node
->FullName
)] == CHAR_NULL
|| DestPath
[StrLen(Node
->FullName
)] == L
'\\')
495 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_SD_SAME
), gShellLevel2HiiHandle
);
496 ShellStatus
= SHELL_INVALID_PARAMETER
;
500 PathCleanUpDirectories(DestPath
);
502 ShellPrintEx(-1, -1, HiiOutput
, Node
->FullName
, DestPath
);
505 // copy single file...
507 ShellStatus
= CopySingleFile(Node
->FullName
, DestPath
, &Response
, SilentMode
);
508 if (ShellStatus
!= SHELL_SUCCESS
) {
512 if (ShellStatus
== SHELL_SUCCESS
&& Resp
== NULL
) {
513 ShellPrintEx(-1, -1, L
"%s", HiiResultOk
);
516 SHELL_FREE_NON_NULL(DestPath
);
517 SHELL_FREE_NON_NULL(HiiOutput
);
518 SHELL_FREE_NON_NULL(HiiResultOk
);
520 SHELL_FREE_NON_NULL(Response
);
523 return (ShellStatus
);
528 Validate and if successful copy all the files from the list into
529 destination directory.
531 @param[in] FileList The list of files to copy.
532 @param[in] DestDir The directory to copy files to.
533 @param[in] SilentMode TRUE to eliminate screen output.
534 @param[in] RecursiveMode TRUE to copy directories.
536 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
537 @retval SHELL_SUCCESS The operation was successful.
541 ProcessValidateAndCopyFiles(
542 IN EFI_SHELL_FILE_INFO
*FileList
,
543 IN CONST CHAR16
*DestDir
,
544 IN BOOLEAN SilentMode
,
545 IN BOOLEAN RecursiveMode
548 SHELL_STATUS ShellStatus
;
549 EFI_SHELL_FILE_INFO
*List
;
550 EFI_FILE_INFO
*FileInfo
;
557 ShellOpenFileMetaArg((CHAR16
*)DestDir
, EFI_FILE_MODE_READ
, &List
);
558 if (List
!= NULL
&& List
->Link
.ForwardLink
!= List
->Link
.BackLink
) {
559 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_MARG_ERROR
), gShellLevel2HiiHandle
, DestDir
);
560 ShellStatus
= SHELL_INVALID_PARAMETER
;
561 ShellCloseFileMetaArg(&List
);
562 } else if (List
!= NULL
) {
563 ASSERT(((EFI_SHELL_FILE_INFO
*)List
->Link
.ForwardLink
) != NULL
);
564 ASSERT(((EFI_SHELL_FILE_INFO
*)List
->Link
.ForwardLink
)->FullName
!= NULL
);
565 FileInfo
= gEfiShellProtocol
->GetFileInfo(((EFI_SHELL_FILE_INFO
*)List
->Link
.ForwardLink
)->Handle
);
566 ASSERT(FileInfo
!= NULL
);
567 StrnCatGrow(&FullName
, NULL
, ((EFI_SHELL_FILE_INFO
*)List
->Link
.ForwardLink
)->FullName
, 0);
568 ShellCloseFileMetaArg(&List
);
569 if ((FileInfo
->Attribute
& EFI_FILE_READ_ONLY
) == 0) {
570 ShellStatus
= ValidateAndCopyFiles(FileList
, FullName
, SilentMode
, RecursiveMode
, NULL
);
572 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_DEST_ERROR
), gShellLevel2HiiHandle
);
573 ShellStatus
= SHELL_ACCESS_DENIED
;
576 ShellCloseFileMetaArg(&List
);
577 ShellStatus
= ValidateAndCopyFiles(FileList
, DestDir
, SilentMode
, RecursiveMode
, NULL
);
580 SHELL_FREE_NON_NULL(FileInfo
);
581 SHELL_FREE_NON_NULL(FullName
);
582 return (ShellStatus
);
585 STATIC CONST SHELL_PARAM_ITEM ParamList
[] = {
592 Function for 'cp' command.
594 @param[in] ImageHandle Handle to the Image (NULL if Internal).
595 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
600 IN EFI_HANDLE ImageHandle
,
601 IN EFI_SYSTEM_TABLE
*SystemTable
606 CHAR16
*ProblemParam
;
607 SHELL_STATUS ShellStatus
;
610 EFI_SHELL_FILE_INFO
*FileList
;
612 BOOLEAN RecursiveMode
;
616 ShellStatus
= SHELL_SUCCESS
;
621 // initialize the shell lib (we must be in non-auto-init...)
623 Status
= ShellInitialize();
624 ASSERT_EFI_ERROR(Status
);
626 Status
= CommandInit();
627 ASSERT_EFI_ERROR(Status
);
630 // parse the command line
632 Status
= ShellCommandLineParse (ParamList
, &Package
, &ProblemParam
, TRUE
);
633 if (EFI_ERROR(Status
)) {
634 if (Status
== EFI_VOLUME_CORRUPTED
&& ProblemParam
!= NULL
) {
635 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellLevel2HiiHandle
, ProblemParam
);
636 FreePool(ProblemParam
);
637 ShellStatus
= SHELL_INVALID_PARAMETER
;
645 if (ShellCommandLineGetFlag(Package
, L
"-?")) {
650 // Initialize SilentMode and RecursiveMode
652 if (gEfiShellProtocol
->BatchIsActive()) {
655 SilentMode
= ShellCommandLineGetFlag(Package
, L
"-q");
657 RecursiveMode
= ShellCommandLineGetFlag(Package
, L
"-r");
659 switch (ParamCount
= ShellCommandLineGetCount(Package
)) {
663 // we have insufficient parameters
665 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellLevel2HiiHandle
);
666 ShellStatus
= SHELL_INVALID_PARAMETER
;
670 // must have valid CWD for single parameter...
672 Cwd
= ShellGetCurrentDir(NULL
);
674 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_CWD
), gShellLevel2HiiHandle
);
675 ShellStatus
= SHELL_INVALID_PARAMETER
;
677 Status
= ShellOpenFileMetaArg((CHAR16
*)ShellCommandLineGetRawValue(Package
, 1), EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
, &FileList
);
678 if (FileList
== NULL
|| IsListEmpty(&FileList
->Link
) || EFI_ERROR(Status
)) {
679 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_NF
), gShellLevel2HiiHandle
, ShellCommandLineGetRawValue(Package
, 1));
680 ShellStatus
= SHELL_NOT_FOUND
;
682 ShellStatus
= ProcessValidateAndCopyFiles(FileList
, Cwd
, SilentMode
, RecursiveMode
);
689 // Make a big list of all the files...
691 for (ParamCount
--, LoopCounter
= 1 ; LoopCounter
< ParamCount
&& ShellStatus
== SHELL_SUCCESS
; LoopCounter
++) {
692 if (ShellGetExecutionBreakFlag()) {
695 Status
= ShellOpenFileMetaArg((CHAR16
*)ShellCommandLineGetRawValue(Package
, LoopCounter
), EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
, &FileList
);
696 if (EFI_ERROR(Status
) || FileList
== NULL
|| IsListEmpty(&FileList
->Link
)) {
697 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_NF
), gShellLevel2HiiHandle
, ShellCommandLineGetRawValue(Package
, LoopCounter
));
698 ShellStatus
= SHELL_NOT_FOUND
;
701 if (ShellStatus
!= SHELL_SUCCESS
) {
702 Status
= ShellCloseFileMetaArg(&FileList
);
705 // now copy them all...
707 if (FileList
!= NULL
&& !IsListEmpty(&FileList
->Link
)) {
708 ShellStatus
= ProcessValidateAndCopyFiles(FileList
, PathCleanUpDirectories((CHAR16
*)ShellCommandLineGetRawValue(Package
, ParamCount
)), SilentMode
, RecursiveMode
);
709 Status
= ShellCloseFileMetaArg(&FileList
);
710 if (EFI_ERROR(Status
) && ShellStatus
== SHELL_SUCCESS
) {
711 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_ERR_FILE
), gShellLevel2HiiHandle
, ShellCommandLineGetRawValue(Package
, ParamCount
), ShellStatus
|MAX_BIT
);
712 ShellStatus
= SHELL_ACCESS_DENIED
;
717 } // switch on parameter count
719 if (FileList
!= NULL
) {
720 ShellCloseFileMetaArg(&FileList
);
724 // free the command line package
726 ShellCommandLineFreeVarList (Package
);
729 if (ShellGetExecutionBreakFlag()) {
730 return (SHELL_ABORTED
);
733 return (ShellStatus
);