2 Main file for cp shell level 2 function.
4 Copyright (c) 2009 - 2014, 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 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_DEST_DIR_FAIL
), gShellLevel2HiiHandle
, Dest
);
135 return (SHELL_ACCESS_DENIED
);
139 // Now copy all the files under the directory...
143 StrnCatGrow(&TempName
, &Size
, Source
, 0);
144 StrnCatGrow(&TempName
, &Size
, L
"\\*", 0);
145 if (TempName
!= NULL
) {
146 ShellOpenFileMetaArg((CHAR16
*)TempName
, EFI_FILE_MODE_READ
, &List
);
147 *TempName
= CHAR_NULL
;
148 StrnCatGrow(&TempName
, &Size
, Dest
, 0);
149 StrnCatGrow(&TempName
, &Size
, L
"\\", 0);
150 ShellStatus
= ValidateAndCopyFiles(List
, TempName
, SilentMode
, TRUE
, Resp
);
151 ShellCloseFileMetaArg(&List
);
152 SHELL_FREE_NON_NULL(TempName
);
156 Status
= ShellDeleteFileByName(Dest
);
159 // open file with create enabled
161 Status
= ShellOpenFileByName(Dest
, &DestHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, 0);
162 if (EFI_ERROR(Status
)) {
163 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_DEST_OPEN_FAIL
), gShellLevel2HiiHandle
, Dest
);
164 return (SHELL_ACCESS_DENIED
);
170 Status
= ShellOpenFileByName(Source
, &SourceHandle
, EFI_FILE_MODE_READ
, 0);
171 ASSERT_EFI_ERROR(Status
);
174 //get file size of source file and freespace available on destination volume
176 ShellGetFileSize(SourceHandle
, &SourceFileSize
);
177 ShellGetFileSize(DestHandle
, &DestFileSize
);
180 //if the destination file already exists then it will be replaced, meaning the sourcefile effectively needs less storage space
182 if(DestFileSize
< SourceFileSize
){
183 SourceFileSize
-= DestFileSize
;
189 //get the system volume info to check the free space
191 DestVolumeFP
= ConvertShellHandleToEfiFileProtocol(DestHandle
);
192 DestVolumeInfo
= NULL
;
193 DestVolumeInfoSize
= 0;
194 Status
= DestVolumeFP
->GetInfo(
196 &gEfiFileSystemInfoGuid
,
201 if (Status
== EFI_BUFFER_TOO_SMALL
) {
202 DestVolumeInfo
= AllocateZeroPool(DestVolumeInfoSize
);
203 Status
= DestVolumeFP
->GetInfo(
205 &gEfiFileSystemInfoGuid
,
212 //check if enough space available on destination drive to complete copy
214 if (DestVolumeInfo
!= NULL
&& (DestVolumeInfo
->FreeSpace
< SourceFileSize
)) {
216 //not enough space on destination directory to copy file
218 SHELL_FREE_NON_NULL(DestVolumeInfo
);
219 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_CPY_FAIL
), gShellLevel2HiiHandle
);
220 return(SHELL_VOLUME_FULL
);
223 // copy data between files
225 Buffer
= AllocateZeroPool(ReadSize
);
226 ASSERT(Buffer
!= NULL
);
227 while (ReadSize
== PcdGet32(PcdShellFileOperationSize
) && !EFI_ERROR(Status
)) {
228 Status
= ShellReadFile(SourceHandle
, &ReadSize
, Buffer
);
229 if (!EFI_ERROR(Status
)) {
230 Status
= ShellWriteFile(DestHandle
, &ReadSize
, Buffer
);
231 if (EFI_ERROR(Status
)) {
232 ShellStatus
= (SHELL_STATUS
) (Status
& (~MAX_BIT
));
233 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_CPY_WRITE_ERROR
), gShellLevel2HiiHandle
, Dest
);
237 ShellStatus
= (SHELL_STATUS
) (Status
& (~MAX_BIT
));
238 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_CPY_READ_ERROR
), gShellLevel2HiiHandle
, Source
);
243 SHELL_FREE_NON_NULL(DestVolumeInfo
);
249 if (DestHandle
!= NULL
) {
250 ShellCloseFile(&DestHandle
);
253 if (SourceHandle
!= NULL
) {
254 ShellCloseFile(&SourceHandle
);
265 function to take a list of files to copy and a destination location and do
266 the verification and copying of those files to that location. This function
267 will report any errors to the user and halt.
269 The key is to have this function called ONLY once. this allows for the parameter
270 verification to happen correctly.
272 @param[in] FileList A LIST_ENTRY* based list of files to move.
273 @param[in] DestDir The destination location.
274 @param[in] SilentMode TRUE to eliminate screen output.
275 @param[in] RecursiveMode TRUE to copy directories.
276 @param[in] Resp The response to the overwrite query (if always).
278 @retval SHELL_SUCCESS the files were all moved.
279 @retval SHELL_INVALID_PARAMETER a parameter was invalid
280 @retval SHELL_SECURITY_VIOLATION a security violation ocurred
281 @retval SHELL_WRITE_PROTECTED the destination was write protected
282 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
286 ValidateAndCopyFiles(
287 IN CONST EFI_SHELL_FILE_INFO
*FileList
,
288 IN CONST CHAR16
*DestDir
,
289 IN BOOLEAN SilentMode
,
290 IN BOOLEAN RecursiveMode
,
296 CONST EFI_SHELL_FILE_INFO
*Node
;
297 SHELL_STATUS ShellStatus
;
311 ShellStatus
= SHELL_SUCCESS
;
313 Cwd
= ShellGetCurrentDir(NULL
);
315 ASSERT(FileList
!= NULL
);
316 ASSERT(DestDir
!= NULL
);
319 // If we are trying to copy multiple files... make sure we got a directory for the target...
321 if (EFI_ERROR(ShellIsDirectory(DestDir
)) && FileList
->Link
.ForwardLink
!= FileList
->Link
.BackLink
) {
323 // Error for destination not a directory
325 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NOT_DIR
), gShellLevel2HiiHandle
, DestDir
);
326 return (SHELL_INVALID_PARAMETER
);
328 for (Node
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&FileList
->Link
)
329 ; !IsNull(&FileList
->Link
, &Node
->Link
)
330 ; Node
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&FileList
->Link
, &Node
->Link
)
333 // skip the directory traversing stuff...
335 if (StrCmp(Node
->FileName
, L
".") == 0 || StrCmp(Node
->FileName
, L
"..") == 0) {
339 NewSize
= StrSize(DestDir
);
340 NewSize
+= StrSize(Node
->FullName
);
341 NewSize
+= (Cwd
== NULL
)? 0 : StrSize(Cwd
);
342 if (NewSize
> PathLen
) {
347 // Make sure got -r if required
349 if (!RecursiveMode
&& !EFI_ERROR(ShellIsDirectory(Node
->FullName
))) {
350 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_DIR_REQ
), gShellLevel2HiiHandle
);
351 return (SHELL_INVALID_PARAMETER
);
355 // make sure got dest as dir if needed
357 if (!EFI_ERROR(ShellIsDirectory(Node
->FullName
)) && EFI_ERROR(ShellIsDirectory(DestDir
))) {
359 // Error for destination not a directory
361 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NOT_DIR
), gShellLevel2HiiHandle
, DestDir
);
362 return (SHELL_INVALID_PARAMETER
);
366 HiiOutput
= HiiGetString (gShellLevel2HiiHandle
, STRING_TOKEN (STR_CP_OUTPUT
), NULL
);
367 HiiResultOk
= HiiGetString (gShellLevel2HiiHandle
, STRING_TOKEN (STR_GEN_RES_OK
), NULL
);
368 DestPath
= AllocateZeroPool(PathLen
);
370 if (DestPath
== NULL
|| HiiOutput
== NULL
|| HiiResultOk
== NULL
) {
371 SHELL_FREE_NON_NULL(DestPath
);
372 SHELL_FREE_NON_NULL(HiiOutput
);
373 SHELL_FREE_NON_NULL(HiiResultOk
);
374 return (SHELL_OUT_OF_RESOURCES
);
378 // Go through the list of files to copy...
380 for (Node
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&FileList
->Link
)
381 ; !IsNull(&FileList
->Link
, &Node
->Link
)
382 ; Node
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&FileList
->Link
, &Node
->Link
)
384 if (ShellGetExecutionBreakFlag()) {
387 ASSERT(Node
->FileName
!= NULL
);
388 ASSERT(Node
->FullName
!= NULL
);
391 // skip the directory traversing stuff...
393 if (StrCmp(Node
->FileName
, L
".") == 0 || StrCmp(Node
->FileName
, L
"..") == 0) {
397 if (FileList
->Link
.ForwardLink
== FileList
->Link
.BackLink
// 1 item
398 && EFI_ERROR(ShellIsDirectory(DestDir
)) // not an existing directory
400 if (StrStr(DestDir
, L
":") == NULL
) {
402 // simple copy of a single file
405 StrCpy(DestPath
, Cwd
);
407 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_DIR_NF
), gShellLevel2HiiHandle
, DestDir
);
408 return (SHELL_INVALID_PARAMETER
);
410 if (DestPath
[StrLen(DestPath
)-1] != L
'\\' && DestDir
[0] != L
'\\') {
411 StrCat(DestPath
, L
"\\");
412 } else if (DestPath
[StrLen(DestPath
)-1] == L
'\\' && DestDir
[0] == L
'\\') {
413 ((CHAR16
*)DestPath
)[StrLen(DestPath
)-1] = CHAR_NULL
;
415 StrCat(DestPath
, DestDir
);
417 StrCpy(DestPath
, DestDir
);
421 // we have multiple files or a directory in the DestDir
425 // Check for leading slash
427 if (DestDir
[0] == L
'\\') {
429 // Copy to the root of CWD
432 StrCpy(DestPath
, Cwd
);
434 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_DIR_NF
), gShellLevel2HiiHandle
, DestDir
);
435 return (SHELL_INVALID_PARAMETER
);
437 while (PathRemoveLastItem(DestPath
));
438 StrCat(DestPath
, DestDir
+1);
439 StrCat(DestPath
, Node
->FileName
);
440 } else if (StrStr(DestDir
, L
":") == NULL
) {
442 StrCpy(DestPath
, Cwd
);
444 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_DIR_NF
), gShellLevel2HiiHandle
, DestDir
);
445 return (SHELL_INVALID_PARAMETER
);
447 if (DestPath
[StrLen(DestPath
)-1] != L
'\\' && DestDir
[0] != L
'\\') {
448 StrCat(DestPath
, L
"\\");
449 } else if (DestPath
[StrLen(DestPath
)-1] == L
'\\' && DestDir
[0] == L
'\\') {
450 ((CHAR16
*)DestPath
)[StrLen(DestPath
)-1] = CHAR_NULL
;
452 StrCat(DestPath
, DestDir
);
453 if (DestDir
[StrLen(DestDir
)-1] != L
'\\' && Node
->FileName
[0] != L
'\\') {
454 StrCat(DestPath
, L
"\\");
455 } else if (DestDir
[StrLen(DestDir
)-1] == L
'\\' && Node
->FileName
[0] == L
'\\') {
456 ((CHAR16
*)DestPath
)[StrLen(DestPath
)-1] = CHAR_NULL
;
458 StrCat(DestPath
, Node
->FileName
);
461 StrCpy(DestPath
, DestDir
);
462 if (DestDir
[StrLen(DestDir
)-1] != L
'\\' && Node
->FileName
[0] != L
'\\') {
463 StrCat(DestPath
, L
"\\");
464 } else if (DestDir
[StrLen(DestDir
)-1] == L
'\\' && Node
->FileName
[0] == L
'\\') {
465 ((CHAR16
*)DestDir
)[StrLen(DestDir
)-1] = CHAR_NULL
;
467 StrCat(DestPath
, Node
->FileName
);
472 // Make sure the path exists
474 if (EFI_ERROR(VerifyIntermediateDirectories(DestPath
))) {
475 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_DIR_WNF
), gShellLevel2HiiHandle
);
476 ShellStatus
= SHELL_DEVICE_ERROR
;
480 if ( !EFI_ERROR(ShellIsDirectory(Node
->FullName
))
481 && !EFI_ERROR(ShellIsDirectory(DestPath
))
482 && StrniCmp(Node
->FullName
, DestPath
, StrLen(DestPath
)) == NULL
484 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_SD_PARENT
), gShellLevel2HiiHandle
);
485 ShellStatus
= SHELL_INVALID_PARAMETER
;
488 if (StringNoCaseCompare(&Node
->FullName
, &DestPath
) == 0) {
489 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_SD_SAME
), gShellLevel2HiiHandle
);
490 ShellStatus
= SHELL_INVALID_PARAMETER
;
494 if ((StrniCmp(Node
->FullName
, DestPath
, StrLen(Node
->FullName
)) == 0)
495 && (DestPath
[StrLen(Node
->FullName
)] == CHAR_NULL
|| DestPath
[StrLen(Node
->FullName
)] == L
'\\')
497 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_SD_SAME
), gShellLevel2HiiHandle
);
498 ShellStatus
= SHELL_INVALID_PARAMETER
;
502 PathCleanUpDirectories(DestPath
);
504 ShellPrintEx(-1, -1, HiiOutput
, Node
->FullName
, DestPath
);
507 // copy single file...
509 ShellStatus
= CopySingleFile(Node
->FullName
, DestPath
, &Response
, SilentMode
);
510 if (ShellStatus
!= SHELL_SUCCESS
) {
514 if (ShellStatus
== SHELL_SUCCESS
&& Resp
== NULL
) {
515 ShellPrintEx(-1, -1, L
"%s", HiiResultOk
);
518 SHELL_FREE_NON_NULL(DestPath
);
519 SHELL_FREE_NON_NULL(HiiOutput
);
520 SHELL_FREE_NON_NULL(HiiResultOk
);
522 SHELL_FREE_NON_NULL(Response
);
525 return (ShellStatus
);
530 Validate and if successful copy all the files from the list into
531 destination directory.
533 @param[in] FileList The list of files to copy.
534 @param[in] DestDir The directory to copy files to.
535 @param[in] SilentMode TRUE to eliminate screen output.
536 @param[in] RecursiveMode TRUE to copy directories.
538 @retval SHELL_INVALID_PARAMETER A parameter was invalid.
539 @retval SHELL_SUCCESS The operation was successful.
543 ProcessValidateAndCopyFiles(
544 IN EFI_SHELL_FILE_INFO
*FileList
,
545 IN CONST CHAR16
*DestDir
,
546 IN BOOLEAN SilentMode
,
547 IN BOOLEAN RecursiveMode
550 SHELL_STATUS ShellStatus
;
551 EFI_SHELL_FILE_INFO
*List
;
552 EFI_FILE_INFO
*FileInfo
;
559 ShellOpenFileMetaArg((CHAR16
*)DestDir
, EFI_FILE_MODE_READ
, &List
);
560 if (List
!= NULL
&& List
->Link
.ForwardLink
!= List
->Link
.BackLink
) {
561 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_MARG_ERROR
), gShellLevel2HiiHandle
, DestDir
);
562 ShellStatus
= SHELL_INVALID_PARAMETER
;
563 ShellCloseFileMetaArg(&List
);
564 } else if (List
!= NULL
) {
565 ASSERT(((EFI_SHELL_FILE_INFO
*)List
->Link
.ForwardLink
) != NULL
);
566 ASSERT(((EFI_SHELL_FILE_INFO
*)List
->Link
.ForwardLink
)->FullName
!= NULL
);
567 FileInfo
= gEfiShellProtocol
->GetFileInfo(((EFI_SHELL_FILE_INFO
*)List
->Link
.ForwardLink
)->Handle
);
568 ASSERT(FileInfo
!= NULL
);
569 StrnCatGrow(&FullName
, NULL
, ((EFI_SHELL_FILE_INFO
*)List
->Link
.ForwardLink
)->FullName
, 0);
570 ShellCloseFileMetaArg(&List
);
571 if ((FileInfo
->Attribute
& EFI_FILE_READ_ONLY
) == 0) {
572 ShellStatus
= ValidateAndCopyFiles(FileList
, FullName
, SilentMode
, RecursiveMode
, NULL
);
574 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_CP_DEST_ERROR
), gShellLevel2HiiHandle
);
575 ShellStatus
= SHELL_ACCESS_DENIED
;
578 ShellCloseFileMetaArg(&List
);
579 ShellStatus
= ValidateAndCopyFiles(FileList
, DestDir
, SilentMode
, RecursiveMode
, NULL
);
582 SHELL_FREE_NON_NULL(FileInfo
);
583 SHELL_FREE_NON_NULL(FullName
);
584 return (ShellStatus
);
587 STATIC CONST SHELL_PARAM_ITEM ParamList
[] = {
594 Function for 'cp' command.
596 @param[in] ImageHandle Handle to the Image (NULL if Internal).
597 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
602 IN EFI_HANDLE ImageHandle
,
603 IN EFI_SYSTEM_TABLE
*SystemTable
608 CHAR16
*ProblemParam
;
609 SHELL_STATUS ShellStatus
;
612 EFI_SHELL_FILE_INFO
*FileList
;
614 BOOLEAN RecursiveMode
;
618 ShellStatus
= SHELL_SUCCESS
;
623 // initialize the shell lib (we must be in non-auto-init...)
625 Status
= ShellInitialize();
626 ASSERT_EFI_ERROR(Status
);
628 Status
= CommandInit();
629 ASSERT_EFI_ERROR(Status
);
632 // parse the command line
634 Status
= ShellCommandLineParse (ParamList
, &Package
, &ProblemParam
, TRUE
);
635 if (EFI_ERROR(Status
)) {
636 if (Status
== EFI_VOLUME_CORRUPTED
&& ProblemParam
!= NULL
) {
637 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellLevel2HiiHandle
, ProblemParam
);
638 FreePool(ProblemParam
);
639 ShellStatus
= SHELL_INVALID_PARAMETER
;
647 if (ShellCommandLineGetFlag(Package
, L
"-?")) {
652 // Initialize SilentMode and RecursiveMode
654 if (gEfiShellProtocol
->BatchIsActive()) {
657 SilentMode
= ShellCommandLineGetFlag(Package
, L
"-q");
659 RecursiveMode
= ShellCommandLineGetFlag(Package
, L
"-r");
661 switch (ParamCount
= ShellCommandLineGetCount(Package
)) {
665 // we have insufficient parameters
667 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellLevel2HiiHandle
);
668 ShellStatus
= SHELL_INVALID_PARAMETER
;
672 // must have valid CWD for single parameter...
674 Cwd
= ShellGetCurrentDir(NULL
);
676 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_CWD
), gShellLevel2HiiHandle
);
677 ShellStatus
= SHELL_INVALID_PARAMETER
;
679 Status
= ShellOpenFileMetaArg((CHAR16
*)ShellCommandLineGetRawValue(Package
, 1), EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
, &FileList
);
680 if (FileList
== NULL
|| IsListEmpty(&FileList
->Link
) || EFI_ERROR(Status
)) {
681 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_NF
), gShellLevel2HiiHandle
, ShellCommandLineGetRawValue(Package
, 1));
682 ShellStatus
= SHELL_NOT_FOUND
;
684 ShellStatus
= ProcessValidateAndCopyFiles(FileList
, Cwd
, SilentMode
, RecursiveMode
);
691 // Make a big list of all the files...
693 for (ParamCount
--, LoopCounter
= 1 ; LoopCounter
< ParamCount
&& ShellStatus
== SHELL_SUCCESS
; LoopCounter
++) {
694 if (ShellGetExecutionBreakFlag()) {
697 Status
= ShellOpenFileMetaArg((CHAR16
*)ShellCommandLineGetRawValue(Package
, LoopCounter
), EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
, &FileList
);
698 if (EFI_ERROR(Status
) || FileList
== NULL
|| IsListEmpty(&FileList
->Link
)) {
699 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_NF
), gShellLevel2HiiHandle
, ShellCommandLineGetRawValue(Package
, LoopCounter
));
700 ShellStatus
= SHELL_NOT_FOUND
;
703 if (ShellStatus
!= SHELL_SUCCESS
) {
704 Status
= ShellCloseFileMetaArg(&FileList
);
707 // now copy them all...
709 if (FileList
!= NULL
&& !IsListEmpty(&FileList
->Link
)) {
710 ShellStatus
= ProcessValidateAndCopyFiles(FileList
, PathCleanUpDirectories((CHAR16
*)ShellCommandLineGetRawValue(Package
, ParamCount
)), SilentMode
, RecursiveMode
);
711 Status
= ShellCloseFileMetaArg(&FileList
);
712 if (EFI_ERROR(Status
) && ShellStatus
== SHELL_SUCCESS
) {
713 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_ERR_FILE
), gShellLevel2HiiHandle
, ShellCommandLineGetRawValue(Package
, ParamCount
), ShellStatus
|MAX_BIT
);
714 ShellStatus
= SHELL_ACCESS_DENIED
;
719 } // switch on parameter count
721 if (FileList
!= NULL
) {
722 ShellCloseFileMetaArg(&FileList
);
726 // free the command line package
728 ShellCommandLineFreeVarList (Package
);
731 if (ShellGetExecutionBreakFlag()) {
732 return (SHELL_ABORTED
);
735 return (ShellStatus
);