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 - 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "UefiShellLevel2CommandsLib.h"
13 function to determine if a move is between file systems.
15 @param FullName [in] The name of the file to move.
16 @param Cwd [in] The current working directory
17 @param DestPath [in] The target location to move to
19 @retval TRUE The move is across file system.
20 @retval FALSE The move is within a file system.
24 IN CONST CHAR16
*FullName
,
26 IN CONST CHAR16
*DestPath
33 Test
= StrStr(FullName
, L
":");
34 if (Test
== NULL
&& Cwd
!= NULL
) {
35 Test
= StrStr(Cwd
, L
":");
37 Test1
= StrStr(DestPath
, L
":");
38 if (Test1
== NULL
&& Cwd
!= NULL
) {
39 Test1
= StrStr(Cwd
, L
":");
41 if (Test1
!= NULL
&& Test
!= NULL
) {
44 Result
= StringNoCaseCompare(&FullName
, &DestPath
);
55 function to determine if SrcPath is valid to mv.
57 if SrcPath equal CWD then it's invalid.
58 if SrcPath is the parent path of CWD then it's invalid.
59 is SrcPath is NULL return FALSE.
61 if CwdPath is NULL then ASSERT()
63 @param SrcPath [in] The source path.
64 @param CwdPath [in] The current working directory.
66 @retval TRUE The source path is valid.
67 @retval FALSE The source path is invalid.
71 IN CONST CHAR16
* SrcPath
,
72 IN CONST CHAR16
* CwdPath
75 CHAR16
* SrcPathBuffer
;
76 CHAR16
* CwdPathBuffer
;
79 ASSERT (CwdPath
!= NULL
);
80 if (SrcPath
== NULL
) {
86 SrcPathBuffer
= AllocateCopyPool (StrSize (SrcPath
), SrcPath
);
87 if (SrcPathBuffer
== NULL
) {
91 CwdPathBuffer
= AllocateCopyPool (StrSize (CwdPath
), CwdPath
);
92 if (CwdPathBuffer
== NULL
) {
93 FreePool(SrcPathBuffer
);
97 gUnicodeCollation
->StrUpr (gUnicodeCollation
, SrcPathBuffer
);
98 gUnicodeCollation
->StrUpr (gUnicodeCollation
, CwdPathBuffer
);
100 if (SrcPathBuffer
[StrLen (SrcPathBuffer
) -1 ] == L
'\\') {
101 SrcPathBuffer
[StrLen (SrcPathBuffer
) - 1] = CHAR_NULL
;
104 if (CwdPathBuffer
[StrLen (CwdPathBuffer
) - 1] == L
'\\') {
105 CwdPathBuffer
[StrLen (CwdPathBuffer
) - 1] = CHAR_NULL
;
108 if (StrCmp (CwdPathBuffer
, SrcPathBuffer
) == 0 ||
109 ((StrStr (CwdPathBuffer
, SrcPathBuffer
) == CwdPathBuffer
) &&
110 (CwdPathBuffer
[StrLen (SrcPathBuffer
)] == L
'\\'))
115 FreePool (SrcPathBuffer
);
116 FreePool (CwdPathBuffer
);
122 Function to validate that moving a specific file (FileName) to a specific
123 location (DestPath) is valid.
125 This function will verify that the destination is not a subdirectory of
126 FullName, that the Current working Directory is not being moved, and that
127 the directory is not read only.
129 if the move is invalid this function will report the error to StdOut.
131 @param SourcePath [in] The name of the file to move.
132 @param Cwd [in] The current working directory
133 @param DestPath [in] The target location to move to
134 @param Attribute [in] The Attribute of the file
135 @param DestAttr [in] The Attribute of the destination
136 @param FileStatus [in] The Status of the file when opened
138 @retval TRUE The move is valid
139 @retval FALSE The move is not
143 IN CONST CHAR16
*SourcePath
,
144 IN CONST CHAR16
*Cwd
,
145 IN CONST CHAR16
*DestPath
,
146 IN CONST UINT64 Attribute
,
147 IN CONST UINT64 DestAttr
,
148 IN CONST EFI_STATUS FileStatus
151 CHAR16
*DestPathCopy
;
152 CHAR16
*DestPathWalker
;
154 if ((Cwd
!= NULL
) && ((Attribute
& EFI_FILE_DIRECTORY
) == EFI_FILE_DIRECTORY
)) {
155 if (!IsSoucePathValid (SourcePath
, Cwd
)) {
159 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_MV_INV_CWD
), gShellLevel2HiiHandle
);
165 // invalid to move read only or move to a read only destination
167 if (((Attribute
& EFI_FILE_READ_ONLY
) != 0)
168 || (FileStatus
== EFI_WRITE_PROTECTED
)
169 || ((DestAttr
& EFI_FILE_READ_ONLY
) != 0)
171 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MV_INV_RO
), gShellLevel2HiiHandle
, SourcePath
);
175 DestPathCopy
= AllocateCopyPool(StrSize(DestPath
), DestPath
);
176 if (DestPathCopy
== NULL
) {
180 for (DestPathWalker
= DestPathCopy
; *DestPathWalker
== L
'\\'; DestPathWalker
++) ;
182 while(DestPathWalker
!= NULL
&& DestPathWalker
[StrLen(DestPathWalker
)-1] == L
'\\') {
183 DestPathWalker
[StrLen(DestPathWalker
)-1] = CHAR_NULL
;
186 ASSERT(DestPathWalker
!= NULL
);
187 ASSERT(SourcePath
!= NULL
);
190 // If they're the same, or if source is "above" dest on file path tree
192 if ( StringNoCaseCompare (&DestPathWalker
, &SourcePath
) == 0 ||
193 ((StrStr(DestPathWalker
, SourcePath
) == DestPathWalker
) &&
194 (DestPathWalker
[StrLen(SourcePath
)] == '\\')
197 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MV_INV_SUB
), gShellLevel2HiiHandle
);
198 FreePool(DestPathCopy
);
201 FreePool(DestPathCopy
);
207 Function to take a destination path that might contain wildcards and verify
208 that there is only a single possible target (IE we cant have wildcards that
209 have 2 possible destination).
211 if the result is sucessful the caller must free *DestPathPointer.
213 @param[in] DestParameter The original path to the destination.
214 @param[in, out] DestPathPointer A pointer to the callee allocated final path.
215 @param[in] Cwd A pointer to the current working directory.
216 @param[in] SingleSource TRUE to have only one source file.
217 @param[in, out] DestAttr A pointer to the destination information attribute.
219 @retval SHELL_INVALID_PARAMETER The DestParameter could not be resolved to a location.
220 @retval SHELL_INVALID_PARAMETER The DestParameter could be resolved to more than 1 location.
221 @retval SHELL_INVALID_PARAMETER Cwd is required and is NULL.
222 @retval SHELL_SUCCESS The operation was sucessful.
225 GetDestinationLocation(
226 IN CONST CHAR16
*DestParameter
,
227 IN OUT CHAR16
**DestPathPointer
,
228 IN CONST CHAR16
*Cwd
,
229 IN CONST BOOLEAN SingleSource
,
230 IN OUT UINT64
*DestAttr
233 EFI_SHELL_FILE_INFO
*DestList
;
234 EFI_SHELL_FILE_INFO
*Node
;
242 ASSERT(DestAttr
!= NULL
);
244 if (StrStr(DestParameter
, L
"\\") == DestParameter
) {
246 return SHELL_INVALID_PARAMETER
;
248 DestPath
= AllocateZeroPool(StrSize(Cwd
));
249 if (DestPath
== NULL
) {
250 return (SHELL_OUT_OF_RESOURCES
);
252 StrCpyS(DestPath
, StrSize(Cwd
) / sizeof(CHAR16
), Cwd
);
253 while (PathRemoveLastItem(DestPath
)) ;
256 // Append DestParameter beyond '\' which may be present
258 CurrentSize
= StrSize(DestPath
);
259 StrnCatGrow(&DestPath
, &CurrentSize
, &DestParameter
[1], 0);
261 *DestPathPointer
= DestPath
;
262 return (SHELL_SUCCESS
);
265 // get the destination path
267 ShellOpenFileMetaArg((CHAR16
*)DestParameter
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
, &DestList
);
268 if (DestList
== NULL
|| IsListEmpty(&DestList
->Link
)) {
270 // Not existing... must be renaming
272 if (StrStr(DestParameter
, L
":") == NULL
) {
274 ShellCloseFileMetaArg(&DestList
);
275 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_CWD
), gShellLevel2HiiHandle
);
276 return (SHELL_INVALID_PARAMETER
);
278 NewSize
= StrSize(Cwd
);
279 NewSize
+= StrSize(DestParameter
);
280 DestPath
= AllocateZeroPool(NewSize
);
281 if (DestPath
== NULL
) {
282 ShellCloseFileMetaArg(&DestList
);
283 return (SHELL_OUT_OF_RESOURCES
);
285 StrCpyS(DestPath
, NewSize
/ sizeof(CHAR16
), Cwd
);
286 if (DestPath
[StrLen(DestPath
)-1] != L
'\\' && DestParameter
[0] != L
'\\') {
287 StrCatS(DestPath
, NewSize
/ sizeof(CHAR16
), L
"\\");
288 } else if (DestPath
[StrLen(DestPath
)-1] == L
'\\' && DestParameter
[0] == L
'\\') {
289 ((CHAR16
*)DestPath
)[StrLen(DestPath
)-1] = CHAR_NULL
;
291 StrCatS(DestPath
, NewSize
/ sizeof(CHAR16
), DestParameter
);
293 ASSERT(DestPath
== NULL
);
294 DestPath
= StrnCatGrow(&DestPath
, NULL
, DestParameter
, 0);
295 if (DestPath
== NULL
) {
296 ShellCloseFileMetaArg(&DestList
);
297 return (SHELL_OUT_OF_RESOURCES
);
301 Node
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&DestList
->Link
);
302 *DestAttr
= Node
->Info
->Attribute
;
304 // Make sure there is only 1 node in the list.
306 if (!IsNodeAtEnd(&DestList
->Link
, &Node
->Link
)) {
307 ShellCloseFileMetaArg(&DestList
);
308 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_MARG_ERROR
), gShellLevel2HiiHandle
, L
"mv", DestParameter
);
309 return (SHELL_INVALID_PARAMETER
);
313 // If we are a directory or a single file, then one node is fine.
315 if (ShellIsDirectory(Node
->FullName
)==EFI_SUCCESS
|| SingleSource
) {
316 DestPath
= AllocateZeroPool(StrSize(Node
->FullName
)+sizeof(CHAR16
));
317 if (DestPath
== NULL
) {
318 ShellCloseFileMetaArg(&DestList
);
319 return (SHELL_OUT_OF_RESOURCES
);
321 StrCpyS(DestPath
, (StrSize(Node
->FullName
)+sizeof(CHAR16
)) / sizeof(CHAR16
), Node
->FullName
);
322 StrCatS(DestPath
, (StrSize(Node
->FullName
)+sizeof(CHAR16
)) / sizeof(CHAR16
), L
"\\");
325 // cant move multiple files onto a single file.
327 ShellCloseFileMetaArg(&DestList
);
328 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_ERROR
), gShellLevel2HiiHandle
, L
"mv", DestParameter
);
329 return (SHELL_INVALID_PARAMETER
);
333 *DestPathPointer
= DestPath
;
334 ShellCloseFileMetaArg(&DestList
);
336 return (SHELL_SUCCESS
);
340 Function to do a move across file systems.
342 @param[in] Node A pointer to the file to be removed.
343 @param[in] DestPath A pointer to the destination file path.
344 @param[out] Resp A pointer to response from question. Pass back on looped calling
346 @retval SHELL_SUCCESS The source file was moved to the destination.
349 MoveBetweenFileSystems(
350 IN EFI_SHELL_FILE_INFO
*Node
,
351 IN CONST CHAR16
*DestPath
,
355 SHELL_STATUS ShellStatus
;
358 // First we copy the file
360 ShellStatus
= CopySingleFile (Node
->FullName
, DestPath
, Resp
, TRUE
, L
"mv");
365 if (ShellStatus
== SHELL_SUCCESS
) {
367 // The copy was successful. delete the source file.
369 CascadeDelete(Node
, TRUE
);
371 } else if (ShellStatus
== SHELL_ABORTED
) {
373 } else if (ShellStatus
== SHELL_ACCESS_DENIED
) {
374 return EFI_ACCESS_DENIED
;
375 } else if (ShellStatus
== SHELL_VOLUME_FULL
) {
376 return EFI_VOLUME_FULL
;
378 return EFI_UNSUPPORTED
;
381 return (EFI_SUCCESS
);
385 Function to take the destination path and target file name to generate the full destination path.
387 @param[in] DestPath A pointer to the destination file path string.
388 @param[out] FullDestPath A pointer to the full destination path string.
389 @param[in] FileName Name string of the targe file.
391 @retval SHELL_SUCCESS the files were all moved.
392 @retval SHELL_INVALID_PARAMETER a parameter was invalid
393 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
397 IN CONST CHAR16
**DestPath
,
398 OUT CHAR16
**FullDestPath
,
399 IN CONST CHAR16
*FileName
403 if (FullDestPath
== NULL
|| FileName
== NULL
|| DestPath
== NULL
|| *DestPath
== NULL
){
404 return (EFI_INVALID_PARAMETER
);
407 Size
= StrSize(*DestPath
) + StrSize(FileName
);
409 *FullDestPath
= AllocateZeroPool(Size
);
410 if (*FullDestPath
== NULL
){
411 return (EFI_OUT_OF_RESOURCES
);
414 StrCpyS(*FullDestPath
, Size
/ sizeof(CHAR16
), *DestPath
);
415 if ((*FullDestPath
)[StrLen(*FullDestPath
)-1] != L
'\\' && FileName
[0] != L
'\\') {
416 StrCatS(*FullDestPath
, Size
/ sizeof(CHAR16
), L
"\\");
418 StrCatS(*FullDestPath
, Size
/ sizeof(CHAR16
), FileName
);
420 return (EFI_SUCCESS
);
424 Function to do a move within a file system.
426 @param[in] Node A pointer to the file to be removed.
427 @param[in] DestPath A pointer to the destination file path.
428 @param[out] Resp A pointer to response from question. Pass back on looped calling.
430 @retval SHELL_SUCCESS The source file was moved to the destination.
431 @retval SHELL_OUT_OF_RESOURCES A memory allocation failed.
434 MoveWithinFileSystems(
435 IN EFI_SHELL_FILE_INFO
*Node
,
440 EFI_FILE_INFO
*NewFileInfo
;
441 CHAR16
*TempLocation
;
447 // Chop off map info from DestPath
449 if ((TempLocation
= StrStr(DestPath
, L
":")) != NULL
) {
450 CopyMem(DestPath
, TempLocation
+1, StrSize(TempLocation
+1));
454 // construct the new file info block
456 NewSize
= StrSize(DestPath
);
457 NewSize
+= StrSize(Node
->FileName
) + SIZE_OF_EFI_FILE_INFO
+ sizeof(CHAR16
);
458 NewFileInfo
= AllocateZeroPool(NewSize
);
459 if (NewFileInfo
== NULL
) {
460 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_MEM
), gShellLevel2HiiHandle
);
461 Status
= EFI_OUT_OF_RESOURCES
;
463 CopyMem(NewFileInfo
, Node
->Info
, SIZE_OF_EFI_FILE_INFO
);
464 if (DestPath
[0] != L
'\\') {
465 StrCpyS(NewFileInfo
->FileName
, (NewSize
- SIZE_OF_EFI_FILE_INFO
) / sizeof(CHAR16
), L
"\\");
466 StrCatS(NewFileInfo
->FileName
, (NewSize
- SIZE_OF_EFI_FILE_INFO
) / sizeof(CHAR16
), DestPath
);
468 StrCpyS(NewFileInfo
->FileName
, (NewSize
- SIZE_OF_EFI_FILE_INFO
) / sizeof(CHAR16
), DestPath
);
470 Length
= StrLen(NewFileInfo
->FileName
);
474 if (NewFileInfo
->FileName
[Length
] == L
'\\') {
475 if (Node
->FileName
[0] == L
'\\') {
477 // Don't allow for double slashes. Eliminate one of them.
479 NewFileInfo
->FileName
[Length
] = CHAR_NULL
;
481 StrCatS(NewFileInfo
->FileName
, (NewSize
- SIZE_OF_EFI_FILE_INFO
) / sizeof(CHAR16
), Node
->FileName
);
483 NewFileInfo
->Size
= SIZE_OF_EFI_FILE_INFO
+ StrSize(NewFileInfo
->FileName
);
486 // Perform the move operation
488 Status
= ShellSetFileInfo(Node
->Handle
, NewFileInfo
);
491 // Free the info object we used...
493 FreePool(NewFileInfo
);
499 function to take a list of files to move and a destination location and do
500 the verification and moving of those files to that location. This function
501 will report any errors to the user and continue to move the rest of the files.
503 @param[in] FileList A LIST_ENTRY* based list of files to move
504 @param[out] Resp pointer to response from question. Pass back on looped calling
505 @param[in] DestParameter the originally specified destination location
507 @retval SHELL_SUCCESS the files were all moved.
508 @retval SHELL_INVALID_PARAMETER a parameter was invalid
509 @retval SHELL_SECURITY_VIOLATION a security violation ocurred
510 @retval SHELL_WRITE_PROTECTED the destination was write protected
511 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
514 ValidateAndMoveFiles(
515 IN EFI_SHELL_FILE_INFO
*FileList
,
517 IN CONST CHAR16
*DestParameter
524 CHAR16
*FullDestPath
;
527 SHELL_STATUS ShellStatus
;
528 EFI_SHELL_FILE_INFO
*Node
;
531 CHAR16
*CleanFilePathStr
;
533 ASSERT(FileList
!= NULL
);
534 ASSERT(DestParameter
!= NULL
);
538 Cwd
= ShellGetCurrentDir(NULL
);
541 CleanFilePathStr
= NULL
;
545 FullCwd
= AllocateZeroPool(StrSize(Cwd
) + sizeof(CHAR16
));
546 if (FullCwd
== NULL
) {
547 return SHELL_OUT_OF_RESOURCES
;
549 StrCpyS(FullCwd
, StrSize(Cwd
)/sizeof(CHAR16
)+1, Cwd
);
550 StrCatS(FullCwd
, StrSize(Cwd
)/sizeof(CHAR16
)+1, L
"\\");
554 Status
= ShellLevel2StripQuotes (DestParameter
, &CleanFilePathStr
);
555 if (EFI_ERROR (Status
)) {
556 SHELL_FREE_NON_NULL(FullCwd
);
557 if (Status
== EFI_OUT_OF_RESOURCES
) {
558 return SHELL_OUT_OF_RESOURCES
;
560 return SHELL_INVALID_PARAMETER
;
564 ASSERT (CleanFilePathStr
!= NULL
);
567 // Get and validate the destination location
569 ShellStatus
= GetDestinationLocation(CleanFilePathStr
, &DestPath
, FullCwd
, (BOOLEAN
)(FileList
->Link
.ForwardLink
== FileList
->Link
.BackLink
), &Attr
);
570 FreePool (CleanFilePathStr
);
572 if (ShellStatus
!= SHELL_SUCCESS
) {
573 SHELL_FREE_NON_NULL (FullCwd
);
574 return (ShellStatus
);
576 DestPath
= PathCleanUpDirectories(DestPath
);
577 if (DestPath
== NULL
) {
579 return (SHELL_OUT_OF_RESOURCES
);
582 HiiOutput
= HiiGetString (gShellLevel2HiiHandle
, STRING_TOKEN (STR_MV_OUTPUT
), NULL
);
583 HiiResultOk
= HiiGetString (gShellLevel2HiiHandle
, STRING_TOKEN (STR_GEN_RES_OK
), NULL
);
584 if (HiiOutput
== NULL
|| HiiResultOk
== NULL
) {
585 SHELL_FREE_NON_NULL(DestPath
);
586 SHELL_FREE_NON_NULL(HiiOutput
);
587 SHELL_FREE_NON_NULL(HiiResultOk
);
588 SHELL_FREE_NON_NULL(FullCwd
);
589 return (SHELL_OUT_OF_RESOURCES
);
593 // Go through the list of files and directories to move...
595 for (Node
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&FileList
->Link
)
596 ; !IsNull(&FileList
->Link
, &Node
->Link
)
597 ; Node
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&FileList
->Link
, &Node
->Link
)
599 if (ShellGetExecutionBreakFlag()) {
604 // These should never be NULL
606 ASSERT(Node
->FileName
!= NULL
);
607 ASSERT(Node
->FullName
!= NULL
);
608 ASSERT(Node
->Info
!= NULL
);
611 // skip the directory traversing stuff...
613 if (StrCmp(Node
->FileName
, L
".") == 0 || StrCmp(Node
->FileName
, L
"..") == 0) {
617 SHELL_FREE_NON_NULL(FullDestPath
);
619 if (ShellIsDirectory(DestPath
)==EFI_SUCCESS
) {
620 CreateFullDestPath((CONST CHAR16
**)&DestPath
, &FullDestPath
, Node
->FileName
);
624 // Validate that the move is valid
626 if (!IsValidMove(Node
->FullName
, FullCwd
, FullDestPath
!=NULL
? FullDestPath
:DestPath
, Node
->Info
->Attribute
, Attr
, Node
->Status
)) {
627 ShellStatus
= SHELL_INVALID_PARAMETER
;
631 ShellPrintEx(-1, -1, HiiOutput
, Node
->FullName
, FullDestPath
!=NULL
? FullDestPath
:DestPath
);
634 // See if destination exists
636 if (!EFI_ERROR(ShellFileExists(FullDestPath
!=NULL
? FullDestPath
:DestPath
))) {
637 if (Response
== NULL
) {
638 ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel
, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR
), gShellLevel2HiiHandle
, &Response
);
640 if (Response
== NULL
) {
641 return SHELL_ABORTED
;
643 switch (*(SHELL_PROMPT_RESPONSE
*)Response
) {
644 case ShellPromptResponseNo
:
648 case ShellPromptResponseCancel
:
651 // indicate to stop everything
653 SHELL_FREE_NON_NULL(FullCwd
);
654 return (SHELL_ABORTED
);
655 case ShellPromptResponseAll
:
658 case ShellPromptResponseYes
:
664 SHELL_FREE_NON_NULL(FullCwd
);
665 return SHELL_ABORTED
;
667 Status
= ShellDeleteFileByName(FullDestPath
!=NULL
? FullDestPath
:DestPath
);
670 if (IsBetweenFileSystem(Node
->FullName
, FullCwd
, DestPath
)) {
671 while (FullDestPath
== NULL
&& DestPath
!= NULL
&& DestPath
[0] != CHAR_NULL
&& DestPath
[StrLen(DestPath
) - 1] == L
'\\') {
672 DestPath
[StrLen(DestPath
) - 1] = CHAR_NULL
;
674 Status
= MoveBetweenFileSystems(Node
, FullDestPath
!=NULL
? FullDestPath
:DestPath
, &Response
);
676 Status
= MoveWithinFileSystems(Node
, DestPath
, &Response
);
678 // Display error status
680 if (EFI_ERROR(Status
)) {
681 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_ERR_UK
), gShellLevel2HiiHandle
, L
"mv", Status
);
688 if (EFI_ERROR(Status
)) {
689 ShellStatus
= SHELL_INVALID_PARAMETER
;
690 if (Status
== EFI_SECURITY_VIOLATION
) {
691 ShellStatus
= SHELL_SECURITY_VIOLATION
;
692 } else if (Status
== EFI_WRITE_PROTECTED
) {
693 ShellStatus
= SHELL_WRITE_PROTECTED
;
694 } else if (Status
== EFI_OUT_OF_RESOURCES
) {
695 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
696 } else if (Status
== EFI_DEVICE_ERROR
) {
697 ShellStatus
= SHELL_DEVICE_ERROR
;
698 } else if (Status
== EFI_ACCESS_DENIED
) {
699 ShellStatus
= SHELL_ACCESS_DENIED
;
702 ShellPrintEx(-1, -1, L
"%s", HiiResultOk
);
707 SHELL_FREE_NON_NULL(FullDestPath
);
708 SHELL_FREE_NON_NULL(DestPath
);
709 SHELL_FREE_NON_NULL(HiiOutput
);
710 SHELL_FREE_NON_NULL(HiiResultOk
);
711 SHELL_FREE_NON_NULL(FullCwd
);
712 return (ShellStatus
);
716 Function for 'mv' command.
718 @param[in] ImageHandle Handle to the Image (NULL if Internal).
719 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
724 IN EFI_HANDLE ImageHandle
,
725 IN EFI_SYSTEM_TABLE
*SystemTable
730 CHAR16
*ProblemParam
;
733 SHELL_STATUS ShellStatus
;
736 EFI_SHELL_FILE_INFO
*FileList
;
740 ShellStatus
= SHELL_SUCCESS
;
746 // initialize the shell lib (we must be in non-auto-init...)
748 Status
= ShellInitialize();
749 ASSERT_EFI_ERROR(Status
);
752 // parse the command line
754 Status
= ShellCommandLineParse (EmptyParamList
, &Package
, &ProblemParam
, TRUE
);
755 if (EFI_ERROR(Status
)) {
756 if (Status
== EFI_VOLUME_CORRUPTED
&& ProblemParam
!= NULL
) {
757 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellLevel2HiiHandle
, L
"mv", ProblemParam
);
758 FreePool(ProblemParam
);
759 ShellStatus
= SHELL_INVALID_PARAMETER
;
767 if (ShellCommandLineGetFlag(Package
, L
"-?")) {
771 switch (ParamCount
= ShellCommandLineGetCount(Package
)) {
775 // we have insufficient parameters
777 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellLevel2HiiHandle
, L
"mv");
778 ShellStatus
= SHELL_INVALID_PARAMETER
;
782 // must have valid CWD for single parameter...
784 if (ShellGetCurrentDir(NULL
) == NULL
){
785 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_CWD
), gShellLevel2HiiHandle
, L
"mv");
786 ShellStatus
= SHELL_INVALID_PARAMETER
;
788 Status
= ShellOpenFileMetaArg((CHAR16
*)ShellCommandLineGetRawValue(Package
, 1), EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
, &FileList
);
789 if (FileList
== NULL
|| IsListEmpty(&FileList
->Link
) || EFI_ERROR(Status
)) {
790 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_NF
), gShellLevel2HiiHandle
, L
"mv", ShellCommandLineGetRawValue(Package
, 1));
791 ShellStatus
= SHELL_NOT_FOUND
;
794 // ValidateAndMoveFiles will report errors to the screen itself
796 CwdSize
= StrSize(ShellGetCurrentDir(NULL
)) + sizeof(CHAR16
);
797 Cwd
= AllocateZeroPool(CwdSize
);
799 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_OUT_MEM
), gShellLevel2HiiHandle
, L
"mv");
800 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
802 StrCpyS (Cwd
, CwdSize
/ sizeof (CHAR16
), ShellGetCurrentDir (NULL
));
803 StrCatS (Cwd
, CwdSize
/ sizeof (CHAR16
), L
"\\");
804 ShellStatus
= ValidateAndMoveFiles (FileList
, &Response
, Cwd
);
812 ///@todo make sure this works with error half way through and continues...
813 for (ParamCount
--, LoopCounter
= 1 ; LoopCounter
< ParamCount
; LoopCounter
++) {
814 if (ShellGetExecutionBreakFlag()) {
817 Status
= ShellOpenFileMetaArg((CHAR16
*)ShellCommandLineGetRawValue(Package
, LoopCounter
), EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
, &FileList
);
818 if (FileList
== NULL
|| IsListEmpty(&FileList
->Link
) || EFI_ERROR(Status
)) {
819 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_NF
), gShellLevel2HiiHandle
, L
"mv", ShellCommandLineGetRawValue(Package
, LoopCounter
));
820 ShellStatus
= SHELL_NOT_FOUND
;
823 // ValidateAndMoveFiles will report errors to the screen itself
824 // Only change ShellStatus if it's sucessful
826 if (ShellStatus
== SHELL_SUCCESS
) {
827 ShellStatus
= ValidateAndMoveFiles(FileList
, &Response
, ShellCommandLineGetRawValue(Package
, ParamCount
));
829 ValidateAndMoveFiles(FileList
, &Response
, ShellCommandLineGetRawValue(Package
, ParamCount
));
832 if (FileList
!= NULL
&& !IsListEmpty(&FileList
->Link
)) {
833 Status
= ShellCloseFileMetaArg(&FileList
);
834 if (EFI_ERROR(Status
) && ShellStatus
== SHELL_SUCCESS
) {
835 ShellStatus
= SHELL_ACCESS_DENIED
;
836 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_ERR_FILE
), gShellLevel2HiiHandle
, L
"mv", ShellCommandLineGetRawValue(Package
, 1), ShellStatus
|MAX_BIT
);
841 } // switch on parameter count
843 if (FileList
!= NULL
) {
844 ShellCloseFileMetaArg(&FileList
);
848 // free the command line package
850 ShellCommandLineFreeVarList (Package
);
853 SHELL_FREE_NON_NULL(Response
);
855 if (ShellGetExecutionBreakFlag()) {
856 return (SHELL_ABORTED
);
859 return (ShellStatus
);