Cp.c revision 427d61ad4ad1462b5f4370a78eb58c1ba73680b4
1a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey/** @file
2a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Main file for cp shell level 2 function.
3a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
47282b505c5da686b95f6b2277bbd25a620d263edJaben Carsey  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
5a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  This program and the accompanying materials
6a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  are licensed and made available under the terms and conditions of the BSD License
7a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  which accompanies this distribution.  The full text of the license may be found at
8a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  http://opensource.org/licenses/bsd-license.php
9a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
10a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
13a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey**/
14a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
15a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey#include "UefiShellLevel2CommandsLib.h"
16f06be00e7aea1dc89c63728d20247a85f1511139jcarsey#include <Guid/FileSystemInfo.h>
17f06be00e7aea1dc89c63728d20247a85f1511139jcarsey#include <Guid/FileSystemVolumeLabelInfo.h>
18a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
19b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey/**
20b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  Function to take a list of files to copy and a destination location and do
21b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  the verification and copying of those files to that location.  This function
22b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  will report any errors to the user and halt.
23b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey
24b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] FileList           A LIST_ENTRY* based list of files to move.
25b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] DestDir            The destination location.
26b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] SilentMode         TRUE to eliminate screen output.
27b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] RecursiveMode      TRUE to copy directories.
28b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] Resp               The response to the overwrite query (if always).
29b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey
30b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @retval SHELL_SUCCESS             the files were all moved.
31b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @retval SHELL_INVALID_PARAMETER   a parameter was invalid
32b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @retval SHELL_SECURITY_VIOLATION  a security violation ocurred
33b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @retval SHELL_WRITE_PROTECTED     the destination was write protected
34b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @retval SHELL_OUT_OF_RESOURCES    a memory allocation failed
35b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey**/
36a405b86d274d32b92f69842bfb9a1ab143128f57jcarseySHELL_STATUS
37a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFIAPI
38a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyValidateAndCopyFiles(
39a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN CONST EFI_SHELL_FILE_INFO  *FileList,
40a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN CONST CHAR16               *DestDir,
41a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN BOOLEAN                    SilentMode,
42a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN BOOLEAN                    RecursiveMode,
43a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN VOID                       **Resp
44a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  );
45a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
46a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey/**
47a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Function to Copy one file to another location
48a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
49a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  If the destination exists the user will be prompted and the result put into *resp
50a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
51a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @param[in] Source     pointer to source file name
52a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @param[in] Dest       pointer to destination file name
53a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @param[out] Resp      pointer to response from question.  Pass back on looped calling
54a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @param[in] SilentMode whether to run in quiet mode or not
55a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
56a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval SHELL_SUCCESS   The source file was copied to the destination
57a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey**/
58a405b86d274d32b92f69842bfb9a1ab143128f57jcarseySHELL_STATUS
59a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFIAPI
60a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyCopySingleFile(
61a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN CONST CHAR16 *Source,
62a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN CONST CHAR16 *Dest,
63a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  OUT VOID        **Resp,
64a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN BOOLEAN      SilentMode
65a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  )
66a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey{
67f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  VOID                  *Response;
68f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  UINTN                 ReadSize;
69f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  SHELL_FILE_HANDLE     SourceHandle;
70f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  SHELL_FILE_HANDLE     DestHandle;
71f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  EFI_STATUS            Status;
72f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  VOID                  *Buffer;
73f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  CHAR16                *TempName;
74f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  UINTN                 Size;
75f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  EFI_SHELL_FILE_INFO   *List;
76f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  SHELL_STATUS          ShellStatus;
77f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  UINT64                SourceFileSize;
78f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  UINT64                DestFileSize;
79f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  EFI_FILE_PROTOCOL     *DestVolumeFP;
80f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  EFI_FILE_SYSTEM_INFO  *DestVolumeInfo;
81f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  UINTN                 DestVolumeInfoSize;
82a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
83a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ASSERT(Resp != NULL);
84a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
85f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  SourceHandle    = NULL;
86f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  DestHandle      = NULL;
87f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  Response        = *Resp;
88f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  List            = NULL;
89f06be00e7aea1dc89c63728d20247a85f1511139jcarsey  DestVolumeInfo  = NULL;
90e755a4ca10aad316c3620223206d63982793b26cjcarsey  ShellStatus     = SHELL_SUCCESS;
91a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
92433a21cba1a6a825b9ec07f580164b84e5d41d3aEugene Cohen  ReadSize = PcdGet32(PcdShellFileOperationSize);
93a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // Why bother copying a file to itself
94a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (StrCmp(Source, Dest) == 0) {
95a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    return (SHELL_SUCCESS);
96a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
97a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
98a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
99a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // if the destination file existed check response and possibly prompt user
100a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
101ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey  if (ShellFileExists(Dest) == EFI_SUCCESS) {
102a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (Response == NULL && !SilentMode) {
103b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey      Status = ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response);
104a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
105a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
106a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    // possibly return based on response
107a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
108a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (!SilentMode) {
109a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      switch (*(SHELL_PROMPT_RESPONSE*)Response) {
110a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        case ShellPromptResponseNo:
111a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          //
112a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          // return success here so we dont stop the process
113a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          //
114a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          return (SHELL_SUCCESS);
115a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        case ShellPromptResponseCancel:
116a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          *Resp = Response;
117a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          //
118a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          // indicate to stop everything
119a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          //
120a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          return (SHELL_ABORTED);
121a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        case ShellPromptResponseAll:
122a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          *Resp = Response;
123a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        case ShellPromptResponseYes:
124a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          break;
125e97233217ed6d37d7bb7fefb0ff0821515a23b48jljusten        default:
126e97233217ed6d37d7bb7fefb0ff0821515a23b48jljusten          return SHELL_ABORTED;
127a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      }
128a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
129a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
130a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
131a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (ShellIsDirectory(Source) == EFI_SUCCESS) {
132a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    Status = ShellCreateDirectory(Dest, &DestHandle);
133a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (EFI_ERROR(Status)) {
1347282b505c5da686b95f6b2277bbd25a620d263edJaben Carsey      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_DIR_FAIL), gShellLevel2HiiHandle, Dest);
135a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      return (SHELL_ACCESS_DENIED);
136a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
137a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
138a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
139a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    // Now copy all the files under the directory...
140a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
141a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    TempName    = NULL;
142f06be00e7aea1dc89c63728d20247a85f1511139jcarsey    Size        = 0;
143a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    StrnCatGrow(&TempName, &Size, Source, 0);
144a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    StrnCatGrow(&TempName, &Size, L"\\*", 0);
1457dd0562309ac668b7025023f05e79687fdf7a13ajcarsey    if (TempName != NULL) {
1467dd0562309ac668b7025023f05e79687fdf7a13ajcarsey      ShellOpenFileMetaArg((CHAR16*)TempName, EFI_FILE_MODE_READ, &List);
1477dd0562309ac668b7025023f05e79687fdf7a13ajcarsey      *TempName = CHAR_NULL;
1487dd0562309ac668b7025023f05e79687fdf7a13ajcarsey      StrnCatGrow(&TempName, &Size, Dest, 0);
1497dd0562309ac668b7025023f05e79687fdf7a13ajcarsey      StrnCatGrow(&TempName, &Size, L"\\", 0);
1507dd0562309ac668b7025023f05e79687fdf7a13ajcarsey      ShellStatus = ValidateAndCopyFiles(List, TempName, SilentMode, TRUE, Resp);
1517dd0562309ac668b7025023f05e79687fdf7a13ajcarsey      ShellCloseFileMetaArg(&List);
1527dd0562309ac668b7025023f05e79687fdf7a13ajcarsey      SHELL_FREE_NON_NULL(TempName);
1537dd0562309ac668b7025023f05e79687fdf7a13ajcarsey      Size = 0;
1547dd0562309ac668b7025023f05e79687fdf7a13ajcarsey    }
155a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  } else {
156ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    Status = ShellDeleteFileByName(Dest);
157a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
158ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //
159ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    // open file with create enabled
160ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //
161ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
162ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    if (EFI_ERROR(Status)) {
1637282b505c5da686b95f6b2277bbd25a620d263edJaben Carsey      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_OPEN_FAIL), gShellLevel2HiiHandle, Dest);
164ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      return (SHELL_ACCESS_DENIED);
165ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    }
166f06be00e7aea1dc89c63728d20247a85f1511139jcarsey
167ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //
168ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    // open source file
169ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //
170ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    Status = ShellOpenFileByName(Source, &SourceHandle, EFI_FILE_MODE_READ, 0);
171ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    ASSERT_EFI_ERROR(Status);
172f06be00e7aea1dc89c63728d20247a85f1511139jcarsey
173ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //
174ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //get file size of source file and freespace available on destination volume
175ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //
176ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    ShellGetFileSize(SourceHandle, &SourceFileSize);
177ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    ShellGetFileSize(DestHandle, &DestFileSize);
178f06be00e7aea1dc89c63728d20247a85f1511139jcarsey
179ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //
180ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //if the destination file already exists then it will be replaced, meaning the sourcefile effectively needs less storage space
181ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //
182ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    if(DestFileSize < SourceFileSize){
183ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      SourceFileSize -= DestFileSize;
184ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    } else {
185ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      SourceFileSize = 0;
186ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    }
187ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey
188ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //
189ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //get the system volume info to check the free space
190ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //
191ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    DestVolumeFP = ConvertShellHandleToEfiFileProtocol(DestHandle);
192ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    DestVolumeInfo = NULL;
193ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    DestVolumeInfoSize = 0;
194ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    Status = DestVolumeFP->GetInfo(
195ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      DestVolumeFP,
196ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      &gEfiFileSystemInfoGuid,
197ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      &DestVolumeInfoSize,
198ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      DestVolumeInfo
199ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      );
200ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey
201ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    if (Status == EFI_BUFFER_TOO_SMALL) {
202ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      DestVolumeInfo = AllocateZeroPool(DestVolumeInfoSize);
203f06be00e7aea1dc89c63728d20247a85f1511139jcarsey      Status = DestVolumeFP->GetInfo(
204f06be00e7aea1dc89c63728d20247a85f1511139jcarsey        DestVolumeFP,
205f06be00e7aea1dc89c63728d20247a85f1511139jcarsey        &gEfiFileSystemInfoGuid,
206f06be00e7aea1dc89c63728d20247a85f1511139jcarsey        &DestVolumeInfoSize,
207f06be00e7aea1dc89c63728d20247a85f1511139jcarsey        DestVolumeInfo
208f06be00e7aea1dc89c63728d20247a85f1511139jcarsey        );
209ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    }
210f06be00e7aea1dc89c63728d20247a85f1511139jcarsey
211ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //
212ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //check if enough space available on destination drive to complete copy
213ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    //
214ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    if (DestVolumeInfo!= NULL && (DestVolumeInfo->FreeSpace < SourceFileSize)) {
215f06be00e7aea1dc89c63728d20247a85f1511139jcarsey      //
216ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      //not enough space on destination directory to copy file
217f06be00e7aea1dc89c63728d20247a85f1511139jcarsey      //
218f06be00e7aea1dc89c63728d20247a85f1511139jcarsey      SHELL_FREE_NON_NULL(DestVolumeInfo);
219ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_FAIL), gShellLevel2HiiHandle);
220ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      return(SHELL_VOLUME_FULL);
221ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    } else {
222ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      //
223ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      // copy data between files
224ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      //
225ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      Buffer = AllocateZeroPool(ReadSize);
226ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      ASSERT(Buffer != NULL);
227ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      while (ReadSize == PcdGet32(PcdShellFileOperationSize) && !EFI_ERROR(Status)) {
228ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey        Status = ShellReadFile(SourceHandle, &ReadSize, Buffer);
229f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu        if (!EFI_ERROR(Status)) {
230f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu          Status = ShellWriteFile(DestHandle, &ReadSize, Buffer);
231f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu          if (EFI_ERROR(Status)) {
232f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu            ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT));
233f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_WRITE_ERROR), gShellLevel2HiiHandle, Dest);
234f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu            break;
235f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu          }
236f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu        } else {
237f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu          ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT));
238f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_READ_ERROR), gShellLevel2HiiHandle, Source);
239f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu          break;
240f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu        }
241ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      }
242a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
243ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    SHELL_FREE_NON_NULL(DestVolumeInfo);
244ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey  }
245f3a14a0f575e7e856ff4d90d7d0ab73f7e02ae41Shumin Qiu
246a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
247a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // close files
248a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
249a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (DestHandle != NULL) {
250a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ShellCloseFile(&DestHandle);
251a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    DestHandle   = NULL;
252a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
253a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (SourceHandle != NULL) {
254a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ShellCloseFile(&SourceHandle);
255a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    SourceHandle = NULL;
256a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
257a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
258a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
259a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // return
260a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
261e755a4ca10aad316c3620223206d63982793b26cjcarsey  return ShellStatus;
262a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey}
263a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
264a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey/**
265a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  function to take a list of files to copy and a destination location and do
266a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  the verification and copying of those files to that location.  This function
267a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  will report any errors to the user and halt.
268a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
269a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  The key is to have this function called ONLY once.  this allows for the parameter
270a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  verification to happen correctly.
271a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
272b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] FileList           A LIST_ENTRY* based list of files to move.
273b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] DestDir            The destination location.
274b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] SilentMode         TRUE to eliminate screen output.
275b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] RecursiveMode      TRUE to copy directories.
276b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] Resp               The response to the overwrite query (if always).
277a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
278a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval SHELL_SUCCESS             the files were all moved.
279a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval SHELL_INVALID_PARAMETER   a parameter was invalid
280a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval SHELL_SECURITY_VIOLATION  a security violation ocurred
281a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval SHELL_WRITE_PROTECTED     the destination was write protected
282a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval SHELL_OUT_OF_RESOURCES    a memory allocation failed
283a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey**/
284a405b86d274d32b92f69842bfb9a1ab143128f57jcarseySHELL_STATUS
285a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFIAPI
286a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyValidateAndCopyFiles(
287a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN CONST EFI_SHELL_FILE_INFO  *FileList,
288a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN CONST CHAR16               *DestDir,
289a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN BOOLEAN                    SilentMode,
290a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN BOOLEAN                    RecursiveMode,
291a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN VOID                       **Resp
292a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  )
293a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey{
294a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  CHAR16                    *HiiOutput;
295a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  CHAR16                    *HiiResultOk;
296a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  CONST EFI_SHELL_FILE_INFO *Node;
297a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  SHELL_STATUS              ShellStatus;
2980960ba17e596812f211ba334cc6699d45bada328Qiu Shumin  EFI_STATUS                Status;
299a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  CHAR16                    *DestPath;
300a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  VOID                      *Response;
301e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey  UINTN                     PathSize;
302a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  CONST CHAR16              *Cwd;
303a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  UINTN                     NewSize;
3040960ba17e596812f211ba334cc6699d45bada328Qiu Shumin  CHAR16                    *CleanFilePathStr;
305a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
306a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (Resp == NULL) {
307a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    Response = NULL;
308a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  } else {
309a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    Response = *Resp;
310a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
311a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
312715096c2448412e54a95092942a397bd4d697524Qiu Shumin  DestPath         = NULL;
313715096c2448412e54a95092942a397bd4d697524Qiu Shumin  ShellStatus      = SHELL_SUCCESS;
314715096c2448412e54a95092942a397bd4d697524Qiu Shumin  PathSize         = 0;
315715096c2448412e54a95092942a397bd4d697524Qiu Shumin  Cwd              = ShellGetCurrentDir(NULL);
316715096c2448412e54a95092942a397bd4d697524Qiu Shumin  CleanFilePathStr = NULL;
317a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
318a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ASSERT(FileList != NULL);
319a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ASSERT(DestDir  != NULL);
320a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
3210960ba17e596812f211ba334cc6699d45bada328Qiu Shumin
3220960ba17e596812f211ba334cc6699d45bada328Qiu Shumin  Status = ShellLevel2StripQuotes (DestDir, &CleanFilePathStr);
3230960ba17e596812f211ba334cc6699d45bada328Qiu Shumin  if (EFI_ERROR (Status)) {
3240960ba17e596812f211ba334cc6699d45bada328Qiu Shumin    if (Status == EFI_OUT_OF_RESOURCES) {
3250960ba17e596812f211ba334cc6699d45bada328Qiu Shumin      return SHELL_OUT_OF_RESOURCES;
3260960ba17e596812f211ba334cc6699d45bada328Qiu Shumin    } else {
3270960ba17e596812f211ba334cc6699d45bada328Qiu Shumin      return SHELL_INVALID_PARAMETER;
3280960ba17e596812f211ba334cc6699d45bada328Qiu Shumin    }
329427d61ad4ad1462b5f4370a78eb58c1ba73680b4Qiu Shumin  }
330427d61ad4ad1462b5f4370a78eb58c1ba73680b4Qiu Shumin
331427d61ad4ad1462b5f4370a78eb58c1ba73680b4Qiu Shumin  ASSERT (CleanFilePathStr != NULL);
3320960ba17e596812f211ba334cc6699d45bada328Qiu Shumin
333a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
334a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // If we are trying to copy multiple files... make sure we got a directory for the target...
335a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
3360960ba17e596812f211ba334cc6699d45bada328Qiu Shumin  if (EFI_ERROR(ShellIsDirectory(CleanFilePathStr)) && FileList->Link.ForwardLink != FileList->Link.BackLink) {
337a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
338a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    // Error for destination not a directory
339a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
3400960ba17e596812f211ba334cc6699d45bada328Qiu Shumin    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, CleanFilePathStr);
3410960ba17e596812f211ba334cc6699d45bada328Qiu Shumin    FreePool (CleanFilePathStr);
342a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    return (SHELL_INVALID_PARAMETER);
343a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
344a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
345a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ;  !IsNull(&FileList->Link, &Node->Link)
346a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ;  Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
347f06be00e7aea1dc89c63728d20247a85f1511139jcarsey    ){
348a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
349a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    // skip the directory traversing stuff...
350a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
351a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
352a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      continue;
353a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
354a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
3550960ba17e596812f211ba334cc6699d45bada328Qiu Shumin    NewSize =  StrSize(CleanFilePathStr);
356b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey    NewSize += StrSize(Node->FullName);
357ed053afece04120c1c62163475806d6aef3bc329Eric Dong    NewSize += (Cwd == NULL)? 0 : StrSize(Cwd);
358e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey    if (NewSize > PathSize) {
359e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey      PathSize = NewSize;
360a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
361a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
362a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
363a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    // Make sure got -r if required
364a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
365a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (!RecursiveMode && !EFI_ERROR(ShellIsDirectory(Node->FullName))) {
366a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_REQ), gShellLevel2HiiHandle);
3670960ba17e596812f211ba334cc6699d45bada328Qiu Shumin      FreePool (CleanFilePathStr);
368a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      return (SHELL_INVALID_PARAMETER);
369a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
370a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
371a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
372a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    // make sure got dest as dir if needed
373a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
3740960ba17e596812f211ba334cc6699d45bada328Qiu Shumin    if (!EFI_ERROR(ShellIsDirectory(Node->FullName)) && EFI_ERROR(ShellIsDirectory(CleanFilePathStr))) {
375a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      //
376a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      // Error for destination not a directory
377a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      //
3780960ba17e596812f211ba334cc6699d45bada328Qiu Shumin      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, CleanFilePathStr);
3790960ba17e596812f211ba334cc6699d45bada328Qiu Shumin      FreePool (CleanFilePathStr);
380a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      return (SHELL_INVALID_PARAMETER);
381a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
382a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
383a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
384a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  HiiOutput   = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_CP_OUTPUT), NULL);
385a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL);
386e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey  DestPath    = AllocateZeroPool(PathSize);
387a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
3883e082d58262da4108a3f1f2ee8fa0a9441bb2a9bjcarsey  if (DestPath == NULL || HiiOutput == NULL || HiiResultOk == NULL) {
3899ea69f8a05b808b4bab81b608436a02e2f2fba09jcarsey    SHELL_FREE_NON_NULL(DestPath);
3909ea69f8a05b808b4bab81b608436a02e2f2fba09jcarsey    SHELL_FREE_NON_NULL(HiiOutput);
3919ea69f8a05b808b4bab81b608436a02e2f2fba09jcarsey    SHELL_FREE_NON_NULL(HiiResultOk);
3920960ba17e596812f211ba334cc6699d45bada328Qiu Shumin    FreePool (CleanFilePathStr);
3939ea69f8a05b808b4bab81b608436a02e2f2fba09jcarsey    return (SHELL_OUT_OF_RESOURCES);
3949ea69f8a05b808b4bab81b608436a02e2f2fba09jcarsey  }
3959ea69f8a05b808b4bab81b608436a02e2f2fba09jcarsey
396a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
397a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // Go through the list of files to copy...
398a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
399a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
400a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ;  !IsNull(&FileList->Link, &Node->Link)
401a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ;  Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
402f06be00e7aea1dc89c63728d20247a85f1511139jcarsey    ){
403a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (ShellGetExecutionBreakFlag()) {
404a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      break;
405a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
406a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ASSERT(Node->FileName != NULL);
407a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ASSERT(Node->FullName != NULL);
408a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
409a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
410a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    // skip the directory traversing stuff...
411a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
412a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
413a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      continue;
414a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
415a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
416a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (FileList->Link.ForwardLink == FileList->Link.BackLink // 1 item
4170960ba17e596812f211ba334cc6699d45bada328Qiu Shumin      && EFI_ERROR(ShellIsDirectory(CleanFilePathStr))                 // not an existing directory
418f06be00e7aea1dc89c63728d20247a85f1511139jcarsey      ) {
4190960ba17e596812f211ba334cc6699d45bada328Qiu Shumin      if (StrStr(CleanFilePathStr, L":") == NULL) {
420b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey        //
421b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey        // simple copy of a single file
422b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey        //
423ed053afece04120c1c62163475806d6aef3bc329Eric Dong        if (Cwd != NULL) {
424e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey          StrnCpy(DestPath, Cwd, PathSize/sizeof(CHAR16)-1);
425ed053afece04120c1c62163475806d6aef3bc329Eric Dong        } else {
4260960ba17e596812f211ba334cc6699d45bada328Qiu Shumin          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, CleanFilePathStr);
4270960ba17e596812f211ba334cc6699d45bada328Qiu Shumin          FreePool (CleanFilePathStr);
428ed053afece04120c1c62163475806d6aef3bc329Eric Dong          return (SHELL_INVALID_PARAMETER);
429ed053afece04120c1c62163475806d6aef3bc329Eric Dong        }
4300960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        if (DestPath[StrLen(DestPath)-1] != L'\\' && CleanFilePathStr[0] != L'\\') {
431e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey          StrnCat(DestPath, L"\\", PathSize/sizeof(CHAR16) - StrLen(DestPath) -1);
4320960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        } else if (DestPath[StrLen(DestPath)-1] == L'\\' && CleanFilePathStr[0] == L'\\') {
433b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey          ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
434b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey        }
4350960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        StrnCat(DestPath, CleanFilePathStr, PathSize/sizeof(CHAR16) - StrLen(DestPath) -1);
436b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey      } else {
4370960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        StrnCpy(DestPath, CleanFilePathStr, PathSize/sizeof(CHAR16) -1);
438a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      }
439a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    } else {
440a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      //
441a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      // we have multiple files or a directory in the DestDir
442a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      //
4431fc3749dad42e8d5caebf6e0e0327b713b6adaebjcarsey
4441fc3749dad42e8d5caebf6e0e0327b713b6adaebjcarsey      //
4451fc3749dad42e8d5caebf6e0e0327b713b6adaebjcarsey      // Check for leading slash
4461fc3749dad42e8d5caebf6e0e0327b713b6adaebjcarsey      //
4470960ba17e596812f211ba334cc6699d45bada328Qiu Shumin      if (CleanFilePathStr[0] == L'\\') {
448ed053afece04120c1c62163475806d6aef3bc329Eric Dong         //
449ed053afece04120c1c62163475806d6aef3bc329Eric Dong         // Copy to the root of CWD
450ed053afece04120c1c62163475806d6aef3bc329Eric Dong         //
451ed053afece04120c1c62163475806d6aef3bc329Eric Dong        if (Cwd != NULL) {
452e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey          StrnCpy(DestPath, Cwd, PathSize/sizeof(CHAR16) -1);
453ed053afece04120c1c62163475806d6aef3bc329Eric Dong        } else {
4540960ba17e596812f211ba334cc6699d45bada328Qiu Shumin          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, CleanFilePathStr);
4550960ba17e596812f211ba334cc6699d45bada328Qiu Shumin          FreePool(CleanFilePathStr);
456ed053afece04120c1c62163475806d6aef3bc329Eric Dong          return (SHELL_INVALID_PARAMETER);
457ed053afece04120c1c62163475806d6aef3bc329Eric Dong        }
4581fc3749dad42e8d5caebf6e0e0327b713b6adaebjcarsey        while (PathRemoveLastItem(DestPath));
4590960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        StrnCat(DestPath, CleanFilePathStr+1, PathSize/sizeof(CHAR16) - StrLen(DestPath) -1);
460e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey        StrnCat(DestPath, Node->FileName, PathSize/sizeof(CHAR16) - StrLen(DestPath) -1);
4610960ba17e596812f211ba334cc6699d45bada328Qiu Shumin      } else if (StrStr(CleanFilePathStr, L":") == NULL) {
462ed053afece04120c1c62163475806d6aef3bc329Eric Dong        if (Cwd != NULL) {
463e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey          StrnCpy(DestPath, Cwd, PathSize/sizeof(CHAR16) -1);
464ed053afece04120c1c62163475806d6aef3bc329Eric Dong        } else {
4650960ba17e596812f211ba334cc6699d45bada328Qiu Shumin          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, CleanFilePathStr);
4660960ba17e596812f211ba334cc6699d45bada328Qiu Shumin          FreePool(CleanFilePathStr);
467ed053afece04120c1c62163475806d6aef3bc329Eric Dong          return (SHELL_INVALID_PARAMETER);
468ed053afece04120c1c62163475806d6aef3bc329Eric Dong        }
4690960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        if (DestPath[StrLen(DestPath)-1] != L'\\' && CleanFilePathStr[0] != L'\\') {
470e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey          StrnCat(DestPath, L"\\", PathSize/sizeof(CHAR16) - StrLen(DestPath) -1);
4710960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        } else if (DestPath[StrLen(DestPath)-1] == L'\\' && CleanFilePathStr[0] == L'\\') {
472a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
473a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        }
4740960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        StrnCat(DestPath, CleanFilePathStr, PathSize/sizeof(CHAR16) - StrLen(DestPath) -1);
4750960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] != L'\\' && Node->FileName[0] != L'\\') {
476e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey          StrnCat(DestPath, L"\\", PathSize/sizeof(CHAR16) - StrLen(DestPath) -1);
4770960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        } else if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] == L'\\' && Node->FileName[0] == L'\\') {
478a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
479a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        }
480e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey        StrnCat(DestPath, Node->FileName, PathSize/sizeof(CHAR16) - StrLen(DestPath) -1);
481a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
482a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      } else {
4830960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        StrnCpy(DestPath, CleanFilePathStr, PathSize/sizeof(CHAR16) -1);
4840960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] != L'\\' && Node->FileName[0] != L'\\') {
485e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey          StrnCat(DestPath, L"\\", PathSize/sizeof(CHAR16) - StrLen(DestPath) -1);
4860960ba17e596812f211ba334cc6699d45bada328Qiu Shumin        } else if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] == L'\\' && Node->FileName[0] == L'\\') {
4870960ba17e596812f211ba334cc6699d45bada328Qiu Shumin          ((CHAR16*)CleanFilePathStr)[StrLen(CleanFilePathStr)-1] = CHAR_NULL;
488a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        }
489e1044f8074836b74188a2371ba70be05d0e0482bJaben Carsey        StrnCat(DestPath, Node->FileName, PathSize/sizeof(CHAR16) - StrLen(DestPath) -1);
490a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      }
491a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
492a6e84d95f50a10e23ee9861270fb84057b5af2e9Ni Ruiyu
493a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
494a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    // Make sure the path exists
495a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
496a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (EFI_ERROR(VerifyIntermediateDirectories(DestPath))) {
497a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_WNF), gShellLevel2HiiHandle);
498a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellStatus = SHELL_DEVICE_ERROR;
499a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      break;
500a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
501a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
502a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if ( !EFI_ERROR(ShellIsDirectory(Node->FullName))
503a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      && !EFI_ERROR(ShellIsDirectory(DestPath))
504a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      && StrniCmp(Node->FullName, DestPath, StrLen(DestPath)) == NULL
505f06be00e7aea1dc89c63728d20247a85f1511139jcarsey      ){
506a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_PARENT), gShellLevel2HiiHandle);
507a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellStatus = SHELL_INVALID_PARAMETER;
508a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      break;
509a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
510a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (StringNoCaseCompare(&Node->FullName, &DestPath) == 0) {
511a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle);
512a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellStatus = SHELL_INVALID_PARAMETER;
513a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      break;
514a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
515a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
5165051c2873b78114da6349e1c7e0754233f6c0024Olivier Martin    if ((StrniCmp(Node->FullName, DestPath, StrLen(Node->FullName)) == 0)
517a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      && (DestPath[StrLen(Node->FullName)] == CHAR_NULL || DestPath[StrLen(Node->FullName)] == L'\\')
518f06be00e7aea1dc89c63728d20247a85f1511139jcarsey      ) {
519a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle);
520a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellStatus = SHELL_INVALID_PARAMETER;
521a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      break;
522a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
523a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
524ab94587a7d2cd89695f9190420daceae0d2b7446jcarsey    PathCleanUpDirectories(DestPath);
525a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
526a737ea734b9d64d6b10e399d5d0a8539604decddJaben Carsey    if (!SilentMode) {
527a737ea734b9d64d6b10e399d5d0a8539604decddJaben Carsey      ShellPrintEx(-1, -1, HiiOutput, Node->FullName, DestPath);
528a737ea734b9d64d6b10e399d5d0a8539604decddJaben Carsey    }
529a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
530a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
531a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    // copy single file...
532a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
533a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ShellStatus = CopySingleFile(Node->FullName, DestPath, &Response, SilentMode);
534a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (ShellStatus != SHELL_SUCCESS) {
535a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      break;
536a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
537a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
538a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (ShellStatus == SHELL_SUCCESS && Resp == NULL) {
539a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ShellPrintEx(-1, -1, L"%s", HiiResultOk);
540a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
541a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
542a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  SHELL_FREE_NON_NULL(DestPath);
543a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  SHELL_FREE_NON_NULL(HiiOutput);
544a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  SHELL_FREE_NON_NULL(HiiResultOk);
545a6e84d95f50a10e23ee9861270fb84057b5af2e9Ni Ruiyu  SHELL_FREE_NON_NULL(CleanFilePathStr);
546590c3cb14ad6547528ea13805817676e32c204aajcarsey  if (Resp == NULL) {
547a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    SHELL_FREE_NON_NULL(Response);
548a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
549a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
550a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  return (ShellStatus);
551f06be00e7aea1dc89c63728d20247a85f1511139jcarsey
552a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey}
553a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
554b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey/**
555b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  Validate and if successful copy all the files from the list into
556b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  destination directory.
557b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey
558b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] FileList       The list of files to copy.
559b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] DestDir        The directory to copy files to.
560b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] SilentMode     TRUE to eliminate screen output.
561b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @param[in] RecursiveMode  TRUE to copy directories.
562b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey
563b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @retval SHELL_INVALID_PARAMETER   A parameter was invalid.
564b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey  @retval SHELL_SUCCESS             The operation was successful.
565b54fd049bdfa0d9520a40d8a1783aa681b40d751jcarsey**/
566a405b86d274d32b92f69842bfb9a1ab143128f57jcarseySHELL_STATUS
567a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFIAPI
568a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyProcessValidateAndCopyFiles(
569a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN       EFI_SHELL_FILE_INFO  *FileList,
570a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN CONST CHAR16               *DestDir,
571a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN BOOLEAN                    SilentMode,
572a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN BOOLEAN                    RecursiveMode
573a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  )
574a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey{
575a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  SHELL_STATUS        ShellStatus;
576a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  EFI_SHELL_FILE_INFO *List;
577a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  EFI_FILE_INFO       *FileInfo;
578ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey  CHAR16              *FullName;
579a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
580ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey  List      = NULL;
581ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey  FullName  = NULL;
5829f56625f2a904701f460c88a7dbfaf17c4c83a22Jaben Carsey  FileInfo  = NULL;
583a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
584e755a4ca10aad316c3620223206d63982793b26cjcarsey  ShellOpenFileMetaArg((CHAR16*)DestDir, EFI_FILE_MODE_READ, &List);
585a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (List != NULL && List->Link.ForwardLink != List->Link.BackLink) {
586a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, DestDir);
587a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ShellStatus = SHELL_INVALID_PARAMETER;
588a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ShellCloseFileMetaArg(&List);
589a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  } else if (List != NULL) {
590a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink) != NULL);
591a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName != NULL);
592a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    FileInfo = gEfiShellProtocol->GetFileInfo(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->Handle);
593a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ASSERT(FileInfo != NULL);
594ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    StrnCatGrow(&FullName, NULL, ((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName, 0);
595ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    ShellCloseFileMetaArg(&List);
596a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) == 0) {
597ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey      ShellStatus = ValidateAndCopyFiles(FileList, FullName, SilentMode, RecursiveMode, NULL);
598a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    } else {
599a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_ERROR), gShellLevel2HiiHandle);
600a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellStatus = SHELL_ACCESS_DENIED;
601a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
602a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  } else {
603ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey    ShellCloseFileMetaArg(&List);
604ed053afece04120c1c62163475806d6aef3bc329Eric Dong    ShellStatus = ValidateAndCopyFiles(FileList, DestDir, SilentMode, RecursiveMode, NULL);
605a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
606a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
607ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey  SHELL_FREE_NON_NULL(FileInfo);
608ac8783c8b162b9a3b1e2da222cf6d088fcf63cfbJaben Carsey  SHELL_FREE_NON_NULL(FullName);
609a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  return (ShellStatus);
610a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey}
611a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
612a405b86d274d32b92f69842bfb9a1ab143128f57jcarseySTATIC CONST SHELL_PARAM_ITEM ParamList[] = {
613a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  {L"-r", TypeFlag},
614a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  {L"-q", TypeFlag},
615a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  {NULL, TypeMax}
616a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  };
617a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
618a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey/**
619a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Function for 'cp' command.
620a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
621a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @param[in] ImageHandle  Handle to the Image (NULL if Internal).
622a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
623a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey**/
624a405b86d274d32b92f69842bfb9a1ab143128f57jcarseySHELL_STATUS
625a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFIAPI
626a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyShellCommandRunCp (
627a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN EFI_HANDLE        ImageHandle,
628a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN EFI_SYSTEM_TABLE  *SystemTable
629a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  )
630a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey{
631a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  EFI_STATUS          Status;
632a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  LIST_ENTRY          *Package;
633a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  CHAR16              *ProblemParam;
634a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  SHELL_STATUS        ShellStatus;
635a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  UINTN               ParamCount;
636a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  UINTN               LoopCounter;
637a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  EFI_SHELL_FILE_INFO *FileList;
638a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  BOOLEAN             SilentMode;
639a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  BOOLEAN             RecursiveMode;
640a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  CONST CHAR16        *Cwd;
641a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
642a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ProblemParam        = NULL;
643a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ShellStatus         = SHELL_SUCCESS;
644a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ParamCount          = 0;
645a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  FileList            = NULL;
646a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
647a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
648a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // initialize the shell lib (we must be in non-auto-init...)
649a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
650a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Status = ShellInitialize();
651a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ASSERT_EFI_ERROR(Status);
652a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
653a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Status = CommandInit();
654a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ASSERT_EFI_ERROR(Status);
655a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
656a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
657a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // parse the command line
658a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
659a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
660a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (EFI_ERROR(Status)) {
661a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
662a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
663a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      FreePool(ProblemParam);
664a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellStatus = SHELL_INVALID_PARAMETER;
665a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    } else {
666a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ASSERT(FALSE);
667a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
668a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  } else {
669a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
670a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    // check for "-?"
671a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
672a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (ShellCommandLineGetFlag(Package, L"-?")) {
673a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ASSERT(FALSE);
674a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
675a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
676a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
677a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    // Initialize SilentMode and RecursiveMode
678a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
679a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (gEfiShellProtocol->BatchIsActive()) {
680a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      SilentMode = TRUE;
681a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    } else {
682a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      SilentMode = ShellCommandLineGetFlag(Package, L"-q");
683a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
684a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    RecursiveMode = ShellCommandLineGetFlag(Package, L"-r");
685a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
686a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    switch (ParamCount = ShellCommandLineGetCount(Package)) {
687a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      case 0:
688a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      case 1:
689a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        //
690a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        // we have insufficient parameters
691a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        //
692a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
693a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        ShellStatus = SHELL_INVALID_PARAMETER;
694a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        break;
695a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      case 2:
696a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        //
697a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        // must have valid CWD for single parameter...
698a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        //
699a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        Cwd = ShellGetCurrentDir(NULL);
700a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        if (Cwd == NULL){
701a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
702a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          ShellStatus = SHELL_INVALID_PARAMETER;
703a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        } else {
704a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
705a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {
706a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));
707a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey            ShellStatus = SHELL_NOT_FOUND;
708a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          } else  {
709a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey            ShellStatus = ProcessValidateAndCopyFiles(FileList, Cwd, SilentMode, RecursiveMode);
710a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          }
711a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        }
712a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
713a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        break;
714a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      default:
715a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        //
716a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        // Make a big list of all the files...
717a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        //
718a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount && ShellStatus == SHELL_SUCCESS ; LoopCounter++) {
719a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          if (ShellGetExecutionBreakFlag()) {
720a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey            break;
721a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          }
722a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
723a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {
724b2bf9735860994b4f4ae3904fd784bedcdd26da1jcarsey            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, LoopCounter));
725a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey            ShellStatus = SHELL_NOT_FOUND;
726a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          }
727a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        }
728b2bf9735860994b4f4ae3904fd784bedcdd26da1jcarsey        if (ShellStatus != SHELL_SUCCESS) {
729a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          Status = ShellCloseFileMetaArg(&FileList);
730b2bf9735860994b4f4ae3904fd784bedcdd26da1jcarsey        } else {
731b2bf9735860994b4f4ae3904fd784bedcdd26da1jcarsey          //
732b2bf9735860994b4f4ae3904fd784bedcdd26da1jcarsey          // now copy them all...
733b2bf9735860994b4f4ae3904fd784bedcdd26da1jcarsey          //
734b2bf9735860994b4f4ae3904fd784bedcdd26da1jcarsey          if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
735ab94587a7d2cd89695f9190420daceae0d2b7446jcarsey            ShellStatus = ProcessValidateAndCopyFiles(FileList, PathCleanUpDirectories((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount)), SilentMode, RecursiveMode);
736b2bf9735860994b4f4ae3904fd784bedcdd26da1jcarsey            Status = ShellCloseFileMetaArg(&FileList);
737b2bf9735860994b4f4ae3904fd784bedcdd26da1jcarsey            if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
738b2bf9735860994b4f4ae3904fd784bedcdd26da1jcarsey              ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamCount), ShellStatus|MAX_BIT);
739b2bf9735860994b4f4ae3904fd784bedcdd26da1jcarsey              ShellStatus = SHELL_ACCESS_DENIED;
740b2bf9735860994b4f4ae3904fd784bedcdd26da1jcarsey            }
741a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey          }
742a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        }
743a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        break;
744a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    } // switch on parameter count
745a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
746a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (FileList != NULL) {
747a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ShellCloseFileMetaArg(&FileList);
748a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
749a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
750a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
751a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    // free the command line package
752a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    //
753a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ShellCommandLineFreeVarList (Package);
754a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
755a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
756a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (ShellGetExecutionBreakFlag()) {
757a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    return (SHELL_ABORTED);
758a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
759a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
760a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  return (ShellStatus);
761a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey}
762a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
763