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