]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c
ShellPkg: Add a typecast to 'BOOLEAN' to avoid build failure in VS2005.
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / Mv.c
1 /** @file
2 Main file for mv shell level 2 function.
3
4 (C) Copyright 2013-2014, Hewlett-Packard Development Company, L.P.
5 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "UefiShellLevel2CommandsLib.h"
17
18 /**
19 function to determine if a move is between file systems.
20
21 @param FullName [in] The name of the file to move.
22 @param Cwd [in] The current working directory
23 @param DestPath [in] The target location to move to
24
25 @retval TRUE The move is across file system.
26 @retval FALSE The move is within a file system.
27 **/
28 STATIC
29 BOOLEAN
30 EFIAPI
31 IsBetweenFileSystem(
32 IN CONST CHAR16 *FullName,
33 IN CONST CHAR16 *Cwd,
34 IN CONST CHAR16 *DestPath
35 )
36 {
37 CHAR16 *Test;
38 CHAR16 *Test1;
39 UINTN Result;
40
41 Test = StrStr(FullName, L":");
42 if (Test == NULL && Cwd != NULL) {
43 Test = StrStr(Cwd, L":");
44 }
45 Test1 = StrStr(DestPath, L":");
46 if (Test1 == NULL && Cwd != NULL) {
47 Test1 = StrStr(Cwd, L":");
48 }
49 if (Test1 != NULL && Test != NULL) {
50 *Test = CHAR_NULL;
51 *Test1 = CHAR_NULL;
52 Result = StringNoCaseCompare(&FullName, &DestPath);
53 *Test = L':';
54 *Test1 = L':';
55 if (Result != 0) {
56 return (TRUE);
57 }
58 }
59 return (FALSE);
60 }
61
62 /**
63 Function to validate that moving a specific file (FileName) to a specific
64 location (DestPath) is valid.
65
66 This function will verify that the destination is not a subdirectory of
67 FullName, that the Current working Directory is not being moved, and that
68 the directory is not read only.
69
70 if the move is invalid this function will report the error to StdOut.
71
72 @param FullName [in] The name of the file to move.
73 @param Cwd [in] The current working directory
74 @param DestPath [in] The target location to move to
75 @param Attribute[in] The Attribute of the file
76 @param DestAttr [in] The Attribute of the destination
77 @param FileStatus[in] The Status of the file when opened
78
79 @retval TRUE The move is valid
80 @retval FALSE The move is not
81 **/
82 STATIC
83 BOOLEAN
84 EFIAPI
85 IsValidMove(
86 IN CONST CHAR16 *SourcePath,
87 IN CONST CHAR16 *Cwd,
88 IN CONST CHAR16 *DestPath,
89 IN CONST UINT64 Attribute,
90 IN CONST UINT64 DestAttr,
91 IN CONST EFI_STATUS FileStatus
92 )
93 {
94 CHAR16 *DestPathCopy;
95 CHAR16 *DestPathWalker;
96
97 if (Cwd != NULL && StrCmp(SourcePath, Cwd) == 0) {
98 //
99 // Invalid move
100 //
101 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_CWD), gShellLevel2HiiHandle);
102 return (FALSE);
103 }
104
105 //
106 // invalid to move read only or move to a read only destination
107 //
108 if (((Attribute & EFI_FILE_READ_ONLY) != 0)
109 || (FileStatus == EFI_WRITE_PROTECTED)
110 || ((DestAttr & EFI_FILE_READ_ONLY) != 0)
111 ) {
112 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_RO), gShellLevel2HiiHandle, SourcePath);
113 return (FALSE);
114 }
115
116 DestPathCopy = AllocateCopyPool(StrSize(DestPath), DestPath);
117 if (DestPathCopy == NULL) {
118 return (FALSE);
119 }
120
121 for (DestPathWalker = DestPathCopy; *DestPathWalker == L'\\'; DestPathWalker++) ;
122
123 while(DestPathWalker != NULL && DestPathWalker[StrLen(DestPathWalker)-1] == L'\\') {
124 DestPathWalker[StrLen(DestPathWalker)-1] = CHAR_NULL;
125 }
126
127 ASSERT(DestPathWalker != NULL);
128 ASSERT(SourcePath != NULL);
129
130 //
131 // If they're the same, or if source is "above" dest on file path tree
132 //
133 if ( StrCmp(DestPathWalker, SourcePath) == 0
134 || StrStr(DestPathWalker, SourcePath) == DestPathWalker
135 ) {
136 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_SUB), gShellLevel2HiiHandle);
137 FreePool(DestPathCopy);
138 return (FALSE);
139 }
140 FreePool(DestPathCopy);
141
142 return (TRUE);
143 }
144
145 /**
146 Function to take a destination path that might contain wildcards and verify
147 that there is only a single possible target (IE we cant have wildcards that
148 have 2 possible destination).
149
150 if the result is sucessful the caller must free *DestPathPointer.
151
152 @param[in] DestParameter The original path to the destination.
153 @param[in, out] DestPathPointer A pointer to the callee allocated final path.
154 @param[in] Cwd A pointer to the current working directory.
155
156 @retval SHELL_INVALID_PARAMETER The DestParameter could not be resolved to a location.
157 @retval SHELL_INVALID_PARAMETER The DestParameter could be resolved to more than 1 location.
158 @retval SHELL_INVALID_PARAMETER Cwd is required and is NULL.
159 @retval SHELL_SUCCESS The operation was sucessful.
160 **/
161 STATIC
162 SHELL_STATUS
163 EFIAPI
164 GetDestinationLocation(
165 IN CONST CHAR16 *DestParameter,
166 IN OUT CHAR16 **DestPathPointer,
167 IN CONST CHAR16 *Cwd,
168 IN CONST BOOLEAN SingleSource,
169 IN OUT UINT64 *DestAttr
170 )
171 {
172 EFI_SHELL_FILE_INFO *DestList;
173 EFI_SHELL_FILE_INFO *Node;
174 CHAR16 *DestPath;
175 UINTN NewSize;
176 UINTN CurrentSize;
177
178 DestList = NULL;
179 DestPath = NULL;
180
181 ASSERT(DestAttr != NULL);
182
183 if (StrStr(DestParameter, L"\\") == DestParameter) {
184 if (Cwd == NULL) {
185 return SHELL_INVALID_PARAMETER;
186 }
187 DestPath = AllocateZeroPool(StrSize(Cwd));
188 if (DestPath == NULL) {
189 return (SHELL_OUT_OF_RESOURCES);
190 }
191 StrCpy(DestPath, Cwd);
192 while (PathRemoveLastItem(DestPath)) ;
193
194 //
195 // Append DestParameter beyond '\' which may be present
196 //
197 CurrentSize = StrSize(DestPath);
198 StrnCatGrow(&DestPath, &CurrentSize, &DestParameter[1], 0);
199
200 *DestPathPointer = DestPath;
201 return (SHELL_SUCCESS);
202 }
203 //
204 // get the destination path
205 //
206 ShellOpenFileMetaArg((CHAR16*)DestParameter, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE, &DestList);
207 if (DestList == NULL || IsListEmpty(&DestList->Link)) {
208 //
209 // Not existing... must be renaming
210 //
211 if (StrStr(DestParameter, L":") == NULL) {
212 if (Cwd == NULL) {
213 ShellCloseFileMetaArg(&DestList);
214 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
215 return (SHELL_INVALID_PARAMETER);
216 }
217 NewSize = StrSize(Cwd);
218 NewSize += StrSize(DestParameter);
219 DestPath = AllocateZeroPool(NewSize);
220 if (DestPath == NULL) {
221 ShellCloseFileMetaArg(&DestList);
222 return (SHELL_OUT_OF_RESOURCES);
223 }
224 StrCpy(DestPath, Cwd);
225 if (DestPath[StrLen(DestPath)-1] != L'\\' && DestParameter[0] != L'\\') {
226 StrCat(DestPath, L"\\");
227 } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestParameter[0] == L'\\') {
228 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
229 }
230 StrCat(DestPath, DestParameter);
231 } else {
232 ASSERT(DestPath == NULL);
233 DestPath = StrnCatGrow(&DestPath, NULL, DestParameter, 0);
234 if (DestPath == NULL) {
235 ShellCloseFileMetaArg(&DestList);
236 return (SHELL_OUT_OF_RESOURCES);
237 }
238 }
239 } else {
240 Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&DestList->Link);
241 *DestAttr = Node->Info->Attribute;
242 //
243 // Make sure there is only 1 node in the list.
244 //
245 if (!IsNodeAtEnd(&DestList->Link, &Node->Link)) {
246 ShellCloseFileMetaArg(&DestList);
247 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, DestParameter);
248 return (SHELL_INVALID_PARAMETER);
249 }
250
251 //
252 // If we are a directory or a single file, then one node is fine.
253 //
254 if (ShellIsDirectory(Node->FullName)==EFI_SUCCESS || SingleSource) {
255 DestPath = AllocateZeroPool(StrSize(Node->FullName)+sizeof(CHAR16));
256 if (DestPath == NULL) {
257 ShellCloseFileMetaArg(&DestList);
258 return (SHELL_OUT_OF_RESOURCES);
259 }
260 StrCpy(DestPath, Node->FullName);
261 StrCat(DestPath, L"\\");
262 } else {
263 //
264 // cant move multiple files onto a single file.
265 //
266 ShellCloseFileMetaArg(&DestList);
267 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_ERROR), gShellLevel2HiiHandle, DestParameter);
268 return (SHELL_INVALID_PARAMETER);
269 }
270 }
271
272 *DestPathPointer = DestPath;
273 ShellCloseFileMetaArg(&DestList);
274
275 return (SHELL_SUCCESS);
276 }
277
278 EFI_STATUS
279 EFIAPI
280 MoveBetweenFileSystems(
281 IN EFI_SHELL_FILE_INFO *Node,
282 IN CONST CHAR16 *DestPath,
283 OUT VOID **Resp
284 )
285 {
286 EFI_STATUS Status;
287
288 //
289 // First we copy the file
290 //
291 Status = CopySingleFile(Node->FullName, DestPath, Resp, TRUE);
292
293 //
294 // Check our result
295 //
296 if (!EFI_ERROR(Status)) {
297 //
298 // The copy was successful. delete the source file.
299 //
300 CascadeDelete(Node, TRUE);
301 Node->Handle = NULL;
302 }
303
304 return (Status);
305 }
306
307 EFI_STATUS
308 EFIAPI
309 CreateFullDestPath(
310 IN CONST CHAR16 **DestPath,
311 OUT CHAR16 **FullDestPath,
312 IN CONST CHAR16 *FileName
313 )
314 {
315 UINTN Size;
316 if (FullDestPath == NULL || FileName == NULL || DestPath == NULL || *DestPath == NULL){
317 return (EFI_INVALID_PARAMETER);
318 }
319
320 Size = StrSize(*DestPath) + StrSize(FileName);
321
322 *FullDestPath = AllocateZeroPool(Size);
323 if (*FullDestPath == NULL){
324 return (EFI_OUT_OF_RESOURCES);
325 }
326
327 StrnCpy(*FullDestPath, *DestPath, Size / sizeof(CHAR16) - 1);
328 if ((*FullDestPath)[StrLen(*FullDestPath)-1] != L'\\' && FileName[0] != L'\\') {
329 StrnCat(*FullDestPath, L"\\",Size / sizeof(CHAR16) - 1 - StrLen(*FullDestPath));
330 }
331 StrnCat(*FullDestPath, FileName, Size / sizeof(CHAR16) - 1 - StrLen(*FullDestPath));
332
333 return (EFI_SUCCESS);
334 }
335
336 EFI_STATUS
337 EFIAPI
338 MoveWithinFileSystems(
339 IN EFI_SHELL_FILE_INFO *Node,
340 IN CHAR16 *DestPath,
341 OUT VOID **Resp
342 )
343 {
344 EFI_FILE_INFO *NewFileInfo;
345 CHAR16 *TempLocation;
346 UINTN NewSize;
347 UINTN Length;
348 EFI_STATUS Status;
349
350 //
351 // Chop off map info from DestPath
352 //
353 if ((TempLocation = StrStr(DestPath, L":")) != NULL) {
354 CopyMem(DestPath, TempLocation+1, StrSize(TempLocation+1));
355 }
356
357 //
358 // construct the new file info block
359 //
360 NewSize = StrSize(DestPath);
361 NewSize += StrSize(Node->FileName) + SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16);
362 NewFileInfo = AllocateZeroPool(NewSize);
363 if (NewFileInfo == NULL) {
364 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellLevel2HiiHandle);
365 Status = EFI_OUT_OF_RESOURCES;
366 } else {
367 CopyMem(NewFileInfo, Node->Info, SIZE_OF_EFI_FILE_INFO);
368 if (DestPath[0] != L'\\') {
369 StrCpy(NewFileInfo->FileName, L"\\");
370 StrCat(NewFileInfo->FileName, DestPath);
371 } else {
372 StrCpy(NewFileInfo->FileName, DestPath);
373 }
374 Length = StrLen(NewFileInfo->FileName);
375 if (Length > 0) {
376 Length--;
377 }
378 if (NewFileInfo->FileName[Length] == L'\\') {
379 if (Node->FileName[0] == L'\\') {
380 //
381 // Don't allow for double slashes. Eliminate one of them.
382 //
383 NewFileInfo->FileName[Length] = CHAR_NULL;
384 }
385 StrCat(NewFileInfo->FileName, Node->FileName);
386 }
387 NewFileInfo->Size = SIZE_OF_EFI_FILE_INFO + StrSize(NewFileInfo->FileName);
388
389 //
390 // Perform the move operation
391 //
392 Status = ShellSetFileInfo(Node->Handle, NewFileInfo);
393
394 //
395 // Free the info object we used...
396 //
397 FreePool(NewFileInfo);
398 }
399
400 return (Status);
401 }
402 /**
403 function to take a list of files to move and a destination location and do
404 the verification and moving of those files to that location. This function
405 will report any errors to the user and continue to move the rest of the files.
406
407 @param[in] FileList A LIST_ENTRY* based list of files to move
408 @param[out] Resp pointer to response from question. Pass back on looped calling
409 @param[in] DestParameter the originally specified destination location
410
411 @retval SHELL_SUCCESS the files were all moved.
412 @retval SHELL_INVALID_PARAMETER a parameter was invalid
413 @retval SHELL_SECURITY_VIOLATION a security violation ocurred
414 @retval SHELL_WRITE_PROTECTED the destination was write protected
415 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
416 **/
417 STATIC
418 SHELL_STATUS
419 EFIAPI
420 ValidateAndMoveFiles(
421 IN EFI_SHELL_FILE_INFO *FileList,
422 OUT VOID **Resp,
423 IN CONST CHAR16 *DestParameter
424 )
425 {
426 EFI_STATUS Status;
427 CHAR16 *HiiOutput;
428 CHAR16 *HiiResultOk;
429 CHAR16 *DestPath;
430 CHAR16 *FullDestPath;
431 CONST CHAR16 *Cwd;
432 SHELL_STATUS ShellStatus;
433 EFI_SHELL_FILE_INFO *Node;
434 VOID *Response;
435 UINT64 Attr;
436 CHAR16 *CleanFilePathStr;
437
438 ASSERT(FileList != NULL);
439 ASSERT(DestParameter != NULL);
440
441 DestPath = NULL;
442 FullDestPath = NULL;
443 Cwd = ShellGetCurrentDir(NULL);
444 Response = *Resp;
445 Attr = 0;
446 CleanFilePathStr = NULL;
447
448 Status = ShellLevel2StripQuotes (DestParameter, &CleanFilePathStr);
449 if (EFI_ERROR (Status)) {
450 if (Status == EFI_OUT_OF_RESOURCES) {
451 return SHELL_OUT_OF_RESOURCES;
452 } else {
453 return SHELL_INVALID_PARAMETER;
454 }
455 }
456
457 ASSERT (CleanFilePathStr != NULL);
458
459 //
460 // Get and validate the destination location
461 //
462 ShellStatus = GetDestinationLocation(CleanFilePathStr, &DestPath, Cwd, (BOOLEAN)(FileList->Link.ForwardLink == FileList->Link.BackLink), &Attr);
463 FreePool (CleanFilePathStr);
464
465 if (ShellStatus != SHELL_SUCCESS) {
466 return (ShellStatus);
467 }
468 DestPath = PathCleanUpDirectories(DestPath);
469 if (DestPath == NULL) {
470 return (SHELL_OUT_OF_RESOURCES);
471 }
472
473 HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MV_OUTPUT), NULL);
474 HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL);
475 if (HiiOutput == NULL || HiiResultOk == NULL) {
476 SHELL_FREE_NON_NULL(DestPath);
477 SHELL_FREE_NON_NULL(HiiOutput);
478 SHELL_FREE_NON_NULL(HiiResultOk);
479 return (SHELL_OUT_OF_RESOURCES);
480 }
481
482 //
483 // Go through the list of files and directories to move...
484 //
485 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
486 ; !IsNull(&FileList->Link, &Node->Link)
487 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
488 ){
489 if (ShellGetExecutionBreakFlag()) {
490 break;
491 }
492
493 //
494 // These should never be NULL
495 //
496 ASSERT(Node->FileName != NULL);
497 ASSERT(Node->FullName != NULL);
498 ASSERT(Node->Info != NULL);
499
500 //
501 // skip the directory traversing stuff...
502 //
503 if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
504 continue;
505 }
506
507 SHELL_FREE_NON_NULL(FullDestPath);
508 FullDestPath = NULL;
509 if (ShellIsDirectory(DestPath)==EFI_SUCCESS) {
510 CreateFullDestPath((CONST CHAR16 **)&DestPath, &FullDestPath, Node->FileName);
511 }
512
513 //
514 // Validate that the move is valid
515 //
516 if (!IsValidMove(Node->FullName, Cwd, FullDestPath?FullDestPath:DestPath, Node->Info->Attribute, Attr, Node->Status)) {
517 ShellStatus = SHELL_INVALID_PARAMETER;
518 continue;
519 }
520
521 ShellPrintEx(-1, -1, HiiOutput, Node->FullName, FullDestPath?FullDestPath:DestPath);
522
523 //
524 // See if destination exists
525 //
526 if (!EFI_ERROR(ShellFileExists(FullDestPath?FullDestPath:DestPath))) {
527 if (Response == NULL) {
528 ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response);
529 }
530 switch (*(SHELL_PROMPT_RESPONSE*)Response) {
531 case ShellPromptResponseNo:
532 FreePool(Response);
533 Response = NULL;
534 continue;
535 case ShellPromptResponseCancel:
536 *Resp = Response;
537 //
538 // indicate to stop everything
539 //
540 return (SHELL_ABORTED);
541 case ShellPromptResponseAll:
542 *Resp = Response;
543 break;
544 case ShellPromptResponseYes:
545 FreePool(Response);
546 Response = NULL;
547 break;
548 default:
549 FreePool(Response);
550 return SHELL_ABORTED;
551 }
552 Status = ShellDeleteFileByName(FullDestPath?FullDestPath:DestPath);
553 }
554
555 if (IsBetweenFileSystem(Node->FullName, Cwd, DestPath)) {
556 while (FullDestPath == NULL && DestPath != NULL && DestPath[0] != CHAR_NULL && DestPath[StrLen(DestPath) - 1] == L'\\') {
557 DestPath[StrLen(DestPath) - 1] = CHAR_NULL;
558 }
559 Status = MoveBetweenFileSystems(Node, FullDestPath?FullDestPath:DestPath, &Response);
560 } else {
561 Status = MoveWithinFileSystems(Node, DestPath, &Response);
562 }
563
564 //
565 // Check our result
566 //
567 if (EFI_ERROR(Status)) {
568 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, Status);
569 ShellStatus = SHELL_INVALID_PARAMETER;
570 if (Status == EFI_SECURITY_VIOLATION) {
571 ShellStatus = SHELL_SECURITY_VIOLATION;
572 } else if (Status == EFI_WRITE_PROTECTED) {
573 ShellStatus = SHELL_WRITE_PROTECTED;
574 } else if (Status == EFI_OUT_OF_RESOURCES) {
575 ShellStatus = SHELL_OUT_OF_RESOURCES;
576 } else if (Status == EFI_DEVICE_ERROR) {
577 ShellStatus = SHELL_DEVICE_ERROR;
578 } else if (Status == EFI_ACCESS_DENIED) {
579 ShellStatus = SHELL_ACCESS_DENIED;
580 }
581 } else {
582 ShellPrintEx(-1, -1, L"%s", HiiResultOk);
583 }
584
585 } // main for loop
586
587 SHELL_FREE_NON_NULL(FullDestPath);
588 SHELL_FREE_NON_NULL(DestPath);
589 SHELL_FREE_NON_NULL(HiiOutput);
590 SHELL_FREE_NON_NULL(HiiResultOk);
591 return (ShellStatus);
592 }
593
594 /**
595 Function for 'mv' command.
596
597 @param[in] ImageHandle Handle to the Image (NULL if Internal).
598 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
599 **/
600 SHELL_STATUS
601 EFIAPI
602 ShellCommandRunMv (
603 IN EFI_HANDLE ImageHandle,
604 IN EFI_SYSTEM_TABLE *SystemTable
605 )
606 {
607 EFI_STATUS Status;
608 LIST_ENTRY *Package;
609 CHAR16 *ProblemParam;
610 SHELL_STATUS ShellStatus;
611 UINTN ParamCount;
612 UINTN LoopCounter;
613 EFI_SHELL_FILE_INFO *FileList;
614 VOID *Response;
615
616 ProblemParam = NULL;
617 ShellStatus = SHELL_SUCCESS;
618 ParamCount = 0;
619 FileList = NULL;
620 Response = NULL;
621
622 //
623 // initialize the shell lib (we must be in non-auto-init...)
624 //
625 Status = ShellInitialize();
626 ASSERT_EFI_ERROR(Status);
627
628 //
629 // parse the command line
630 //
631 Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
632 if (EFI_ERROR(Status)) {
633 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
634 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);
635 FreePool(ProblemParam);
636 ShellStatus = SHELL_INVALID_PARAMETER;
637 } else {
638 ASSERT(FALSE);
639 }
640 } else {
641 //
642 // check for "-?"
643 //
644 if (ShellCommandLineGetFlag(Package, L"-?")) {
645 ASSERT(FALSE);
646 }
647
648 switch (ParamCount = ShellCommandLineGetCount(Package)) {
649 case 0:
650 case 1:
651 //
652 // we have insufficient parameters
653 //
654 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);
655 ShellStatus = SHELL_INVALID_PARAMETER;
656 break;
657 case 2:
658 //
659 // must have valid CWD for single parameter...
660 //
661 if (ShellGetCurrentDir(NULL) == NULL){
662 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
663 ShellStatus = SHELL_INVALID_PARAMETER;
664 } else {
665 Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
666 if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {
667 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));
668 ShellStatus = SHELL_NOT_FOUND;
669 } else {
670 //
671 // ValidateAndMoveFiles will report errors to the screen itself
672 //
673 ShellStatus = ValidateAndMoveFiles(FileList, &Response, ShellGetCurrentDir(NULL));
674 }
675 }
676
677 break;
678 default:
679 ///@todo make sure this works with error half way through and continues...
680 for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount ; LoopCounter++) {
681 if (ShellGetExecutionBreakFlag()) {
682 break;
683 }
684 Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
685 if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {
686 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, LoopCounter));
687 ShellStatus = SHELL_NOT_FOUND;
688 } else {
689 //
690 // ValidateAndMoveFiles will report errors to the screen itself
691 // Only change ShellStatus if it's sucessful
692 //
693 if (ShellStatus == SHELL_SUCCESS) {
694 ShellStatus = ValidateAndMoveFiles(FileList, &Response, ShellCommandLineGetRawValue(Package, ParamCount));
695 } else {
696 ValidateAndMoveFiles(FileList, &Response, ShellCommandLineGetRawValue(Package, ParamCount));
697 }
698 }
699 if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
700 Status = ShellCloseFileMetaArg(&FileList);
701 if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
702 ShellStatus = SHELL_ACCESS_DENIED;
703 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1), ShellStatus|MAX_BIT);
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 SHELL_FREE_NON_NULL(Response);
721
722 if (ShellGetExecutionBreakFlag()) {
723 return (SHELL_ABORTED);
724 }
725
726 return (ShellStatus);
727 }