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 determine if SrcPath is valid to mv.
63 if SrcPath equal CWD then it's invalid.
64 if SrcPath is the parent path of CWD then it's invalid.
65 is SrcPath is NULL return FALSE.
67 if CwdPath is NULL then ASSERT()
69 @param SrcPath [in] The source path.
70 @param CwdPath [in] The current working directory.
72 @retval TRUE The source path is valid.
73 @retval FALSE The source path is invalid.
77 IN CONST CHAR16
* SrcPath
,
78 IN CONST CHAR16
* CwdPath
81 CHAR16
* SrcPathBuffer
;
82 CHAR16
* CwdPathBuffer
;
85 ASSERT (CwdPath
!= NULL
);
86 if (SrcPath
== NULL
) {
92 SrcPathBuffer
= AllocateCopyPool (StrSize (SrcPath
), SrcPath
);
93 if (SrcPathBuffer
== NULL
) {
97 CwdPathBuffer
= AllocateCopyPool (StrSize (CwdPath
), CwdPath
);
98 if (CwdPathBuffer
== NULL
) {
99 FreePool(SrcPathBuffer
);
103 gUnicodeCollation
->StrUpr (gUnicodeCollation
, SrcPathBuffer
);
104 gUnicodeCollation
->StrUpr (gUnicodeCollation
, CwdPathBuffer
);
106 if (SrcPathBuffer
[StrLen (SrcPathBuffer
) -1 ] == L
'\\') {
107 SrcPathBuffer
[StrLen (SrcPathBuffer
) - 1] = CHAR_NULL
;
110 if (CwdPathBuffer
[StrLen (CwdPathBuffer
) - 1] == L
'\\') {
111 CwdPathBuffer
[StrLen (CwdPathBuffer
) - 1] = CHAR_NULL
;
114 if (StrCmp (CwdPathBuffer
, SrcPathBuffer
) == 0 ||
115 ((StrStr (CwdPathBuffer
, SrcPathBuffer
) == CwdPathBuffer
) &&
116 (CwdPathBuffer
[StrLen (SrcPathBuffer
)] == L
'\\'))
121 FreePool (SrcPathBuffer
);
122 FreePool (CwdPathBuffer
);
128 Function to validate that moving a specific file (FileName) to a specific
129 location (DestPath) is valid.
131 This function will verify that the destination is not a subdirectory of
132 FullName, that the Current working Directory is not being moved, and that
133 the directory is not read only.
135 if the move is invalid this function will report the error to StdOut.
137 @param SourcePath [in] The name of the file to move.
138 @param Cwd [in] The current working directory
139 @param DestPath [in] The target location to move to
140 @param Attribute [in] The Attribute of the file
141 @param DestAttr [in] The Attribute of the destination
142 @param FileStatus [in] The Status of the file when opened
144 @retval TRUE The move is valid
145 @retval FALSE The move is not
149 IN CONST CHAR16
*SourcePath
,
150 IN CONST CHAR16
*Cwd
,
151 IN CONST CHAR16
*DestPath
,
152 IN CONST UINT64 Attribute
,
153 IN CONST UINT64 DestAttr
,
154 IN CONST EFI_STATUS FileStatus
157 CHAR16
*DestPathCopy
;
158 CHAR16
*DestPathWalker
;
160 if ((Cwd
!= NULL
) && ((Attribute
& EFI_FILE_DIRECTORY
) == EFI_FILE_DIRECTORY
)) {
161 if (!IsSoucePathValid (SourcePath
, Cwd
)) {
165 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN(STR_MV_INV_CWD
), gShellLevel2HiiHandle
);
171 // invalid to move read only or move to a read only destination
173 if (((Attribute
& EFI_FILE_READ_ONLY
) != 0)
174 || (FileStatus
== EFI_WRITE_PROTECTED
)
175 || ((DestAttr
& EFI_FILE_READ_ONLY
) != 0)
177 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MV_INV_RO
), gShellLevel2HiiHandle
, SourcePath
);
181 DestPathCopy
= AllocateCopyPool(StrSize(DestPath
), DestPath
);
182 if (DestPathCopy
== NULL
) {
186 for (DestPathWalker
= DestPathCopy
; *DestPathWalker
== L
'\\'; DestPathWalker
++) ;
188 while(DestPathWalker
!= NULL
&& DestPathWalker
[StrLen(DestPathWalker
)-1] == L
'\\') {
189 DestPathWalker
[StrLen(DestPathWalker
)-1] = CHAR_NULL
;
192 ASSERT(DestPathWalker
!= NULL
);
193 ASSERT(SourcePath
!= NULL
);
196 // If they're the same, or if source is "above" dest on file path tree
198 if ( StringNoCaseCompare (&DestPathWalker
, &SourcePath
) == 0 ||
199 ((StrStr(DestPathWalker
, SourcePath
) == DestPathWalker
) &&
200 (DestPathWalker
[StrLen(SourcePath
)] == '\\')
203 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_MV_INV_SUB
), gShellLevel2HiiHandle
);
204 FreePool(DestPathCopy
);
207 FreePool(DestPathCopy
);
213 Function to take a destination path that might contain wildcards and verify
214 that there is only a single possible target (IE we cant have wildcards that
215 have 2 possible destination).
217 if the result is sucessful the caller must free *DestPathPointer.
219 @param[in] DestParameter The original path to the destination.
220 @param[in, out] DestPathPointer A pointer to the callee allocated final path.
221 @param[in] Cwd A pointer to the current working directory.
222 @param[in] SingleSource TRUE to have only one source file.
223 @param[in, out] DestAttr A pointer to the destination information attribute.
225 @retval SHELL_INVALID_PARAMETER The DestParameter could not be resolved to a location.
226 @retval SHELL_INVALID_PARAMETER The DestParameter could be resolved to more than 1 location.
227 @retval SHELL_INVALID_PARAMETER Cwd is required and is NULL.
228 @retval SHELL_SUCCESS The operation was sucessful.
231 GetDestinationLocation(
232 IN CONST CHAR16
*DestParameter
,
233 IN OUT CHAR16
**DestPathPointer
,
234 IN CONST CHAR16
*Cwd
,
235 IN CONST BOOLEAN SingleSource
,
236 IN OUT UINT64
*DestAttr
239 EFI_SHELL_FILE_INFO
*DestList
;
240 EFI_SHELL_FILE_INFO
*Node
;
248 ASSERT(DestAttr
!= NULL
);
250 if (StrStr(DestParameter
, L
"\\") == DestParameter
) {
252 return SHELL_INVALID_PARAMETER
;
254 DestPath
= AllocateZeroPool(StrSize(Cwd
));
255 if (DestPath
== NULL
) {
256 return (SHELL_OUT_OF_RESOURCES
);
258 StrCpyS(DestPath
, StrSize(Cwd
) / sizeof(CHAR16
), Cwd
);
259 while (PathRemoveLastItem(DestPath
)) ;
262 // Append DestParameter beyond '\' which may be present
264 CurrentSize
= StrSize(DestPath
);
265 StrnCatGrow(&DestPath
, &CurrentSize
, &DestParameter
[1], 0);
267 *DestPathPointer
= DestPath
;
268 return (SHELL_SUCCESS
);
271 // get the destination path
273 ShellOpenFileMetaArg((CHAR16
*)DestParameter
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
, &DestList
);
274 if (DestList
== NULL
|| IsListEmpty(&DestList
->Link
)) {
276 // Not existing... must be renaming
278 if (StrStr(DestParameter
, L
":") == NULL
) {
280 ShellCloseFileMetaArg(&DestList
);
281 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_CWD
), gShellLevel2HiiHandle
);
282 return (SHELL_INVALID_PARAMETER
);
284 NewSize
= StrSize(Cwd
);
285 NewSize
+= StrSize(DestParameter
);
286 DestPath
= AllocateZeroPool(NewSize
);
287 if (DestPath
== NULL
) {
288 ShellCloseFileMetaArg(&DestList
);
289 return (SHELL_OUT_OF_RESOURCES
);
291 StrCpyS(DestPath
, NewSize
/ sizeof(CHAR16
), Cwd
);
292 if (DestPath
[StrLen(DestPath
)-1] != L
'\\' && DestParameter
[0] != L
'\\') {
293 StrCatS(DestPath
, NewSize
/ sizeof(CHAR16
), L
"\\");
294 } else if (DestPath
[StrLen(DestPath
)-1] == L
'\\' && DestParameter
[0] == L
'\\') {
295 ((CHAR16
*)DestPath
)[StrLen(DestPath
)-1] = CHAR_NULL
;
297 StrCatS(DestPath
, NewSize
/ sizeof(CHAR16
), DestParameter
);
299 ASSERT(DestPath
== NULL
);
300 DestPath
= StrnCatGrow(&DestPath
, NULL
, DestParameter
, 0);
301 if (DestPath
== NULL
) {
302 ShellCloseFileMetaArg(&DestList
);
303 return (SHELL_OUT_OF_RESOURCES
);
307 Node
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&DestList
->Link
);
308 *DestAttr
= Node
->Info
->Attribute
;
310 // Make sure there is only 1 node in the list.
312 if (!IsNodeAtEnd(&DestList
->Link
, &Node
->Link
)) {
313 ShellCloseFileMetaArg(&DestList
);
314 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_MARG_ERROR
), gShellLevel2HiiHandle
, L
"mv", DestParameter
);
315 return (SHELL_INVALID_PARAMETER
);
319 // If we are a directory or a single file, then one node is fine.
321 if (ShellIsDirectory(Node
->FullName
)==EFI_SUCCESS
|| SingleSource
) {
322 DestPath
= AllocateZeroPool(StrSize(Node
->FullName
)+sizeof(CHAR16
));
323 if (DestPath
== NULL
) {
324 ShellCloseFileMetaArg(&DestList
);
325 return (SHELL_OUT_OF_RESOURCES
);
327 StrCpyS(DestPath
, (StrSize(Node
->FullName
)+sizeof(CHAR16
)) / sizeof(CHAR16
), Node
->FullName
);
328 StrCatS(DestPath
, (StrSize(Node
->FullName
)+sizeof(CHAR16
)) / sizeof(CHAR16
), L
"\\");
331 // cant move multiple files onto a single file.
333 ShellCloseFileMetaArg(&DestList
);
334 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_ERROR
), gShellLevel2HiiHandle
, L
"mv", DestParameter
);
335 return (SHELL_INVALID_PARAMETER
);
339 *DestPathPointer
= DestPath
;
340 ShellCloseFileMetaArg(&DestList
);
342 return (SHELL_SUCCESS
);
346 Function to do a move across file systems.
348 @param[in] Node A pointer to the file to be removed.
349 @param[in] DestPath A pointer to the destination file path.
350 @param[out] Resp A pointer to response from question. Pass back on looped calling
352 @retval SHELL_SUCCESS The source file was moved to the destination.
355 MoveBetweenFileSystems(
356 IN EFI_SHELL_FILE_INFO
*Node
,
357 IN CONST CHAR16
*DestPath
,
361 SHELL_STATUS ShellStatus
;
364 // First we copy the file
366 ShellStatus
= CopySingleFile (Node
->FullName
, DestPath
, Resp
, TRUE
, L
"mv");
371 if (ShellStatus
== SHELL_SUCCESS
) {
373 // The copy was successful. delete the source file.
375 CascadeDelete(Node
, TRUE
);
377 } else if (ShellStatus
== SHELL_ABORTED
) {
379 } else if (ShellStatus
== SHELL_ACCESS_DENIED
) {
380 return EFI_ACCESS_DENIED
;
381 } else if (ShellStatus
== SHELL_VOLUME_FULL
) {
382 return EFI_VOLUME_FULL
;
384 return EFI_UNSUPPORTED
;
387 return (EFI_SUCCESS
);
391 Function to take the destination path and target file name to generate the full destination path.
393 @param[in] DestPath A pointer to the destination file path string.
394 @param[out] FullDestPath A pointer to the full destination path string.
395 @param[in] FileName Name string of the targe file.
397 @retval SHELL_SUCCESS the files were all moved.
398 @retval SHELL_INVALID_PARAMETER a parameter was invalid
399 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
403 IN CONST CHAR16
**DestPath
,
404 OUT CHAR16
**FullDestPath
,
405 IN CONST CHAR16
*FileName
409 if (FullDestPath
== NULL
|| FileName
== NULL
|| DestPath
== NULL
|| *DestPath
== NULL
){
410 return (EFI_INVALID_PARAMETER
);
413 Size
= StrSize(*DestPath
) + StrSize(FileName
);
415 *FullDestPath
= AllocateZeroPool(Size
);
416 if (*FullDestPath
== NULL
){
417 return (EFI_OUT_OF_RESOURCES
);
420 StrCpyS(*FullDestPath
, Size
/ sizeof(CHAR16
), *DestPath
);
421 if ((*FullDestPath
)[StrLen(*FullDestPath
)-1] != L
'\\' && FileName
[0] != L
'\\') {
422 StrCatS(*FullDestPath
, Size
/ sizeof(CHAR16
), L
"\\");
424 StrCatS(*FullDestPath
, Size
/ sizeof(CHAR16
), FileName
);
426 return (EFI_SUCCESS
);
430 Function to do a move within a file system.
432 @param[in] Node A pointer to the file to be removed.
433 @param[in] DestPath A pointer to the destination file path.
434 @param[out] Resp A pointer to response from question. Pass back on looped calling.
436 @retval SHELL_SUCCESS The source file was moved to the destination.
437 @retval SHELL_OUT_OF_RESOURCES A memory allocation failed.
440 MoveWithinFileSystems(
441 IN EFI_SHELL_FILE_INFO
*Node
,
446 EFI_FILE_INFO
*NewFileInfo
;
447 CHAR16
*TempLocation
;
453 // Chop off map info from DestPath
455 if ((TempLocation
= StrStr(DestPath
, L
":")) != NULL
) {
456 CopyMem(DestPath
, TempLocation
+1, StrSize(TempLocation
+1));
460 // construct the new file info block
462 NewSize
= StrSize(DestPath
);
463 NewSize
+= StrSize(Node
->FileName
) + SIZE_OF_EFI_FILE_INFO
+ sizeof(CHAR16
);
464 NewFileInfo
= AllocateZeroPool(NewSize
);
465 if (NewFileInfo
== NULL
) {
466 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_MEM
), gShellLevel2HiiHandle
);
467 Status
= EFI_OUT_OF_RESOURCES
;
469 CopyMem(NewFileInfo
, Node
->Info
, SIZE_OF_EFI_FILE_INFO
);
470 if (DestPath
[0] != L
'\\') {
471 StrCpyS(NewFileInfo
->FileName
, (NewSize
- SIZE_OF_EFI_FILE_INFO
) / sizeof(CHAR16
), L
"\\");
472 StrCatS(NewFileInfo
->FileName
, (NewSize
- SIZE_OF_EFI_FILE_INFO
) / sizeof(CHAR16
), DestPath
);
474 StrCpyS(NewFileInfo
->FileName
, (NewSize
- SIZE_OF_EFI_FILE_INFO
) / sizeof(CHAR16
), DestPath
);
476 Length
= StrLen(NewFileInfo
->FileName
);
480 if (NewFileInfo
->FileName
[Length
] == L
'\\') {
481 if (Node
->FileName
[0] == L
'\\') {
483 // Don't allow for double slashes. Eliminate one of them.
485 NewFileInfo
->FileName
[Length
] = CHAR_NULL
;
487 StrCatS(NewFileInfo
->FileName
, (NewSize
- SIZE_OF_EFI_FILE_INFO
) / sizeof(CHAR16
), Node
->FileName
);
489 NewFileInfo
->Size
= SIZE_OF_EFI_FILE_INFO
+ StrSize(NewFileInfo
->FileName
);
492 // Perform the move operation
494 Status
= ShellSetFileInfo(Node
->Handle
, NewFileInfo
);
497 // Free the info object we used...
499 FreePool(NewFileInfo
);
505 function to take a list of files to move and a destination location and do
506 the verification and moving of those files to that location. This function
507 will report any errors to the user and continue to move the rest of the files.
509 @param[in] FileList A LIST_ENTRY* based list of files to move
510 @param[out] Resp pointer to response from question. Pass back on looped calling
511 @param[in] DestParameter the originally specified destination location
513 @retval SHELL_SUCCESS the files were all moved.
514 @retval SHELL_INVALID_PARAMETER a parameter was invalid
515 @retval SHELL_SECURITY_VIOLATION a security violation ocurred
516 @retval SHELL_WRITE_PROTECTED the destination was write protected
517 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
520 ValidateAndMoveFiles(
521 IN EFI_SHELL_FILE_INFO
*FileList
,
523 IN CONST CHAR16
*DestParameter
530 CHAR16
*FullDestPath
;
533 SHELL_STATUS ShellStatus
;
534 EFI_SHELL_FILE_INFO
*Node
;
537 CHAR16
*CleanFilePathStr
;
539 ASSERT(FileList
!= NULL
);
540 ASSERT(DestParameter
!= NULL
);
544 Cwd
= ShellGetCurrentDir(NULL
);
547 CleanFilePathStr
= NULL
;
551 FullCwd
= AllocateZeroPool(StrSize(Cwd
) + sizeof(CHAR16
));
552 if (FullCwd
== NULL
) {
553 return SHELL_OUT_OF_RESOURCES
;
555 StrCpyS(FullCwd
, StrSize(Cwd
)/sizeof(CHAR16
)+1, Cwd
);
556 StrCatS(FullCwd
, StrSize(Cwd
)/sizeof(CHAR16
)+1, L
"\\");
560 Status
= ShellLevel2StripQuotes (DestParameter
, &CleanFilePathStr
);
561 if (EFI_ERROR (Status
)) {
562 SHELL_FREE_NON_NULL(FullCwd
);
563 if (Status
== EFI_OUT_OF_RESOURCES
) {
564 return SHELL_OUT_OF_RESOURCES
;
566 return SHELL_INVALID_PARAMETER
;
570 ASSERT (CleanFilePathStr
!= NULL
);
573 // Get and validate the destination location
575 ShellStatus
= GetDestinationLocation(CleanFilePathStr
, &DestPath
, FullCwd
, (BOOLEAN
)(FileList
->Link
.ForwardLink
== FileList
->Link
.BackLink
), &Attr
);
576 FreePool (CleanFilePathStr
);
578 if (ShellStatus
!= SHELL_SUCCESS
) {
579 SHELL_FREE_NON_NULL (FullCwd
);
580 return (ShellStatus
);
582 DestPath
= PathCleanUpDirectories(DestPath
);
583 if (DestPath
== NULL
) {
585 return (SHELL_OUT_OF_RESOURCES
);
588 HiiOutput
= HiiGetString (gShellLevel2HiiHandle
, STRING_TOKEN (STR_MV_OUTPUT
), NULL
);
589 HiiResultOk
= HiiGetString (gShellLevel2HiiHandle
, STRING_TOKEN (STR_GEN_RES_OK
), NULL
);
590 if (HiiOutput
== NULL
|| HiiResultOk
== NULL
) {
591 SHELL_FREE_NON_NULL(DestPath
);
592 SHELL_FREE_NON_NULL(HiiOutput
);
593 SHELL_FREE_NON_NULL(HiiResultOk
);
594 SHELL_FREE_NON_NULL(FullCwd
);
595 return (SHELL_OUT_OF_RESOURCES
);
599 // Go through the list of files and directories to move...
601 for (Node
= (EFI_SHELL_FILE_INFO
*)GetFirstNode(&FileList
->Link
)
602 ; !IsNull(&FileList
->Link
, &Node
->Link
)
603 ; Node
= (EFI_SHELL_FILE_INFO
*)GetNextNode(&FileList
->Link
, &Node
->Link
)
605 if (ShellGetExecutionBreakFlag()) {
610 // These should never be NULL
612 ASSERT(Node
->FileName
!= NULL
);
613 ASSERT(Node
->FullName
!= NULL
);
614 ASSERT(Node
->Info
!= NULL
);
617 // skip the directory traversing stuff...
619 if (StrCmp(Node
->FileName
, L
".") == 0 || StrCmp(Node
->FileName
, L
"..") == 0) {
623 SHELL_FREE_NON_NULL(FullDestPath
);
625 if (ShellIsDirectory(DestPath
)==EFI_SUCCESS
) {
626 CreateFullDestPath((CONST CHAR16
**)&DestPath
, &FullDestPath
, Node
->FileName
);
630 // Validate that the move is valid
632 if (!IsValidMove(Node
->FullName
, FullCwd
, FullDestPath
!=NULL
? FullDestPath
:DestPath
, Node
->Info
->Attribute
, Attr
, Node
->Status
)) {
633 ShellStatus
= SHELL_INVALID_PARAMETER
;
637 ShellPrintEx(-1, -1, HiiOutput
, Node
->FullName
, FullDestPath
!=NULL
? FullDestPath
:DestPath
);
640 // See if destination exists
642 if (!EFI_ERROR(ShellFileExists(FullDestPath
!=NULL
? FullDestPath
:DestPath
))) {
643 if (Response
== NULL
) {
644 ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel
, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR
), gShellLevel2HiiHandle
, &Response
);
646 switch (*(SHELL_PROMPT_RESPONSE
*)Response
) {
647 case ShellPromptResponseNo
:
651 case ShellPromptResponseCancel
:
654 // indicate to stop everything
656 SHELL_FREE_NON_NULL(FullCwd
);
657 return (SHELL_ABORTED
);
658 case ShellPromptResponseAll
:
661 case ShellPromptResponseYes
:
667 SHELL_FREE_NON_NULL(FullCwd
);
668 return SHELL_ABORTED
;
670 Status
= ShellDeleteFileByName(FullDestPath
!=NULL
? FullDestPath
:DestPath
);
673 if (IsBetweenFileSystem(Node
->FullName
, FullCwd
, DestPath
)) {
674 while (FullDestPath
== NULL
&& DestPath
!= NULL
&& DestPath
[0] != CHAR_NULL
&& DestPath
[StrLen(DestPath
) - 1] == L
'\\') {
675 DestPath
[StrLen(DestPath
) - 1] = CHAR_NULL
;
677 Status
= MoveBetweenFileSystems(Node
, FullDestPath
!=NULL
? FullDestPath
:DestPath
, &Response
);
679 Status
= MoveWithinFileSystems(Node
, DestPath
, &Response
);
681 // Display error status
683 if (EFI_ERROR(Status
)) {
684 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_ERR_UK
), gShellLevel2HiiHandle
, L
"mv", Status
);
691 if (EFI_ERROR(Status
)) {
692 ShellStatus
= SHELL_INVALID_PARAMETER
;
693 if (Status
== EFI_SECURITY_VIOLATION
) {
694 ShellStatus
= SHELL_SECURITY_VIOLATION
;
695 } else if (Status
== EFI_WRITE_PROTECTED
) {
696 ShellStatus
= SHELL_WRITE_PROTECTED
;
697 } else if (Status
== EFI_OUT_OF_RESOURCES
) {
698 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
699 } else if (Status
== EFI_DEVICE_ERROR
) {
700 ShellStatus
= SHELL_DEVICE_ERROR
;
701 } else if (Status
== EFI_ACCESS_DENIED
) {
702 ShellStatus
= SHELL_ACCESS_DENIED
;
705 ShellPrintEx(-1, -1, L
"%s", HiiResultOk
);
710 SHELL_FREE_NON_NULL(FullDestPath
);
711 SHELL_FREE_NON_NULL(DestPath
);
712 SHELL_FREE_NON_NULL(HiiOutput
);
713 SHELL_FREE_NON_NULL(HiiResultOk
);
714 SHELL_FREE_NON_NULL(FullCwd
);
715 return (ShellStatus
);
719 Function for 'mv' command.
721 @param[in] ImageHandle Handle to the Image (NULL if Internal).
722 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
727 IN EFI_HANDLE ImageHandle
,
728 IN EFI_SYSTEM_TABLE
*SystemTable
733 CHAR16
*ProblemParam
;
736 SHELL_STATUS ShellStatus
;
739 EFI_SHELL_FILE_INFO
*FileList
;
743 ShellStatus
= SHELL_SUCCESS
;
749 // initialize the shell lib (we must be in non-auto-init...)
751 Status
= ShellInitialize();
752 ASSERT_EFI_ERROR(Status
);
755 // parse the command line
757 Status
= ShellCommandLineParse (EmptyParamList
, &Package
, &ProblemParam
, TRUE
);
758 if (EFI_ERROR(Status
)) {
759 if (Status
== EFI_VOLUME_CORRUPTED
&& ProblemParam
!= NULL
) {
760 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellLevel2HiiHandle
, L
"mv", ProblemParam
);
761 FreePool(ProblemParam
);
762 ShellStatus
= SHELL_INVALID_PARAMETER
;
770 if (ShellCommandLineGetFlag(Package
, L
"-?")) {
774 switch (ParamCount
= ShellCommandLineGetCount(Package
)) {
778 // we have insufficient parameters
780 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_FEW
), gShellLevel2HiiHandle
, L
"mv");
781 ShellStatus
= SHELL_INVALID_PARAMETER
;
785 // must have valid CWD for single parameter...
787 if (ShellGetCurrentDir(NULL
) == NULL
){
788 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_CWD
), gShellLevel2HiiHandle
, L
"mv");
789 ShellStatus
= SHELL_INVALID_PARAMETER
;
791 Status
= ShellOpenFileMetaArg((CHAR16
*)ShellCommandLineGetRawValue(Package
, 1), EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
, &FileList
);
792 if (FileList
== NULL
|| IsListEmpty(&FileList
->Link
) || EFI_ERROR(Status
)) {
793 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_NF
), gShellLevel2HiiHandle
, L
"mv", ShellCommandLineGetRawValue(Package
, 1));
794 ShellStatus
= SHELL_NOT_FOUND
;
797 // ValidateAndMoveFiles will report errors to the screen itself
799 CwdSize
= StrSize(ShellGetCurrentDir(NULL
)) + sizeof(CHAR16
);
800 Cwd
= AllocateZeroPool(CwdSize
);
802 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_OUT_MEM
), gShellLevel2HiiHandle
, L
"mv");
803 ShellStatus
= SHELL_OUT_OF_RESOURCES
;
805 StrCpyS (Cwd
, CwdSize
/ sizeof (CHAR16
), ShellGetCurrentDir (NULL
));
806 StrCatS (Cwd
, CwdSize
/ sizeof (CHAR16
), L
"\\");
807 ShellStatus
= ValidateAndMoveFiles (FileList
, &Response
, Cwd
);
815 ///@todo make sure this works with error half way through and continues...
816 for (ParamCount
--, LoopCounter
= 1 ; LoopCounter
< ParamCount
; LoopCounter
++) {
817 if (ShellGetExecutionBreakFlag()) {
820 Status
= ShellOpenFileMetaArg((CHAR16
*)ShellCommandLineGetRawValue(Package
, LoopCounter
), EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
, &FileList
);
821 if (FileList
== NULL
|| IsListEmpty(&FileList
->Link
) || EFI_ERROR(Status
)) {
822 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_FILE_NF
), gShellLevel2HiiHandle
, L
"mv", ShellCommandLineGetRawValue(Package
, LoopCounter
));
823 ShellStatus
= SHELL_NOT_FOUND
;
826 // ValidateAndMoveFiles will report errors to the screen itself
827 // Only change ShellStatus if it's sucessful
829 if (ShellStatus
== SHELL_SUCCESS
) {
830 ShellStatus
= ValidateAndMoveFiles(FileList
, &Response
, ShellCommandLineGetRawValue(Package
, ParamCount
));
832 ValidateAndMoveFiles(FileList
, &Response
, ShellCommandLineGetRawValue(Package
, ParamCount
));
835 if (FileList
!= NULL
&& !IsListEmpty(&FileList
->Link
)) {
836 Status
= ShellCloseFileMetaArg(&FileList
);
837 if (EFI_ERROR(Status
) && ShellStatus
== SHELL_SUCCESS
) {
838 ShellStatus
= SHELL_ACCESS_DENIED
;
839 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_GEN_ERR_FILE
), gShellLevel2HiiHandle
, L
"mv", ShellCommandLineGetRawValue(Package
, 1), ShellStatus
|MAX_BIT
);
844 } // switch on parameter count
846 if (FileList
!= NULL
) {
847 ShellCloseFileMetaArg(&FileList
);
851 // free the command line package
853 ShellCommandLineFreeVarList (Package
);
856 SHELL_FREE_NON_NULL(Response
);
858 if (ShellGetExecutionBreakFlag()) {
859 return (SHELL_ABORTED
);
862 return (ShellStatus
);