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