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