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