]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c
didn't mean to remove this comment.
[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
b54fd049 4 Copyright (c) 2009 - 2011, 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
150 TempName = NULL;\r
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
257 //\r
258 // If we are trying to copy multiple files... make sure we got a directory for the target...\r
259 //\r
260 if (EFI_ERROR(ShellIsDirectory(DestDir)) && FileList->Link.ForwardLink != FileList->Link.BackLink) {\r
261 //\r
262 // Error for destination not a directory\r
263 //\r
264 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir);\r
265 return (SHELL_INVALID_PARAMETER);\r
266 }\r
267 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)\r
268 ; !IsNull(&FileList->Link, &Node->Link)\r
269 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)\r
270 ){\r
271 //\r
272 // skip the directory traversing stuff...\r
273 //\r
274 if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {\r
275 continue;\r
276 }\r
277\r
278 NewSize = StrSize(DestDir);\r
b54fd049 279 NewSize += StrSize(Node->FullName);\r
a405b86d 280 NewSize += StrSize(Cwd);\r
281 if (NewSize > PathLen) {\r
282 PathLen = NewSize;\r
283 }\r
284\r
285 //\r
286 // Make sure got -r if required\r
287 //\r
288 if (!RecursiveMode && !EFI_ERROR(ShellIsDirectory(Node->FullName))) {\r
289 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_REQ), gShellLevel2HiiHandle);\r
290 return (SHELL_INVALID_PARAMETER);\r
291 }\r
292\r
293 //\r
294 // make sure got dest as dir if needed\r
295 //\r
296 if (!EFI_ERROR(ShellIsDirectory(Node->FullName)) && EFI_ERROR(ShellIsDirectory(DestDir))) {\r
297 //\r
298 // Error for destination not a directory\r
299 //\r
300 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir);\r
301 return (SHELL_INVALID_PARAMETER);\r
302 }\r
303 }\r
304\r
305 HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_CP_OUTPUT), NULL);\r
306 HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL);\r
b54fd049 307 DestPath = AllocateZeroPool(PathLen);\r
a405b86d 308\r
3e082d58 309 if (DestPath == NULL || HiiOutput == NULL || HiiResultOk == NULL) {\r
9ea69f8a 310 SHELL_FREE_NON_NULL(DestPath);\r
311 SHELL_FREE_NON_NULL(HiiOutput);\r
312 SHELL_FREE_NON_NULL(HiiResultOk);\r
313 return (SHELL_OUT_OF_RESOURCES);\r
314 }\r
315\r
a405b86d 316 //\r
317 // Go through the list of files to copy...\r
318 //\r
319 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)\r
320 ; !IsNull(&FileList->Link, &Node->Link)\r
321 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)\r
322 ){\r
323 if (ShellGetExecutionBreakFlag()) {\r
324 break;\r
325 }\r
326 ASSERT(Node->FileName != NULL);\r
327 ASSERT(Node->FullName != NULL);\r
328\r
329 //\r
330 // skip the directory traversing stuff...\r
331 //\r
332 if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {\r
333 continue;\r
334 }\r
335\r
336 if (FileList->Link.ForwardLink == FileList->Link.BackLink // 1 item\r
337 && EFI_ERROR(ShellIsDirectory(DestDir)) // not an existing directory\r
338 ) {\r
b54fd049 339 if (StrStr(DestDir, L":") == NULL) {\r
340 //\r
341 // simple copy of a single file\r
342 //\r
343 StrCpy(DestPath, Cwd);\r
344 if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') {\r
345 StrCat(DestPath, L"\\");\r
346 } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') {\r
347 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;\r
348 }\r
349 StrCat(DestPath, DestDir);\r
350 } else {\r
351 StrCpy(DestPath, DestDir);\r
a405b86d 352 }\r
a405b86d 353 } else {\r
354 //\r
355 // we have multiple files or a directory in the DestDir\r
356 //\r
357 if (StrStr(DestDir, L":") == NULL) {\r
358 StrCpy(DestPath, Cwd);\r
359 if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') {\r
360 StrCat(DestPath, L"\\");\r
361 } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') {\r
362 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;\r
363 }\r
364 StrCat(DestPath, DestDir);\r
365 if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') {\r
366 StrCat(DestPath, L"\\");\r
367 } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') {\r
368 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;\r
369 }\r
370 StrCat(DestPath, Node->FileName);\r
371\r
372 } else {\r
373 StrCpy(DestPath, DestDir);\r
374 if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') {\r
375 StrCat(DestPath, L"\\");\r
376 } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') {\r
377 ((CHAR16*)DestDir)[StrLen(DestDir)-1] = CHAR_NULL;\r
378 }\r
379 StrCat(DestPath, Node->FileName);\r
380 }\r
381 }\r
382\r
383 //\r
384 // Make sure the path exists\r
385 //\r
386 if (EFI_ERROR(VerifyIntermediateDirectories(DestPath))) {\r
387 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_WNF), gShellLevel2HiiHandle);\r
388 ShellStatus = SHELL_DEVICE_ERROR;\r
389 break;\r
390 }\r
391\r
392 if ( !EFI_ERROR(ShellIsDirectory(Node->FullName))\r
393 && !EFI_ERROR(ShellIsDirectory(DestPath))\r
394 && StrniCmp(Node->FullName, DestPath, StrLen(DestPath)) == NULL\r
395 ){\r
396 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_PARENT), gShellLevel2HiiHandle);\r
397 ShellStatus = SHELL_INVALID_PARAMETER;\r
398 break;\r
399 }\r
400 if (StringNoCaseCompare(&Node->FullName, &DestPath) == 0) {\r
401 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle);\r
402 ShellStatus = SHELL_INVALID_PARAMETER;\r
403 break;\r
404 }\r
405\r
406 if ((TempLocation = StrniCmp(Node->FullName, DestPath, StrLen(Node->FullName))) == 0\r
407 && (DestPath[StrLen(Node->FullName)] == CHAR_NULL || DestPath[StrLen(Node->FullName)] == L'\\')\r
408 ) {\r
409 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle);\r
410 ShellStatus = SHELL_INVALID_PARAMETER;\r
411 break;\r
412 }\r
413\r
414 CleanPath(DestPath);\r
415\r
416 ShellPrintEx(-1, -1, HiiOutput, Node->FullName, DestPath);\r
417\r
418 //\r
419 // copy single file...\r
420 //\r
421 ShellStatus = CopySingleFile(Node->FullName, DestPath, &Response, SilentMode);\r
422 if (ShellStatus != SHELL_SUCCESS) {\r
423 break;\r
424 }\r
425 }\r
426 if (ShellStatus == SHELL_SUCCESS && Resp == NULL) {\r
427 ShellPrintEx(-1, -1, L"%s", HiiResultOk);\r
428 }\r
429\r
430 SHELL_FREE_NON_NULL(DestPath);\r
431 SHELL_FREE_NON_NULL(HiiOutput);\r
432 SHELL_FREE_NON_NULL(HiiResultOk);\r
590c3cb1 433 if (Resp == NULL) {\r
a405b86d 434 SHELL_FREE_NON_NULL(Response);\r
435 }\r
436\r
437 return (ShellStatus);\r
438}\r
439\r
b54fd049 440/**\r
441 Validate and if successful copy all the files from the list into \r
442 destination directory.\r
443\r
444 @param[in] FileList The list of files to copy.\r
445 @param[in] DestDir The directory to copy files to.\r
446 @param[in] SilentMode TRUE to eliminate screen output.\r
447 @param[in] RecursiveMode TRUE to copy directories.\r
448\r
449 @retval SHELL_INVALID_PARAMETER A parameter was invalid.\r
450 @retval SHELL_SUCCESS The operation was successful.\r
451**/\r
a405b86d 452SHELL_STATUS\r
453EFIAPI\r
454ProcessValidateAndCopyFiles(\r
455 IN EFI_SHELL_FILE_INFO *FileList,\r
456 IN CONST CHAR16 *DestDir,\r
457 IN BOOLEAN SilentMode,\r
458 IN BOOLEAN RecursiveMode\r
459 )\r
460{\r
461 SHELL_STATUS ShellStatus;\r
462 EFI_SHELL_FILE_INFO *List;\r
463 EFI_STATUS Status;\r
464 EFI_FILE_INFO *FileInfo;\r
465\r
466 List = NULL;\r
467\r
468 Status = ShellOpenFileMetaArg((CHAR16*)DestDir, EFI_FILE_MODE_READ, &List);\r
469 if (List != NULL && List->Link.ForwardLink != List->Link.BackLink) {\r
470 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, DestDir);\r
471 ShellStatus = SHELL_INVALID_PARAMETER;\r
472 ShellCloseFileMetaArg(&List);\r
473 } else if (List != NULL) {\r
a405b86d 474 ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink) != NULL);\r
475 ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName != NULL);\r
476 FileInfo = NULL;\r
477 FileInfo = gEfiShellProtocol->GetFileInfo(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->Handle);\r
478 ASSERT(FileInfo != NULL);\r
479 if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) == 0) {\r
480 ShellStatus = ValidateAndCopyFiles(FileList, ((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName, SilentMode, RecursiveMode, NULL);\r
481 } else {\r
482 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_ERROR), gShellLevel2HiiHandle);\r
483 ShellStatus = SHELL_ACCESS_DENIED;\r
484 }\r
485 SHELL_FREE_NON_NULL(FileInfo);\r
486 ShellCloseFileMetaArg(&List);\r
487 } else {\r
488 ShellStatus = ValidateAndCopyFiles(FileList, DestDir, SilentMode, RecursiveMode, NULL);\r
489 }\r
490\r
491 return (ShellStatus);\r
492}\r
493\r
494STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
495 {L"-r", TypeFlag},\r
496 {L"-q", TypeFlag},\r
497 {NULL, TypeMax}\r
498 };\r
499\r
500/**\r
501 Function for 'cp' command.\r
502\r
503 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
504 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
505**/\r
506SHELL_STATUS\r
507EFIAPI\r
508ShellCommandRunCp (\r
509 IN EFI_HANDLE ImageHandle,\r
510 IN EFI_SYSTEM_TABLE *SystemTable\r
511 )\r
512{\r
513 EFI_STATUS Status;\r
514 LIST_ENTRY *Package;\r
515 CHAR16 *ProblemParam;\r
516 SHELL_STATUS ShellStatus;\r
517 UINTN ParamCount;\r
518 UINTN LoopCounter;\r
519 EFI_SHELL_FILE_INFO *FileList;\r
520 BOOLEAN SilentMode;\r
521 BOOLEAN RecursiveMode;\r
522 CONST CHAR16 *Cwd;\r
523\r
524 ProblemParam = NULL;\r
525 ShellStatus = SHELL_SUCCESS;\r
526 ParamCount = 0;\r
527 FileList = NULL;\r
528\r
529 //\r
530 // initialize the shell lib (we must be in non-auto-init...)\r
531 //\r
532 Status = ShellInitialize();\r
533 ASSERT_EFI_ERROR(Status);\r
534\r
535 Status = CommandInit();\r
536 ASSERT_EFI_ERROR(Status);\r
537\r
538 //\r
539 // parse the command line\r
540 //\r
541 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
542 if (EFI_ERROR(Status)) {\r
543 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
544 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);\r
545 FreePool(ProblemParam);\r
546 ShellStatus = SHELL_INVALID_PARAMETER;\r
547 } else {\r
548 ASSERT(FALSE);\r
549 }\r
550 } else {\r
551 //\r
552 // check for "-?"\r
553 //\r
554 if (ShellCommandLineGetFlag(Package, L"-?")) {\r
555 ASSERT(FALSE);\r
556 }\r
557\r
558 //\r
559 // Initialize SilentMode and RecursiveMode\r
560 //\r
561 if (gEfiShellProtocol->BatchIsActive()) {\r
562 SilentMode = TRUE;\r
563 } else {\r
564 SilentMode = ShellCommandLineGetFlag(Package, L"-q");\r
565 }\r
566 RecursiveMode = ShellCommandLineGetFlag(Package, L"-r");\r
567\r
568 switch (ParamCount = ShellCommandLineGetCount(Package)) {\r
569 case 0:\r
570 case 1:\r
571 //\r
572 // we have insufficient parameters\r
573 //\r
574 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);\r
575 ShellStatus = SHELL_INVALID_PARAMETER;\r
576 break;\r
577 case 2:\r
578 //\r
579 // must have valid CWD for single parameter...\r
580 //\r
581 Cwd = ShellGetCurrentDir(NULL);\r
582 if (Cwd == NULL){\r
583 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);\r
584 ShellStatus = SHELL_INVALID_PARAMETER;\r
585 } else {\r
586 Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);\r
587 if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {\r
588 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));\r
589 ShellStatus = SHELL_NOT_FOUND;\r
590 } else {\r
591 ShellStatus = ProcessValidateAndCopyFiles(FileList, Cwd, SilentMode, RecursiveMode);\r
592 }\r
593 }\r
594\r
595 break;\r
596 default:\r
597 //\r
598 // Make a big list of all the files...\r
599 //\r
600 for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount && ShellStatus == SHELL_SUCCESS ; LoopCounter++) {\r
601 if (ShellGetExecutionBreakFlag()) {\r
602 break;\r
603 }\r
604 Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);\r
605 if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {\r
606 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));\r
607 ShellStatus = SHELL_NOT_FOUND;\r
608 }\r
609 }\r
610 //\r
611 // now copy them all...\r
612 //\r
613 if (FileList != NULL && !IsListEmpty(&FileList->Link)) {\r
614 ShellStatus = ProcessValidateAndCopyFiles(FileList, ShellCommandCleanPath((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount)), SilentMode, RecursiveMode);\r
615 Status = ShellCloseFileMetaArg(&FileList);\r
616 if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {\r
617 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1), ShellStatus|MAX_BIT);\r
618 ShellStatus = SHELL_ACCESS_DENIED;\r
619 }\r
620 }\r
621\r
622 break;\r
623 } // switch on parameter count\r
624\r
625 if (FileList != NULL) {\r
626 ShellCloseFileMetaArg(&FileList);\r
627 }\r
628\r
629 //\r
630 // free the command line package\r
631 //\r
632 ShellCommandLineFreeVarList (Package);\r
633 }\r
634\r
635 if (ShellGetExecutionBreakFlag()) {\r
636 return (SHELL_ABORTED);\r
637 }\r
638\r
639 return (ShellStatus);\r
640}\r
641\r