TianoCore EDK2 master
Loading...
Searching...
No Matches
Cp.c
Go to the documentation of this file.
1
11#include <Guid/FileSystemInfo.h>
13
34 IN CONST CHAR16 *DestDir,
35 IN BOOLEAN SilentMode,
36 IN BOOLEAN RecursiveMode,
37 IN VOID **Resp
38 );
39
55 IN CONST CHAR16 *Source,
56 IN CONST CHAR16 *Dest,
57 OUT VOID **Resp,
58 IN BOOLEAN SilentMode,
59 IN CONST CHAR16 *CmdName
60 )
61{
62 VOID *Response;
63 UINTN ReadSize;
64 SHELL_FILE_HANDLE SourceHandle;
65 SHELL_FILE_HANDLE DestHandle;
66 EFI_STATUS Status;
67 VOID *Buffer;
68 CHAR16 *TempName;
69 UINTN Size;
71 SHELL_STATUS ShellStatus;
72 UINT64 SourceFileSize;
73 UINT64 DestFileSize;
74 EFI_FILE_PROTOCOL *DestVolumeFP;
75 EFI_FILE_SYSTEM_INFO *DestVolumeInfo;
76 UINTN DestVolumeInfoSize;
77
78 ASSERT (Resp != NULL);
79
80 SourceHandle = NULL;
81 DestHandle = NULL;
82 Response = *Resp;
83 List = NULL;
84 DestVolumeInfo = NULL;
85 ShellStatus = SHELL_SUCCESS;
86
87 ReadSize = PcdGet32 (PcdShellFileOperationSize);
88 // Why bother copying a file to itself
89 if (StrCmp (Source, Dest) == 0) {
90 return (SHELL_SUCCESS);
91 }
92
93 //
94 // if the destination file existed check response and possibly prompt user
95 //
96 if (ShellFileExists (Dest) == EFI_SUCCESS) {
97 if ((Response == NULL) && !SilentMode) {
98 Status = ShellPromptForResponseHii (ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response);
99 }
100
101 //
102 // possibly return based on response
103 //
104 if (!SilentMode) {
105 if (Response == NULL) {
106 return SHELL_ABORTED;
107 }
108
109 switch (*(SHELL_PROMPT_RESPONSE *)Response) {
110 case ShellPromptResponseNo:
111 //
112 // return success here so we dont stop the process
113 //
114 return (SHELL_SUCCESS);
115 case ShellPromptResponseCancel:
116 *Resp = Response;
117 //
118 // indicate to stop everything
119 //
120 return (SHELL_ABORTED);
121 case ShellPromptResponseAll:
122 *Resp = Response;
123 case ShellPromptResponseYes:
124 break;
125 default:
126 return SHELL_ABORTED;
127 }
128 }
129 }
130
131 if (ShellIsDirectory (Source) == EFI_SUCCESS) {
132 Status = ShellCreateDirectory (Dest, &DestHandle);
133 if (EFI_ERROR (Status)) {
134 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_DIR_FAIL), gShellLevel2HiiHandle, CmdName, Dest);
135 return (SHELL_ACCESS_DENIED);
136 }
137
138 //
139 // Now copy all the files under the directory...
140 //
141 TempName = NULL;
142 Size = 0;
143 StrnCatGrow (&TempName, &Size, Source, 0);
144 StrnCatGrow (&TempName, &Size, L"\\*", 0);
145 if (TempName != NULL) {
146 ShellOpenFileMetaArg ((CHAR16 *)TempName, EFI_FILE_MODE_READ, &List);
147 *TempName = CHAR_NULL;
148 StrnCatGrow (&TempName, &Size, Dest, 0);
149 StrnCatGrow (&TempName, &Size, L"\\", 0);
150 ShellStatus = ValidateAndCopyFiles (List, TempName, SilentMode, TRUE, Resp);
151 ShellCloseFileMetaArg (&List);
152 SHELL_FREE_NON_NULL (TempName);
153 Size = 0;
154 }
155 } else {
156 Status = ShellDeleteFileByName (Dest);
157
158 //
159 // open file with create enabled
160 //
161 Status = ShellOpenFileByName (Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
162 if (EFI_ERROR (Status)) {
163 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_OPEN_FAIL), gShellLevel2HiiHandle, CmdName, Dest);
164 return (SHELL_ACCESS_DENIED);
165 }
166
167 //
168 // open source file
169 //
170 Status = ShellOpenFileByName (Source, &SourceHandle, EFI_FILE_MODE_READ, 0);
171 if (EFI_ERROR (Status)) {
172 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_SRC_OPEN_FAIL), gShellLevel2HiiHandle, CmdName, Source);
173 return (SHELL_ACCESS_DENIED);
174 }
175
176 //
177 // get file size of source file and freespace available on destination volume
178 //
179 ShellGetFileSize (SourceHandle, &SourceFileSize);
180 ShellGetFileSize (DestHandle, &DestFileSize);
181
182 //
183 // if the destination file already exists then it will be replaced, meaning the sourcefile effectively needs less storage space
184 //
185 if (DestFileSize < SourceFileSize) {
186 SourceFileSize -= DestFileSize;
187 } else {
188 SourceFileSize = 0;
189 }
190
191 //
192 // get the system volume info to check the free space
193 //
194 DestVolumeFP = ConvertShellHandleToEfiFileProtocol (DestHandle);
195 DestVolumeInfo = NULL;
196 DestVolumeInfoSize = 0;
197 Status = DestVolumeFP->GetInfo (
198 DestVolumeFP,
199 &gEfiFileSystemInfoGuid,
200 &DestVolumeInfoSize,
201 DestVolumeInfo
202 );
203
204 if (Status == EFI_BUFFER_TOO_SMALL) {
205 DestVolumeInfo = AllocateZeroPool (DestVolumeInfoSize);
206 if (DestVolumeInfo == NULL) {
207 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"cp");
208 ShellStatus = SHELL_OUT_OF_RESOURCES;
209 goto Done;
210 }
211
212 Status = DestVolumeFP->GetInfo (
213 DestVolumeFP,
214 &gEfiFileSystemInfoGuid,
215 &DestVolumeInfoSize,
216 DestVolumeInfo
217 );
218 }
219
220 //
221 // check if enough space available on destination drive to complete copy
222 //
223 if ((DestVolumeInfo != NULL) && (DestVolumeInfo->FreeSpace < SourceFileSize)) {
224 //
225 // not enough space on destination directory to copy file
226 //
227 SHELL_FREE_NON_NULL (DestVolumeInfo);
228 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_FAIL), gShellLevel2HiiHandle, CmdName);
229 return (SHELL_VOLUME_FULL);
230 } else {
231 //
232 // copy data between files
233 //
234 Buffer = AllocateZeroPool (ReadSize);
235 if (Buffer == NULL) {
236 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, CmdName);
238 }
239
240 while (ReadSize == PcdGet32 (PcdShellFileOperationSize) && !EFI_ERROR (Status)) {
241 Status = ShellReadFile (SourceHandle, &ReadSize, Buffer);
242 if (!EFI_ERROR (Status)) {
243 Status = ShellWriteFile (DestHandle, &ReadSize, Buffer);
244 if (EFI_ERROR (Status)) {
245 ShellStatus = (SHELL_STATUS)(Status & (~MAX_BIT));
246 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_WRITE_ERROR), gShellLevel2HiiHandle, CmdName, Dest);
247 break;
248 }
249 } else {
250 ShellStatus = (SHELL_STATUS)(Status & (~MAX_BIT));
251 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_READ_ERROR), gShellLevel2HiiHandle, CmdName, Source);
252 break;
253 }
254 }
255 }
256
257 SHELL_FREE_NON_NULL (DestVolumeInfo);
258 }
259
260Done:
261 //
262 // close files
263 //
264 if (DestHandle != NULL) {
265 ShellCloseFile (&DestHandle);
266 DestHandle = NULL;
267 }
268
269 if (SourceHandle != NULL) {
270 ShellCloseFile (&SourceHandle);
271 SourceHandle = NULL;
272 }
273
274 //
275 // return
276 //
277 return ShellStatus;
278}
279
302 IN CONST EFI_SHELL_FILE_INFO *FileList,
303 IN CONST CHAR16 *DestDir,
304 IN BOOLEAN SilentMode,
305 IN BOOLEAN RecursiveMode,
306 IN VOID **Resp
307 )
308{
309 CHAR16 *HiiOutput;
310 CHAR16 *HiiResultOk;
312 SHELL_STATUS ShellStatus;
313 EFI_STATUS Status;
314 CHAR16 *DestPath;
315 VOID *Response;
316 UINTN PathSize;
317 CONST CHAR16 *Cwd;
318 UINTN NewSize;
319 CHAR16 *CleanFilePathStr;
320
321 if (Resp == NULL) {
322 Response = NULL;
323 } else {
324 Response = *Resp;
325 }
326
327 DestPath = NULL;
328 ShellStatus = SHELL_SUCCESS;
329 PathSize = 0;
330 Cwd = ShellGetCurrentDir (NULL);
331 CleanFilePathStr = NULL;
332
333 ASSERT (FileList != NULL);
334 ASSERT (DestDir != NULL);
335
336 Status = ShellLevel2StripQuotes (DestDir, &CleanFilePathStr);
337 if (EFI_ERROR (Status)) {
338 if (Status == EFI_OUT_OF_RESOURCES) {
340 } else {
342 }
343 }
344
345 ASSERT (CleanFilePathStr != NULL);
346
347 //
348 // If we are trying to copy multiple files... make sure we got a directory for the target...
349 //
350 if (EFI_ERROR (ShellIsDirectory (CleanFilePathStr)) && (FileList->Link.ForwardLink != FileList->Link.BackLink)) {
351 //
352 // Error for destination not a directory
353 //
354 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cp", CleanFilePathStr);
355 FreePool (CleanFilePathStr);
357 }
358
359 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link)
360 ; !IsNull (&FileList->Link, &Node->Link)
361 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode (&FileList->Link, &Node->Link)
362 )
363 {
364 //
365 // skip the directory traversing stuff...
366 //
367 if ((StrCmp (Node->FileName, L".") == 0) || (StrCmp (Node->FileName, L"..") == 0)) {
368 continue;
369 }
370
371 NewSize = StrSize (CleanFilePathStr);
372 NewSize += StrSize (Node->FullName);
373 NewSize += (Cwd == NULL) ? 0 : (StrSize (Cwd) + sizeof (CHAR16));
374 if (NewSize > PathSize) {
375 PathSize = NewSize;
376 }
377
378 //
379 // Make sure got -r if required
380 //
381 if (!RecursiveMode && !EFI_ERROR (ShellIsDirectory (Node->FullName))) {
382 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_REQ), gShellLevel2HiiHandle, L"cp");
383 FreePool (CleanFilePathStr);
385 }
386
387 //
388 // make sure got dest as dir if needed
389 //
390 if (!EFI_ERROR (ShellIsDirectory (Node->FullName)) && EFI_ERROR (ShellIsDirectory (CleanFilePathStr))) {
391 //
392 // Error for destination not a directory
393 //
394 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cp", CleanFilePathStr);
395 FreePool (CleanFilePathStr);
397 }
398 }
399
400 HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_CP_OUTPUT), NULL);
401 HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL);
402 DestPath = AllocateZeroPool (PathSize);
403
404 if ((DestPath == NULL) || (HiiOutput == NULL) || (HiiResultOk == NULL)) {
405 SHELL_FREE_NON_NULL (DestPath);
406 SHELL_FREE_NON_NULL (HiiOutput);
407 SHELL_FREE_NON_NULL (HiiResultOk);
408 FreePool (CleanFilePathStr);
409 return (SHELL_OUT_OF_RESOURCES);
410 }
411
412 //
413 // Go through the list of files to copy...
414 //
415 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link)
416 ; !IsNull (&FileList->Link, &Node->Link)
417 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode (&FileList->Link, &Node->Link)
418 )
419 {
421 break;
422 }
423
424 ASSERT (Node->FileName != NULL);
425 ASSERT (Node->FullName != NULL);
426
427 //
428 // skip the directory traversing stuff...
429 //
430 if ((StrCmp (Node->FileName, L".") == 0) || (StrCmp (Node->FileName, L"..") == 0)) {
431 continue;
432 }
433
434 if ( (FileList->Link.ForwardLink == FileList->Link.BackLink) // 1 item
435 && EFI_ERROR (ShellIsDirectory (CleanFilePathStr)) // not an existing directory
436 )
437 {
438 if (StrStr (CleanFilePathStr, L":") == NULL) {
439 //
440 // simple copy of a single file
441 //
442 if (Cwd != NULL) {
443 StrCpyS (DestPath, PathSize / sizeof (CHAR16), Cwd);
444 StrCatS (DestPath, PathSize / sizeof (CHAR16), L"\\");
445 } else {
446 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cp", CleanFilePathStr);
447 FreePool (CleanFilePathStr);
449 }
450
451 if ((DestPath[StrLen (DestPath)-1] != L'\\') && (CleanFilePathStr[0] != L'\\')) {
452 StrCatS (DestPath, PathSize / sizeof (CHAR16), L"\\");
453 } else if ((DestPath[StrLen (DestPath)-1] == L'\\') && (CleanFilePathStr[0] == L'\\')) {
454 ((CHAR16 *)DestPath)[StrLen (DestPath)-1] = CHAR_NULL;
455 }
456
457 StrCatS (DestPath, PathSize/sizeof (CHAR16), CleanFilePathStr);
458 } else {
459 StrCpyS (DestPath, PathSize/sizeof (CHAR16), CleanFilePathStr);
460 }
461 } else {
462 //
463 // we have multiple files or a directory in the DestDir
464 //
465
466 //
467 // Check for leading slash
468 //
469 if (CleanFilePathStr[0] == L'\\') {
470 //
471 // Copy to the root of CWD
472 //
473 if (Cwd != NULL) {
474 StrCpyS (DestPath, PathSize/sizeof (CHAR16), Cwd);
475 StrCatS (DestPath, PathSize/sizeof (CHAR16), L"\\");
476 } else {
477 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cp", CleanFilePathStr);
478 FreePool (CleanFilePathStr);
480 }
481
482 while (PathRemoveLastItem (DestPath)) {
483 }
484
485 StrCatS (DestPath, PathSize/sizeof (CHAR16), CleanFilePathStr+1);
486 StrCatS (DestPath, PathSize/sizeof (CHAR16), Node->FileName);
487 } else if (StrStr (CleanFilePathStr, L":") == NULL) {
488 if (Cwd != NULL) {
489 StrCpyS (DestPath, PathSize/sizeof (CHAR16), Cwd);
490 StrCatS (DestPath, PathSize/sizeof (CHAR16), L"\\");
491 } else {
492 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cp", CleanFilePathStr);
493 FreePool (CleanFilePathStr);
495 }
496
497 if ((DestPath[StrLen (DestPath)-1] != L'\\') && (CleanFilePathStr[0] != L'\\')) {
498 StrCatS (DestPath, PathSize/sizeof (CHAR16), L"\\");
499 } else if ((DestPath[StrLen (DestPath)-1] == L'\\') && (CleanFilePathStr[0] == L'\\')) {
500 ((CHAR16 *)DestPath)[StrLen (DestPath)-1] = CHAR_NULL;
501 }
502
503 StrCatS (DestPath, PathSize/sizeof (CHAR16), CleanFilePathStr);
504 if ((CleanFilePathStr[StrLen (CleanFilePathStr)-1] != L'\\') && (Node->FileName[0] != L'\\')) {
505 StrCatS (DestPath, PathSize/sizeof (CHAR16), L"\\");
506 } else if ((CleanFilePathStr[StrLen (CleanFilePathStr)-1] == L'\\') && (Node->FileName[0] == L'\\')) {
507 ((CHAR16 *)DestPath)[StrLen (DestPath)-1] = CHAR_NULL;
508 }
509
510 StrCatS (DestPath, PathSize/sizeof (CHAR16), Node->FileName);
511 } else {
512 StrCpyS (DestPath, PathSize/sizeof (CHAR16), CleanFilePathStr);
513 if ((CleanFilePathStr[StrLen (CleanFilePathStr)-1] != L'\\') && (Node->FileName[0] != L'\\')) {
514 StrCatS (DestPath, PathSize/sizeof (CHAR16), L"\\");
515 } else if ((CleanFilePathStr[StrLen (CleanFilePathStr)-1] == L'\\') && (Node->FileName[0] == L'\\')) {
516 ((CHAR16 *)CleanFilePathStr)[StrLen (CleanFilePathStr)-1] = CHAR_NULL;
517 }
518
519 StrCatS (DestPath, PathSize/sizeof (CHAR16), Node->FileName);
520 }
521 }
522
523 //
524 // Make sure the path exists
525 //
526 if (EFI_ERROR (VerifyIntermediateDirectories (DestPath))) {
527 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_WNF), gShellLevel2HiiHandle, L"cp", DestPath);
528 ShellStatus = SHELL_DEVICE_ERROR;
529 break;
530 }
531
532 if ( !EFI_ERROR (ShellIsDirectory (Node->FullName))
533 && !EFI_ERROR (ShellIsDirectory (DestPath))
534 && (StrniCmp (Node->FullName, DestPath, StrLen (DestPath)) == 0)
535 )
536 {
537 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_SD_PARENT), gShellLevel2HiiHandle, L"cp");
538 ShellStatus = SHELL_INVALID_PARAMETER;
539 break;
540 }
541
542 if (StringNoCaseCompare (&Node->FullName, &DestPath) == 0) {
543 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle, L"cp");
544 ShellStatus = SHELL_INVALID_PARAMETER;
545 break;
546 }
547
548 if ( (StrniCmp (Node->FullName, DestPath, StrLen (Node->FullName)) == 0)
549 && ((DestPath[StrLen (Node->FullName)] == CHAR_NULL) || (DestPath[StrLen (Node->FullName)] == L'\\'))
550 )
551 {
552 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle, L"cp");
553 ShellStatus = SHELL_INVALID_PARAMETER;
554 break;
555 }
556
557 PathCleanUpDirectories (DestPath);
558
559 if (!SilentMode) {
560 ShellPrintEx (-1, -1, HiiOutput, Node->FullName, DestPath);
561 }
562
563 //
564 // copy single file...
565 //
566 ShellStatus = CopySingleFile (Node->FullName, DestPath, &Response, SilentMode, L"cp");
567 if (ShellStatus != SHELL_SUCCESS) {
568 break;
569 }
570 }
571
572 if ((ShellStatus == SHELL_SUCCESS) && (Resp == NULL)) {
573 ShellPrintEx (-1, -1, L"%s", HiiResultOk);
574 }
575
576 SHELL_FREE_NON_NULL (DestPath);
577 SHELL_FREE_NON_NULL (HiiOutput);
578 SHELL_FREE_NON_NULL (HiiResultOk);
579 SHELL_FREE_NON_NULL (CleanFilePathStr);
580 if (Resp == NULL) {
581 SHELL_FREE_NON_NULL (Response);
582 }
583
584 return (ShellStatus);
585}
586
601 IN EFI_SHELL_FILE_INFO *FileList,
602 IN CONST CHAR16 *DestDir,
603 IN BOOLEAN SilentMode,
604 IN BOOLEAN RecursiveMode
605 )
606{
607 SHELL_STATUS ShellStatus;
610 CHAR16 *FullName;
611
612 List = NULL;
613 FullName = NULL;
614 FileInfo = NULL;
615
616 ShellOpenFileMetaArg ((CHAR16 *)DestDir, EFI_FILE_MODE_READ, &List);
617 if ((List != NULL) && (List->Link.ForwardLink != List->Link.BackLink)) {
618 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, L"cp", DestDir);
619 ShellStatus = SHELL_INVALID_PARAMETER;
620 ShellCloseFileMetaArg (&List);
621 } else if (List != NULL) {
622 ASSERT (((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink) != NULL);
623 ASSERT (((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName != NULL);
624 FileInfo = gEfiShellProtocol->GetFileInfo (((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->Handle);
625 ASSERT (FileInfo != NULL);
626 StrnCatGrow (&FullName, NULL, ((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName, 0);
627 ShellCloseFileMetaArg (&List);
628 if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) == 0) {
629 ShellStatus = ValidateAndCopyFiles (FileList, FullName, SilentMode, RecursiveMode, NULL);
630 } else {
631 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_ERROR), gShellLevel2HiiHandle, L"cp");
632 ShellStatus = SHELL_ACCESS_DENIED;
633 }
634 } else {
635 ShellCloseFileMetaArg (&List);
636 ShellStatus = ValidateAndCopyFiles (FileList, DestDir, SilentMode, RecursiveMode, NULL);
637 }
638
639 SHELL_FREE_NON_NULL (FileInfo);
640 SHELL_FREE_NON_NULL (FullName);
641 return (ShellStatus);
642}
643
644STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
645 { L"-r", TypeFlag },
646 { L"-q", TypeFlag },
647 { NULL, TypeMax }
648};
649
657EFIAPI
659 IN EFI_HANDLE ImageHandle,
660 IN EFI_SYSTEM_TABLE *SystemTable
661 )
662{
663 EFI_STATUS Status;
664 LIST_ENTRY *Package;
665 CHAR16 *ProblemParam;
666 SHELL_STATUS ShellStatus;
667 UINTN ParamCount;
668 UINTN LoopCounter;
669 EFI_SHELL_FILE_INFO *FileList;
670 BOOLEAN SilentMode;
671 BOOLEAN RecursiveMode;
672 CONST CHAR16 *Cwd;
673 CHAR16 *FullCwd;
674
675 ProblemParam = NULL;
676 ShellStatus = SHELL_SUCCESS;
677 ParamCount = 0;
678 FileList = NULL;
679
680 //
681 // initialize the shell lib (we must be in non-auto-init...)
682 //
683 Status = ShellInitialize ();
684 ASSERT_EFI_ERROR (Status);
685
686 Status = CommandInit ();
687 ASSERT_EFI_ERROR (Status);
688
689 //
690 // parse the command line
691 //
692 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
693 if (EFI_ERROR (Status)) {
694 if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
695 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"cp", ProblemParam);
696 FreePool (ProblemParam);
697 ShellStatus = SHELL_INVALID_PARAMETER;
698 } else {
699 ASSERT (FALSE);
700 }
701 } else {
702 //
703 // check for "-?"
704 //
705 if (ShellCommandLineGetFlag (Package, L"-?")) {
706 ASSERT (FALSE);
707 }
708
709 //
710 // Initialize SilentMode and RecursiveMode
711 //
712 if (gEfiShellProtocol->BatchIsActive ()) {
713 SilentMode = TRUE;
714 } else {
715 SilentMode = ShellCommandLineGetFlag (Package, L"-q");
716 }
717
718 RecursiveMode = ShellCommandLineGetFlag (Package, L"-r");
719
720 switch (ParamCount = ShellCommandLineGetCount (Package)) {
721 case 0:
722 case 1:
723 //
724 // we have insufficient parameters
725 //
726 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"cp");
727 ShellStatus = SHELL_INVALID_PARAMETER;
728 break;
729 case 2:
730 //
731 // must have valid CWD for single parameter...
732 //
733 Cwd = ShellGetCurrentDir (NULL);
734 if (Cwd == NULL) {
735 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cp");
736 ShellStatus = SHELL_INVALID_PARAMETER;
737 } else {
738 Status = ShellOpenFileMetaArg ((CHAR16 *)ShellCommandLineGetRawValue (Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
739 if ((FileList == NULL) || IsListEmpty (&FileList->Link) || EFI_ERROR (Status)) {
740 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"cp", ShellCommandLineGetRawValue (Package, 1));
741 ShellStatus = SHELL_NOT_FOUND;
742 } else {
743 FullCwd = AllocateZeroPool (StrSize (Cwd) + sizeof (CHAR16));
744 if (FullCwd == NULL) {
745 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"cp");
746 ShellStatus = SHELL_OUT_OF_RESOURCES;
747 } else {
748 StrCpyS (FullCwd, StrSize (Cwd) / sizeof (CHAR16) + 1, Cwd);
749 ShellStatus = ProcessValidateAndCopyFiles (FileList, FullCwd, SilentMode, RecursiveMode);
750 FreePool (FullCwd);
751 }
752 }
753 }
754
755 break;
756 default:
757 //
758 // Make a big list of all the files...
759 //
760 for (ParamCount--, LoopCounter = 1; LoopCounter < ParamCount && ShellStatus == SHELL_SUCCESS; LoopCounter++) {
762 break;
763 }
764
765 Status = ShellOpenFileMetaArg ((CHAR16 *)ShellCommandLineGetRawValue (Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
766 if (EFI_ERROR (Status) || (FileList == NULL) || IsListEmpty (&FileList->Link)) {
767 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"cp", ShellCommandLineGetRawValue (Package, LoopCounter));
768 ShellStatus = SHELL_NOT_FOUND;
769 }
770 }
771
772 if (ShellStatus != SHELL_SUCCESS) {
773 Status = ShellCloseFileMetaArg (&FileList);
774 } else {
775 //
776 // now copy them all...
777 //
778 if ((FileList != NULL) && !IsListEmpty (&FileList->Link)) {
779 ShellStatus = ProcessValidateAndCopyFiles (FileList, PathCleanUpDirectories ((CHAR16 *)ShellCommandLineGetRawValue (Package, ParamCount)), SilentMode, RecursiveMode);
780 Status = ShellCloseFileMetaArg (&FileList);
781 if (EFI_ERROR (Status) && (ShellStatus == SHELL_SUCCESS)) {
782 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, L"cp", ShellCommandLineGetRawValue (Package, ParamCount), ShellStatus|MAX_BIT);
783 ShellStatus = SHELL_ACCESS_DENIED;
784 }
785 }
786 }
787
788 break;
789 } // switch on parameter count
790
791 if (FileList != NULL) {
792 ShellCloseFileMetaArg (&FileList);
793 }
794
795 //
796 // free the command line package
797 //
799 }
800
802 return (SHELL_ABORTED);
803 }
804
805 return (ShellStatus);
806}
#define MAX_BIT
UINT64 UINTN
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
RETURN_STATUS EFIAPI StrCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:226
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
INTN EFIAPI StrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
Definition: String.c:109
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
RETURN_STATUS EFIAPI StrCatS(IN OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source)
Definition: SafeString.c:405
CHAR16 *EFIAPI PathCleanUpDirectories(IN CHAR16 *Path)
Definition: FilePaths.c:68
BOOLEAN EFIAPI PathRemoveLastItem(IN OUT CHAR16 *Path)
Definition: FilePaths.c:22
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
CHAR16 *EFIAPI StrStr(IN CONST CHAR16 *String, IN CONST CHAR16 *SearchString)
Definition: String.c:224
SHELL_STATUS ValidateAndCopyFiles(IN CONST EFI_SHELL_FILE_INFO *FileList, IN CONST CHAR16 *DestDir, IN BOOLEAN SilentMode, IN BOOLEAN RecursiveMode, IN VOID **Resp)
Definition: Cp.c:301
SHELL_STATUS EFIAPI ShellCommandRunCp(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: Cp.c:658
SHELL_STATUS ProcessValidateAndCopyFiles(IN EFI_SHELL_FILE_INFO *FileList, IN CONST CHAR16 *DestDir, IN BOOLEAN SilentMode, IN BOOLEAN RecursiveMode)
Definition: Cp.c:600
SHELL_STATUS CopySingleFile(IN CONST CHAR16 *Source, IN CONST CHAR16 *Dest, OUT VOID **Resp, IN BOOLEAN SilentMode, IN CONST CHAR16 *CmdName)
Definition: Cp.c:54
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STRING EFIAPI HiiGetString(IN EFI_HII_HANDLE HiiHandle, IN EFI_STRING_ID StringId, IN CONST CHAR8 *Language OPTIONAL)
Definition: HiiString.c:211
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
SHELL_STATUS
Definition: Shell.h:21
@ SHELL_OUT_OF_RESOURCES
Definition: Shell.h:73
@ SHELL_ACCESS_DENIED
Definition: Shell.h:106
@ SHELL_ABORTED
Definition: Shell.h:128
@ SHELL_SUCCESS
Definition: Shell.h:25
@ SHELL_NOT_FOUND
Definition: Shell.h:101
@ SHELL_VOLUME_FULL
Definition: Shell.h:84
@ SHELL_DEVICE_ERROR
Definition: Shell.h:63
@ SHELL_INVALID_PARAMETER
Definition: Shell.h:35
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
EFI_FILE_INFO * FileInfo(IN EFI_FILE_HANDLE FHand)
EFI_STATUS EFIAPI CommandInit(VOID)
EFI_FILE_PROTOCOL *EFIAPI ConvertShellHandleToEfiFileProtocol(IN CONST SHELL_FILE_HANDLE Handle)
EFI_STATUS EFIAPI ShellGetFileSize(IN SHELL_FILE_HANDLE FileHandle, OUT UINT64 *Size)
CONST CHAR16 *EFIAPI ShellGetCurrentDir(IN CHAR16 *CONST DeviceName OPTIONAL)
BOOLEAN EFIAPI ShellGetExecutionBreakFlag(VOID)
EFI_STATUS EFIAPI ShellDeleteFileByName(IN CONST CHAR16 *FileName)
EFI_STATUS EFIAPI ShellPromptForResponseHii(IN SHELL_PROMPT_REQUEST_TYPE Type, IN CONST EFI_STRING_ID HiiFormatStringId, IN CONST EFI_HII_HANDLE HiiFormatHandle, IN OUT VOID **Response)
EFI_STATUS EFIAPI ShellCreateDirectory(IN CONST CHAR16 *DirectoryName, OUT SHELL_FILE_HANDLE *FileHandle)
Definition: UefiShellLib.c:857
EFI_STATUS EFIAPI ShellCloseFileMetaArg(IN OUT EFI_SHELL_FILE_INFO **ListHead)
#define ShellCommandLineParse(CheckList, CheckPackage, ProblemParam, AutoPageBreak)
Make it easy to upgrade from older versions of the shell library.
Definition: ShellLib.h:755
EFI_STATUS EFIAPI ShellPrintHiiEx(IN INT32 Col OPTIONAL, IN INT32 Row OPTIONAL, IN CONST CHAR8 *Language OPTIONAL, IN CONST EFI_STRING_ID HiiFormatStringId, IN CONST EFI_HII_HANDLE HiiFormatHandle,...)
BOOLEAN EFIAPI ShellCommandLineGetFlag(IN CONST LIST_ENTRY *CONST CheckPackage, IN CONST CHAR16 *CONST KeyString)
@ TypeFlag
A flag that is present or not present only (IE "-a").
Definition: ShellLib.h:699
EFI_STATUS EFIAPI ShellOpenFileByName(IN CONST CHAR16 *FileName, OUT SHELL_FILE_HANDLE *FileHandle, IN UINT64 OpenMode, IN UINT64 Attributes)
Definition: UefiShellLib.c:720
CHAR16 *EFIAPI StrnCatGrow(IN OUT CHAR16 **Destination, IN OUT UINTN *CurrentSize, IN CONST CHAR16 *Source, IN UINTN Count)
SHELL_PROMPT_RESPONSE
Definition: ShellLib.h:1198
EFI_STATUS EFIAPI ShellFileExists(IN CONST CHAR16 *Name)
EFI_STATUS EFIAPI ShellOpenFileMetaArg(IN CHAR16 *Arg, IN UINT64 OpenMode, IN OUT EFI_SHELL_FILE_INFO **ListHead)
VOID EFIAPI ShellCommandLineFreeVarList(IN LIST_ENTRY *CheckPackage)
EFI_STATUS EFIAPI ShellInitialize(VOID)
Definition: UefiShellLib.c:532
EFI_STATUS EFIAPI ShellIsDirectory(IN CONST CHAR16 *DirName)
EFI_STATUS EFIAPI ShellPrintEx(IN INT32 Col OPTIONAL, IN INT32 Row OPTIONAL, IN CONST CHAR16 *Format,...)
CONST CHAR16 *EFIAPI ShellCommandLineGetRawValue(IN CONST LIST_ENTRY *CONST CheckPackage, IN UINTN Position)
UINTN EFIAPI ShellCommandLineGetCount(IN CONST LIST_ENTRY *CheckPackage)
EFI_STATUS EFIAPI ShellWriteFile(IN SHELL_FILE_HANDLE FileHandle, IN OUT UINTN *BufferSize, IN VOID *Buffer)
Definition: UefiShellLib.c:947
EFI_STATUS EFIAPI ShellCloseFile(IN SHELL_FILE_HANDLE *FileHandle)
Definition: UefiShellLib.c:969
EFI_STATUS EFIAPI ShellReadFile(IN SHELL_FILE_HANDLE FileHandle, IN OUT UINTN *ReadSize, OUT VOID *Buffer)
Definition: UefiShellLib.c:912
INTN EFIAPI StringNoCaseCompare(IN CONST VOID *Buffer1, IN CONST VOID *Buffer2)
Definition: BaseSortLib.c:92
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
#define STRING_TOKEN(t)
INTN StrniCmp(IN CONST CHAR16 *Source, IN CONST CHAR16 *Target, IN CONST UINTN Count)
EFI_STATUS VerifyIntermediateDirectories(IN CONST CHAR16 *Path)
EFI_STATUS ShellLevel2StripQuotes(IN CONST CHAR16 *OriginalString, OUT CHAR16 **CleanString)
UINT64 Attribute
Definition: FileInfo.h:47
LIST_ENTRY Link
Linked list members.
Definition: Shell.h:153