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