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