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