2 Main file for mv shell level 2 function.
4 (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2009 - 2016, 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
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.
16 #include "UefiShellLevel2CommandsLib.h"
19 function to determine if a move is between file systems.
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
25 @retval TRUE The move is across file system.
26 @retval FALSE The move is within a file system.
30 IN CONST CHAR16
*FullName
,
32 IN CONST CHAR16
*DestPath
39 Test
= StrStr(FullName
, L
":");
40 if (Test
== NULL
&& Cwd
!= NULL
) {
41 Test
= StrStr(Cwd
, L
":");
43 Test1
= StrStr(DestPath
, L
":");
44 if (Test1
== NULL
&& Cwd
!= NULL
) {
45 Test1
= StrStr(Cwd
, L
":");
47 if (Test1
!= NULL
&& Test
!= NULL
) {
50 Result
= StringNoCaseCompare(&FullName
, &DestPath
);
61 Function to validate that moving a specific file (FileName) to a specific
62 location (DestPath) is valid.
64 This function will verify that the destination is not a subdirectory of
65 FullName, that the Current working Directory is not being moved, and that
66 the directory is not read only.
68 if the move is invalid this function will report the error to StdOut.
70 @param SourcePath [in] The name of the file to move.
71 @param Cwd [in] The current working directory
72 @param DestPath [in] The target location to move to
73 @param Attribute [in] The Attribute of the file
74 @param DestAttr [in] The Attribute of the destination
75 @param FileStatus [in] The Status of the file when opened
77 @retval TRUE The move is valid
78 @retval FALSE The move is not
82 IN CONST CHAR16
*SourcePath
,
84 IN CONST CHAR16
*DestPath
,
85 IN CONST UINT64 Attribute
,
86 IN CONST UINT64 DestAttr
,
87 IN CONST EFI_STATUS FileStatus
91 CHAR16
*DestPathWalker
;
93 if (Cwd
!= NULL
&& StrCmp(SourcePath
, Cwd
) == 0) {
97 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MV_INV_CWD
), gShellLevel2HiiHandle
);
102 // invalid to move read only or move to a read only destination
104 if (((Attribute
& EFI_FILE_READ_ONLY
) != 0)
105 || (FileStatus
== EFI_WRITE_PROTECTED
)
106 || ((DestAttr
& EFI_FILE_READ_ONLY
) != 0)
108 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MV_INV_RO
), gShellLevel2HiiHandle
, SourcePath
);
112 DestPathCopy
= AllocateCopyPool(StrSize(DestPath
), DestPath
);
113 if (DestPathCopy
== NULL
) {
117 for (DestPathWalker
= DestPathCopy
; *DestPathWalker
== L
'\\'; DestPathWalker
++) ;
119 while(DestPathWalker
!= NULL
&& DestPathWalker
[StrLen(DestPathWalker
)-1] == L
'\\') {
120 DestPathWalker
[StrLen(DestPathWalker
)-1] = CHAR_NULL
;
123 ASSERT(DestPathWalker
!= NULL
);
124 ASSERT(SourcePath
!= NULL
);
127 // If they're the same, or if source is "above" dest on file path tree
129 if ( StringNoCaseCompare (&DestPathWalker
, &SourcePath
) == 0 ||
130 ((StrStr(DestPathWalker
, SourcePath
) == DestPathWalker
) &&
131 (DestPathWalker
[StrLen(SourcePath
)] == '\\')
134 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MV_INV_SUB
), gShellLevel2HiiHandle
);
135 FreePool(DestPathCopy
);
138 FreePool(DestPathCopy
);
144 Function to take a destination path that might contain wildcards and verify
145 that there is only a single possible target (IE we cant have wildcards that
146 have 2 possible destination).
148 if the result is sucessful the caller must free *DestPathPointer.
150 @param[in] DestParameter The original path to the destination.
151 @param[in, out] DestPathPointer A pointer to the callee allocated final path.
152 @param[in] Cwd A pointer to the current working directory.
153 @param[in] SingleSource TRUE to have only one source file.
154 @param[in, out] DestAttr A pointer to the destination information attribute.
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.
162 GetDestinationLocation(
163 IN CONST CHAR16
*DestParameter
,
164 IN OUT CHAR16
**DestPathPointer
,
165 IN CONST CHAR16
*Cwd
,
166 IN CONST BOOLEAN SingleSource
,
167 IN OUT UINT64
*DestAttr
170 EFI_SHELL_FILE_INFO
*DestList
;
171 EFI_SHELL_FILE_INFO
*Node
;
179 ASSERT(DestAttr
!= NULL
);
181 if (StrStr(DestParameter
, L
"\\") == DestParameter
) {
183 return SHELL_INVALID_PARAMETER
;
185 DestPath
= AllocateZeroPool(StrSize(Cwd
));
186 if (DestPath
== NULL
) {
187 return (SHELL_OUT_OF_RESOURCES
);
189 StrCpyS(DestPath
, StrSize(Cwd
) / sizeof(CHAR16
), Cwd
);
190 while (PathRemoveLastItem(DestPath
)) ;
193 // Append DestParameter beyond '\' which may be present
195 CurrentSize
= StrSize(DestPath
);
196 StrnCatGrow(&DestPath
, &CurrentSize
, &DestParameter
[1], 0);
198 *DestPathPointer
= DestPath
;
199 return (SHELL_SUCCESS
);
202 // get the destination path
204 ShellOpenFileMetaArg((CHAR16
*)DestParameter
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
, &DestList
);
205 if (DestList
== NULL
|| IsListEmpty(&DestList
->Link
)) {
207 // Not existing... must be renaming
209 if (StrStr(DestParameter
, L
":") == NULL
) {
211 ShellCloseFileMetaArg(&DestList
);
212 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_CWD
), gShellLevel2HiiHandle
);
213 return (SHELL_INVALID_PARAMETER
);
215 NewSize
= StrSize(Cwd
);
216 NewSize
+= StrSize(DestParameter
);
217 DestPath
= AllocateZeroPool(NewSize
);
218 if (DestPath
== NULL
) {
219 ShellCloseFileMetaArg(&DestList
);
220 return (SHELL_OUT_OF_RESOURCES
);
222 StrCpyS(DestPath
, NewSize
/ sizeof(CHAR16
), Cwd
);
223 if (DestPath
[StrLen(DestPath
)-1] != L
'\\' && DestParameter
[0] != L
'\\') {
224 StrCatS(DestPath
, NewSize
/ sizeof(CHAR16
), L
"\\");
225 } else if (DestPath
[StrLen(DestPath
)-1] == L
'\\' && DestParameter
[0] == L
'\\') {
226 ((CHAR16
*)DestPath
)[StrLen(DestPath
)-1] = CHAR_NULL
;
228 StrCatS(DestPath
, NewSize
/ sizeof(CHAR16
), DestParameter
);
230 ASSERT(DestPath
== NULL
);
231 DestPath
= StrnCatGrow(&DestPath
, NULL
, DestParameter
, 0);
232 if (DestPath
== NULL
) {
233 ShellCloseFileMetaArg(&DestList
);
234 return (SHELL_OUT_OF_RESOURCES
);
238 Node
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&DestList
->Link
);
239 *DestAttr
= Node
->Info
->Attribute
;
241 // Make sure there is only 1 node in the list.
243 if (!IsNodeAtEnd(&DestList
->Link
, &Node
->Link
)) {
244 ShellCloseFileMetaArg(&DestList
);
245 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_MARG_ERROR
), gShellLevel2HiiHandle
, L
"mv", DestParameter
);
246 return (SHELL_INVALID_PARAMETER
);
250 // If we are a directory or a single file, then one node is fine.
252 if (ShellIsDirectory(Node
->FullName
)==EFI_SUCCESS
|| SingleSource
) {
253 DestPath
= AllocateZeroPool(StrSize(Node
->FullName
)+sizeof(CHAR16
));
254 if (DestPath
== NULL
) {
255 ShellCloseFileMetaArg(&DestList
);
256 return (SHELL_OUT_OF_RESOURCES
);
258 StrCpyS(DestPath
, (StrSize(Node
->FullName
)+sizeof(CHAR16
)) / sizeof(CHAR16
), Node
->FullName
);
259 StrCatS(DestPath
, (StrSize(Node
->FullName
)+sizeof(CHAR16
)) / sizeof(CHAR16
), L
"\\");
262 // cant move multiple files onto a single file.
264 ShellCloseFileMetaArg(&DestList
);
265 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_ERROR
), gShellLevel2HiiHandle
, L
"mv", DestParameter
);
266 return (SHELL_INVALID_PARAMETER
);
270 *DestPathPointer
= DestPath
;
271 ShellCloseFileMetaArg(&DestList
);
273 return (SHELL_SUCCESS
);
277 Function to do a move across file systems.
279 @param[in] Node A pointer to the file to be removed.
280 @param[in] DestPath A pointer to the destination file path.
281 @param[out] Resp A pointer to response from question. Pass back on looped calling
283 @retval SHELL_SUCCESS The source file was moved to the destination.
286 MoveBetweenFileSystems(
287 IN EFI_SHELL_FILE_INFO
*Node
,
288 IN CONST CHAR16
*DestPath
,
292 SHELL_STATUS ShellStatus
;
295 // First we copy the file
297 ShellStatus
= CopySingleFile (Node
->FullName
, DestPath
, Resp
, TRUE
, L
"mv");
302 if (ShellStatus
== SHELL_SUCCESS
) {
304 // The copy was successful. delete the source file.
306 CascadeDelete(Node
, TRUE
);
308 } else if (ShellStatus
== SHELL_ABORTED
) {
310 } else if (ShellStatus
== SHELL_ACCESS_DENIED
) {
311 return EFI_ACCESS_DENIED
;
312 } else if (ShellStatus
== SHELL_VOLUME_FULL
) {
313 return EFI_VOLUME_FULL
;
315 return EFI_UNSUPPORTED
;
318 return (EFI_SUCCESS
);
322 Function to take the destination path and target file name to generate the full destination path.
324 @param[in] DestPath A pointer to the destination file path string.
325 @param[out] FullDestPath A pointer to the full destination path string.
326 @param[in] FileName Name string of the targe file.
328 @retval SHELL_SUCCESS the files were all moved.
329 @retval SHELL_INVALID_PARAMETER a parameter was invalid
330 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
334 IN CONST CHAR16
**DestPath
,
335 OUT CHAR16
**FullDestPath
,
336 IN CONST CHAR16
*FileName
340 if (FullDestPath
== NULL
|| FileName
== NULL
|| DestPath
== NULL
|| *DestPath
== NULL
){
341 return (EFI_INVALID_PARAMETER
);
344 Size
= StrSize(*DestPath
) + StrSize(FileName
);
346 *FullDestPath
= AllocateZeroPool(Size
);
347 if (*FullDestPath
== NULL
){
348 return (EFI_OUT_OF_RESOURCES
);
351 StrCpyS(*FullDestPath
, Size
/ sizeof(CHAR16
), *DestPath
);
352 if ((*FullDestPath
)[StrLen(*FullDestPath
)-1] != L
'\\' && FileName
[0] != L
'\\') {
353 StrCatS(*FullDestPath
, Size
/ sizeof(CHAR16
), L
"\\");
355 StrCatS(*FullDestPath
, Size
/ sizeof(CHAR16
), FileName
);
357 return (EFI_SUCCESS
);
361 Function to do a move within a file system.
363 @param[in] Node A pointer to the file to be removed.
364 @param[in] DestPath A pointer to the destination file path.
365 @param[out] Resp A pointer to response from question. Pass back on looped calling.
367 @retval SHELL_SUCCESS The source file was moved to the destination.
368 @retval SHELL_OUT_OF_RESOURCES A memory allocation failed.
371 MoveWithinFileSystems(
372 IN EFI_SHELL_FILE_INFO
*Node
,
377 EFI_FILE_INFO
*NewFileInfo
;
378 CHAR16
*TempLocation
;
384 // Chop off map info from DestPath
386 if ((TempLocation
= StrStr(DestPath
, L
":")) != NULL
) {
387 CopyMem(DestPath
, TempLocation
+1, StrSize(TempLocation
+1));
391 // construct the new file info block
393 NewSize
= StrSize(DestPath
);
394 NewSize
+= StrSize(Node
->FileName
) + SIZE_OF_EFI_FILE_INFO
+ sizeof(CHAR16
);
395 NewFileInfo
= AllocateZeroPool(NewSize
);
396 if (NewFileInfo
== NULL
) {
397 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_MEM
), gShellLevel2HiiHandle
);
398 Status
= EFI_OUT_OF_RESOURCES
;
400 CopyMem(NewFileInfo
, Node
->Info
, SIZE_OF_EFI_FILE_INFO
);
401 if (DestPath
[0] != L
'\\') {
402 StrCpyS(NewFileInfo
->FileName
, (NewSize
- SIZE_OF_EFI_FILE_INFO
) / sizeof(CHAR16
), L
"\\");
403 StrCatS(NewFileInfo
->FileName
, (NewSize
- SIZE_OF_EFI_FILE_INFO
) / sizeof(CHAR16
), DestPath
);
405 StrCpyS(NewFileInfo
->FileName
, (NewSize
- SIZE_OF_EFI_FILE_INFO
) / sizeof(CHAR16
), DestPath
);
407 Length
= StrLen(NewFileInfo
->FileName
);
411 if (NewFileInfo
->FileName
[Length
] == L
'\\') {
412 if (Node
->FileName
[0] == L
'\\') {
414 // Don't allow for double slashes. Eliminate one of them.
416 NewFileInfo
->FileName
[Length
] = CHAR_NULL
;
418 StrCatS(NewFileInfo
->FileName
, (NewSize
- SIZE_OF_EFI_FILE_INFO
) / sizeof(CHAR16
), Node
->FileName
);
420 NewFileInfo
->Size
= SIZE_OF_EFI_FILE_INFO
+ StrSize(NewFileInfo
->FileName
);
423 // Perform the move operation
425 Status
= ShellSetFileInfo(Node
->Handle
, NewFileInfo
);
428 // Free the info object we used...
430 FreePool(NewFileInfo
);
436 function to take a list of files to move and a destination location and do
437 the verification and moving of those files to that location. This function
438 will report any errors to the user and continue to move the rest of the files.
440 @param[in] FileList A LIST_ENTRY* based list of files to move
441 @param[out] Resp pointer to response from question. Pass back on looped calling
442 @param[in] DestParameter the originally specified destination location
444 @retval SHELL_SUCCESS the files were all moved.
445 @retval SHELL_INVALID_PARAMETER a parameter was invalid
446 @retval SHELL_SECURITY_VIOLATION a security violation ocurred
447 @retval SHELL_WRITE_PROTECTED the destination was write protected
448 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
451 ValidateAndMoveFiles(
452 IN EFI_SHELL_FILE_INFO
*FileList
,
454 IN CONST CHAR16
*DestParameter
461 CHAR16
*FullDestPath
;
464 SHELL_STATUS ShellStatus
;
465 EFI_SHELL_FILE_INFO
*Node
;
468 CHAR16
*CleanFilePathStr
;
470 ASSERT(FileList
!= NULL
);
471 ASSERT(DestParameter
!= NULL
);
475 Cwd
= ShellGetCurrentDir(NULL
);
478 CleanFilePathStr
= NULL
;
482 FullCwd
= AllocateZeroPool(StrSize(Cwd
) + sizeof(CHAR16
));
483 if (FullCwd
== NULL
) {
484 return SHELL_OUT_OF_RESOURCES
;
486 StrCpyS(FullCwd
, StrSize(Cwd
)/sizeof(CHAR16
)+1, Cwd
);
487 StrCatS(FullCwd
, StrSize(Cwd
)/sizeof(CHAR16
)+1, L
"\\");
491 Status
= ShellLevel2StripQuotes (DestParameter
, &CleanFilePathStr
);
492 if (EFI_ERROR (Status
)) {
493 SHELL_FREE_NON_NULL(FullCwd
);
494 if (Status
== EFI_OUT_OF_RESOURCES
) {
495 return SHELL_OUT_OF_RESOURCES
;
497 return SHELL_INVALID_PARAMETER
;
501 ASSERT (CleanFilePathStr
!= NULL
);
504 // Get and validate the destination location
506 ShellStatus
= GetDestinationLocation(CleanFilePathStr
, &DestPath
, FullCwd
, (BOOLEAN
)(FileList
->Link
.ForwardLink
== FileList
->Link
.BackLink
), &Attr
);
507 FreePool (CleanFilePathStr
);
509 if (ShellStatus
!= SHELL_SUCCESS
) {
510 SHELL_FREE_NON_NULL (FullCwd
);
511 return (ShellStatus
);
513 DestPath
= PathCleanUpDirectories(DestPath
);
514 if (DestPath
== NULL
) {
516 return (SHELL_OUT_OF_RESOURCES
);
519 HiiOutput
= HiiGetString (gShellLevel2HiiHandle
, STRING_TOKEN (STR_MV_OUTPUT
), NULL
);
520 HiiResultOk
= HiiGetString (gShellLevel2HiiHandle
, STRING_TOKEN (STR_GEN_RES_OK
), NULL
);
521 if (HiiOutput
== NULL
|| HiiResultOk
== NULL
) {
522 SHELL_FREE_NON_NULL(DestPath
);
523 SHELL_FREE_NON_NULL(HiiOutput
);
524 SHELL_FREE_NON_NULL(HiiResultOk
);
525 SHELL_FREE_NON_NULL(FullCwd
);
526 return (SHELL_OUT_OF_RESOURCES
);
530 // Go through the list of files and directories to move...
532 for (Node
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&FileList
->Link
)
533 ; !IsNull(&FileList
->Link
, &Node
->Link
)
534 ; Node
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&FileList
->Link
, &Node
->Link
)
536 if (ShellGetExecutionBreakFlag()) {
541 // These should never be NULL
543 ASSERT(Node
->FileName
!= NULL
);
544 ASSERT(Node
->FullName
!= NULL
);
545 ASSERT(Node
->Info
!= NULL
);
548 // skip the directory traversing stuff...
550 if (StrCmp(Node
->FileName
, L
".") == 0 || StrCmp(Node
->FileName
, L
"..") == 0) {
554 SHELL_FREE_NON_NULL(FullDestPath
);
556 if (ShellIsDirectory(DestPath
)==EFI_SUCCESS
) {
557 CreateFullDestPath((CONST CHAR16
**)&DestPath
, &FullDestPath
, Node
->FileName
);
561 // Validate that the move is valid
563 if (!IsValidMove(Node
->FullName
, FullCwd
, FullDestPath
!=NULL
? FullDestPath
:DestPath
, Node
->Info
->Attribute
, Attr
, Node
->Status
)) {
564 ShellStatus
= SHELL_INVALID_PARAMETER
;
568 ShellPrintEx(-1, -1, HiiOutput
, Node
->FullName
, FullDestPath
!=NULL
? FullDestPath
:DestPath
);
571 // See if destination exists
573 if (!EFI_ERROR(ShellFileExists(FullDestPath
!=NULL
? FullDestPath
:DestPath
))) {
574 if (Response
== NULL
) {
575 ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel
, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR
), gShellLevel2HiiHandle
, &Response
);
577 switch (*(SHELL_PROMPT_RESPONSE
*)Response
) {
578 case ShellPromptResponseNo
:
582 case ShellPromptResponseCancel
:
585 // indicate to stop everything
587 SHELL_FREE_NON_NULL(FullCwd
);
588 return (SHELL_ABORTED
);
589 case ShellPromptResponseAll
:
592 case ShellPromptResponseYes
:
598 SHELL_FREE_NON_NULL(FullCwd
);
599 return SHELL_ABORTED
;
601 Status
= ShellDeleteFileByName(FullDestPath
!=NULL
? FullDestPath
:DestPath
);
604 if (IsBetweenFileSystem(Node
->FullName
, FullCwd
, DestPath
)) {
605 while (FullDestPath
== NULL
&& DestPath
!= NULL
&& DestPath
[0] != CHAR_NULL
&& DestPath
[StrLen(DestPath
) - 1] == L
'\\') {
606 DestPath
[StrLen(DestPath
) - 1] = CHAR_NULL
;
608 Status
= MoveBetweenFileSystems(Node
, FullDestPath
!=NULL
? FullDestPath
:DestPath
, &Response
);
610 Status
= MoveWithinFileSystems(Node
, DestPath
, &Response
);
612 // Display error status
614 if (EFI_ERROR(Status
)) {
615 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_ERR_UK
), gShellLevel2HiiHandle
, L
"mv", Status
);
622 if (EFI_ERROR(Status
)) {
623 ShellStatus
= SHELL_INVALID_PARAMETER
;
624 if (Status
== EFI_SECURITY_VIOLATION
) {
625 ShellStatus
= SHELL_SECURITY_VIOLATION
;
626 } else if (Status
== EFI_WRITE_PROTECTED
) {
627 ShellStatus
= SHELL_WRITE_PROTECTED
;
628 } else if (Status
== EFI_OUT_OF_RESOURCES
) {
629 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
630 } else if (Status
== EFI_DEVICE_ERROR
) {
631 ShellStatus
= SHELL_DEVICE_ERROR
;
632 } else if (Status
== EFI_ACCESS_DENIED
) {
633 ShellStatus
= SHELL_ACCESS_DENIED
;
636 ShellPrintEx(-1, -1, L
"%s", HiiResultOk
);
641 SHELL_FREE_NON_NULL(FullDestPath
);
642 SHELL_FREE_NON_NULL(DestPath
);
643 SHELL_FREE_NON_NULL(HiiOutput
);
644 SHELL_FREE_NON_NULL(HiiResultOk
);
645 SHELL_FREE_NON_NULL(FullCwd
);
646 return (ShellStatus
);
650 Function for 'mv' command.
652 @param[in] ImageHandle Handle to the Image (NULL if Internal).
653 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
658 IN EFI_HANDLE ImageHandle
,
659 IN EFI_SYSTEM_TABLE
*SystemTable
664 CHAR16
*ProblemParam
;
667 SHELL_STATUS ShellStatus
;
670 EFI_SHELL_FILE_INFO
*FileList
;
674 ShellStatus
= SHELL_SUCCESS
;
680 // initialize the shell lib (we must be in non-auto-init...)
682 Status
= ShellInitialize();
683 ASSERT_EFI_ERROR(Status
);
686 // parse the command line
688 Status
= ShellCommandLineParse (EmptyParamList
, &Package
, &ProblemParam
, TRUE
);
689 if (EFI_ERROR(Status
)) {
690 if (Status
== EFI_VOLUME_CORRUPTED
&& ProblemParam
!= NULL
) {
691 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellLevel2HiiHandle
, L
"mv", ProblemParam
);
692 FreePool(ProblemParam
);
693 ShellStatus
= SHELL_INVALID_PARAMETER
;
701 if (ShellCommandLineGetFlag(Package
, L
"-?")) {
705 switch (ParamCount
= ShellCommandLineGetCount(Package
)) {
709 // we have insufficient parameters
711 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellLevel2HiiHandle
, L
"mv");
712 ShellStatus
= SHELL_INVALID_PARAMETER
;
716 // must have valid CWD for single parameter...
718 if (ShellGetCurrentDir(NULL
) == NULL
){
719 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_CWD
), gShellLevel2HiiHandle
, L
"mv");
720 ShellStatus
= SHELL_INVALID_PARAMETER
;
722 Status
= ShellOpenFileMetaArg((CHAR16
*)ShellCommandLineGetRawValue(Package
, 1), EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
, &FileList
);
723 if (FileList
== NULL
|| IsListEmpty(&FileList
->Link
) || EFI_ERROR(Status
)) {
724 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_NF
), gShellLevel2HiiHandle
, L
"mv", ShellCommandLineGetRawValue(Package
, 1));
725 ShellStatus
= SHELL_NOT_FOUND
;
728 // ValidateAndMoveFiles will report errors to the screen itself
730 CwdSize
= StrSize(ShellGetCurrentDir(NULL
)) + sizeof(CHAR16
);
731 Cwd
= AllocateZeroPool(CwdSize
);
733 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_OUT_MEM
), gShellLevel2HiiHandle
, L
"mv");
734 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
736 StrCpyS (Cwd
, CwdSize
/ sizeof (CHAR16
), ShellGetCurrentDir (NULL
));
737 StrCatS (Cwd
, CwdSize
/ sizeof (CHAR16
), L
"\\");
738 ShellStatus
= ValidateAndMoveFiles (FileList
, &Response
, Cwd
);
746 ///@todo make sure this works with error half way through and continues...
747 for (ParamCount
--, LoopCounter
= 1 ; LoopCounter
< ParamCount
; LoopCounter
++) {
748 if (ShellGetExecutionBreakFlag()) {
751 Status
= ShellOpenFileMetaArg((CHAR16
*)ShellCommandLineGetRawValue(Package
, LoopCounter
), EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
, &FileList
);
752 if (FileList
== NULL
|| IsListEmpty(&FileList
->Link
) || EFI_ERROR(Status
)) {
753 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_NF
), gShellLevel2HiiHandle
, L
"mv", ShellCommandLineGetRawValue(Package
, LoopCounter
));
754 ShellStatus
= SHELL_NOT_FOUND
;
757 // ValidateAndMoveFiles will report errors to the screen itself
758 // Only change ShellStatus if it's sucessful
760 if (ShellStatus
== SHELL_SUCCESS
) {
761 ShellStatus
= ValidateAndMoveFiles(FileList
, &Response
, ShellCommandLineGetRawValue(Package
, ParamCount
));
763 ValidateAndMoveFiles(FileList
, &Response
, ShellCommandLineGetRawValue(Package
, ParamCount
));
766 if (FileList
!= NULL
&& !IsListEmpty(&FileList
->Link
)) {
767 Status
= ShellCloseFileMetaArg(&FileList
);
768 if (EFI_ERROR(Status
) && ShellStatus
== SHELL_SUCCESS
) {
769 ShellStatus
= SHELL_ACCESS_DENIED
;
770 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_ERR_FILE
), gShellLevel2HiiHandle
, L
"mv", ShellCommandLineGetRawValue(Package
, 1), ShellStatus
|MAX_BIT
);
775 } // switch on parameter count
777 if (FileList
!= NULL
) {
778 ShellCloseFileMetaArg(&FileList
);
782 // free the command line package
784 ShellCommandLineFreeVarList (Package
);
787 SHELL_FREE_NON_NULL(Response
);
789 if (ShellGetExecutionBreakFlag()) {
790 return (SHELL_ABORTED
);
793 return (ShellStatus
);