]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c
1) Add type cast for better coding style.
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / Cp.c
CommitLineData
a405b86d 1/** @file\r
2 Main file for cp shell level 2 function.\r
3\r
7282b505 4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
a405b86d 5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "UefiShellLevel2CommandsLib.h"\r
f06be00e 16#include <Guid/FileSystemInfo.h>\r
17#include <Guid/FileSystemVolumeLabelInfo.h>\r
a405b86d 18\r
b54fd049 19/**\r
20 Function to take a list of files to copy and a destination location and do\r
21 the verification and copying of those files to that location. This function\r
22 will report any errors to the user and halt.\r
23\r
24 @param[in] FileList A LIST_ENTRY* based list of files to move.\r
25 @param[in] DestDir The destination location.\r
26 @param[in] SilentMode TRUE to eliminate screen output.\r
27 @param[in] RecursiveMode TRUE to copy directories.\r
28 @param[in] Resp The response to the overwrite query (if always).\r
29\r
30 @retval SHELL_SUCCESS the files were all moved.\r
31 @retval SHELL_INVALID_PARAMETER a parameter was invalid\r
32 @retval SHELL_SECURITY_VIOLATION a security violation ocurred\r
33 @retval SHELL_WRITE_PROTECTED the destination was write protected\r
34 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed\r
35**/\r
a405b86d 36SHELL_STATUS\r
37EFIAPI\r
38ValidateAndCopyFiles(\r
39 IN CONST EFI_SHELL_FILE_INFO *FileList,\r
40 IN CONST CHAR16 *DestDir,\r
41 IN BOOLEAN SilentMode,\r
42 IN BOOLEAN RecursiveMode,\r
43 IN VOID **Resp\r
44 );\r
45\r
46/**\r
47 Function to Copy one file to another location\r
48\r
49 If the destination exists the user will be prompted and the result put into *resp\r
50\r
51 @param[in] Source pointer to source file name\r
52 @param[in] Dest pointer to destination file name\r
53 @param[out] Resp pointer to response from question. Pass back on looped calling\r
54 @param[in] SilentMode whether to run in quiet mode or not\r
55\r
56 @retval SHELL_SUCCESS The source file was copied to the destination\r
57**/\r
58SHELL_STATUS\r
59EFIAPI\r
60CopySingleFile(\r
61 IN CONST CHAR16 *Source,\r
62 IN CONST CHAR16 *Dest,\r
63 OUT VOID **Resp,\r
64 IN BOOLEAN SilentMode\r
65 )\r
66{\r
f06be00e 67 VOID *Response;\r
68 UINTN ReadSize;\r
69 SHELL_FILE_HANDLE SourceHandle;\r
70 SHELL_FILE_HANDLE DestHandle;\r
71 EFI_STATUS Status;\r
72 VOID *Buffer;\r
73 CHAR16 *TempName;\r
74 UINTN Size;\r
75 EFI_SHELL_FILE_INFO *List;\r
76 SHELL_STATUS ShellStatus;\r
77 UINT64 SourceFileSize;\r
78 UINT64 DestFileSize;\r
79 EFI_FILE_PROTOCOL *DestVolumeFP;\r
80 EFI_FILE_SYSTEM_INFO *DestVolumeInfo;\r
81 UINTN DestVolumeInfoSize;\r
a405b86d 82\r
83 ASSERT(Resp != NULL);\r
84\r
f06be00e 85 SourceHandle = NULL;\r
86 DestHandle = NULL;\r
87 Response = *Resp;\r
88 List = NULL;\r
89 DestVolumeInfo = NULL;\r
e755a4ca 90 ShellStatus = SHELL_SUCCESS;\r
a405b86d 91\r
433a21cb 92 ReadSize = PcdGet32(PcdShellFileOperationSize);\r
a405b86d 93 // Why bother copying a file to itself\r
94 if (StrCmp(Source, Dest) == 0) {\r
95 return (SHELL_SUCCESS);\r
96 }\r
97\r
a405b86d 98 //\r
99 // if the destination file existed check response and possibly prompt user\r
100 //\r
ac8783c8 101 if (ShellFileExists(Dest) == EFI_SUCCESS) {\r
a405b86d 102 if (Response == NULL && !SilentMode) {\r
b54fd049 103 Status = ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response);\r
a405b86d 104 }\r
105 //\r
106 // possibly return based on response\r
107 //\r
108 if (!SilentMode) {\r
109 switch (*(SHELL_PROMPT_RESPONSE*)Response) {\r
110 case ShellPromptResponseNo:\r
111 //\r
112 // return success here so we dont stop the process\r
113 //\r
114 return (SHELL_SUCCESS);\r
115 case ShellPromptResponseCancel:\r
116 *Resp = Response;\r
117 //\r
118 // indicate to stop everything\r
119 //\r
120 return (SHELL_ABORTED);\r
121 case ShellPromptResponseAll:\r
122 *Resp = Response;\r
123 case ShellPromptResponseYes:\r
124 break;\r
e9723321 125 default:\r
126 return SHELL_ABORTED;\r
a405b86d 127 }\r
128 }\r
129 }\r
130\r
131 if (ShellIsDirectory(Source) == EFI_SUCCESS) {\r
132 Status = ShellCreateDirectory(Dest, &DestHandle);\r
133 if (EFI_ERROR(Status)) {\r
7282b505 134 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_DIR_FAIL), gShellLevel2HiiHandle, Dest);\r
a405b86d 135 return (SHELL_ACCESS_DENIED);\r
136 }\r
137\r
138 //\r
139 // Now copy all the files under the directory...\r
140 //\r
141 TempName = NULL;\r
f06be00e 142 Size = 0;\r
a405b86d 143 StrnCatGrow(&TempName, &Size, Source, 0);\r
144 StrnCatGrow(&TempName, &Size, L"\\*", 0);\r
7dd05623 145 if (TempName != NULL) {\r
146 ShellOpenFileMetaArg((CHAR16*)TempName, EFI_FILE_MODE_READ, &List);\r
147 *TempName = CHAR_NULL;\r
148 StrnCatGrow(&TempName, &Size, Dest, 0);\r
149 StrnCatGrow(&TempName, &Size, L"\\", 0);\r
150 ShellStatus = ValidateAndCopyFiles(List, TempName, SilentMode, TRUE, Resp);\r
151 ShellCloseFileMetaArg(&List);\r
152 SHELL_FREE_NON_NULL(TempName);\r
153 Size = 0;\r
154 }\r
a405b86d 155 } else {\r
ac8783c8 156 Status = ShellDeleteFileByName(Dest);\r
a405b86d 157\r
ac8783c8
JC
158 //\r
159 // open file with create enabled\r
160 //\r
161 Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);\r
162 if (EFI_ERROR(Status)) {\r
7282b505 163 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_OPEN_FAIL), gShellLevel2HiiHandle, Dest);\r
ac8783c8
JC
164 return (SHELL_ACCESS_DENIED);\r
165 }\r
f06be00e 166\r
ac8783c8
JC
167 //\r
168 // open source file\r
169 //\r
170 Status = ShellOpenFileByName(Source, &SourceHandle, EFI_FILE_MODE_READ, 0);\r
171 ASSERT_EFI_ERROR(Status);\r
f06be00e 172\r
ac8783c8
JC
173 //\r
174 //get file size of source file and freespace available on destination volume\r
175 //\r
176 ShellGetFileSize(SourceHandle, &SourceFileSize);\r
177 ShellGetFileSize(DestHandle, &DestFileSize);\r
f06be00e 178\r
ac8783c8
JC
179 //\r
180 //if the destination file already exists then it will be replaced, meaning the sourcefile effectively needs less storage space\r
181 //\r
182 if(DestFileSize < SourceFileSize){\r
183 SourceFileSize -= DestFileSize;\r
184 } else {\r
185 SourceFileSize = 0;\r
186 }\r
187\r
188 //\r
189 //get the system volume info to check the free space\r
190 //\r
191 DestVolumeFP = ConvertShellHandleToEfiFileProtocol(DestHandle);\r
192 DestVolumeInfo = NULL;\r
193 DestVolumeInfoSize = 0;\r
194 Status = DestVolumeFP->GetInfo(\r
195 DestVolumeFP,\r
196 &gEfiFileSystemInfoGuid,\r
197 &DestVolumeInfoSize,\r
198 DestVolumeInfo\r
199 );\r
200\r
201 if (Status == EFI_BUFFER_TOO_SMALL) {\r
202 DestVolumeInfo = AllocateZeroPool(DestVolumeInfoSize);\r
f06be00e 203 Status = DestVolumeFP->GetInfo(\r
204 DestVolumeFP,\r
205 &gEfiFileSystemInfoGuid,\r
206 &DestVolumeInfoSize,\r
207 DestVolumeInfo\r
208 );\r
ac8783c8 209 }\r
f06be00e 210\r
ac8783c8
JC
211 //\r
212 //check if enough space available on destination drive to complete copy\r
213 //\r
214 if (DestVolumeInfo!= NULL && (DestVolumeInfo->FreeSpace < SourceFileSize)) {\r
f06be00e 215 //\r
ac8783c8 216 //not enough space on destination directory to copy file\r
f06be00e 217 //\r
f06be00e 218 SHELL_FREE_NON_NULL(DestVolumeInfo);\r
ac8783c8
JC
219 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_FAIL), gShellLevel2HiiHandle);\r
220 return(SHELL_VOLUME_FULL);\r
221 } else {\r
222 //\r
223 // copy data between files\r
224 //\r
225 Buffer = AllocateZeroPool(ReadSize);\r
226 ASSERT(Buffer != NULL);\r
227 while (ReadSize == PcdGet32(PcdShellFileOperationSize) && !EFI_ERROR(Status)) {\r
228 Status = ShellReadFile(SourceHandle, &ReadSize, Buffer);\r
f3a14a0f
SQ
229 if (!EFI_ERROR(Status)) {\r
230 Status = ShellWriteFile(DestHandle, &ReadSize, Buffer);\r
231 if (EFI_ERROR(Status)) {\r
232 ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT));\r
233 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_WRITE_ERROR), gShellLevel2HiiHandle, Dest);\r
234 break;\r
235 }\r
236 } else {\r
237 ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT));\r
238 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_READ_ERROR), gShellLevel2HiiHandle, Source);\r
239 break;\r
240 }\r
ac8783c8 241 }\r
a405b86d 242 }\r
ac8783c8
JC
243 SHELL_FREE_NON_NULL(DestVolumeInfo);\r
244 }\r
f3a14a0f 245 \r
a405b86d 246 //\r
247 // close files\r
248 //\r
249 if (DestHandle != NULL) {\r
250 ShellCloseFile(&DestHandle);\r
251 DestHandle = NULL;\r
252 }\r
253 if (SourceHandle != NULL) {\r
254 ShellCloseFile(&SourceHandle);\r
255 SourceHandle = NULL;\r
256 }\r
257\r
258 //\r
259 // return\r
260 //\r
e755a4ca 261 return ShellStatus;\r
a405b86d 262}\r
263\r
264/**\r
265 function to take a list of files to copy and a destination location and do\r
266 the verification and copying of those files to that location. This function\r
267 will report any errors to the user and halt.\r
268\r
269 The key is to have this function called ONLY once. this allows for the parameter\r
270 verification to happen correctly.\r
271\r
b54fd049 272 @param[in] FileList A LIST_ENTRY* based list of files to move.\r
273 @param[in] DestDir The destination location.\r
274 @param[in] SilentMode TRUE to eliminate screen output.\r
275 @param[in] RecursiveMode TRUE to copy directories.\r
276 @param[in] Resp The response to the overwrite query (if always).\r
a405b86d 277\r
278 @retval SHELL_SUCCESS the files were all moved.\r
279 @retval SHELL_INVALID_PARAMETER a parameter was invalid\r
280 @retval SHELL_SECURITY_VIOLATION a security violation ocurred\r
281 @retval SHELL_WRITE_PROTECTED the destination was write protected\r
282 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed\r
283**/\r
284SHELL_STATUS\r
285EFIAPI\r
286ValidateAndCopyFiles(\r
287 IN CONST EFI_SHELL_FILE_INFO *FileList,\r
288 IN CONST CHAR16 *DestDir,\r
289 IN BOOLEAN SilentMode,\r
290 IN BOOLEAN RecursiveMode,\r
291 IN VOID **Resp\r
292 )\r
293{\r
294 CHAR16 *HiiOutput;\r
295 CHAR16 *HiiResultOk;\r
296 CONST EFI_SHELL_FILE_INFO *Node;\r
297 SHELL_STATUS ShellStatus;\r
298 CHAR16 *DestPath;\r
299 VOID *Response;\r
300 UINTN PathLen;\r
301 CONST CHAR16 *Cwd;\r
a405b86d 302 UINTN NewSize;\r
303\r
304 if (Resp == NULL) {\r
305 Response = NULL;\r
306 } else {\r
307 Response = *Resp;\r
308 }\r
309\r
310 DestPath = NULL;\r
311 ShellStatus = SHELL_SUCCESS;\r
312 PathLen = 0;\r
313 Cwd = ShellGetCurrentDir(NULL);\r
314\r
315 ASSERT(FileList != NULL);\r
316 ASSERT(DestDir != NULL);\r
317\r
318 //\r
319 // If we are trying to copy multiple files... make sure we got a directory for the target...\r
320 //\r
321 if (EFI_ERROR(ShellIsDirectory(DestDir)) && FileList->Link.ForwardLink != FileList->Link.BackLink) {\r
322 //\r
323 // Error for destination not a directory\r
324 //\r
325 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir);\r
326 return (SHELL_INVALID_PARAMETER);\r
327 }\r
328 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)\r
329 ; !IsNull(&FileList->Link, &Node->Link)\r
330 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)\r
f06be00e 331 ){\r
a405b86d 332 //\r
333 // skip the directory traversing stuff...\r
334 //\r
335 if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {\r
336 continue;\r
337 }\r
338\r
339 NewSize = StrSize(DestDir);\r
b54fd049 340 NewSize += StrSize(Node->FullName);\r
ed053afe 341 NewSize += (Cwd == NULL)? 0 : StrSize(Cwd);\r
a405b86d 342 if (NewSize > PathLen) {\r
343 PathLen = NewSize;\r
344 }\r
345\r
346 //\r
347 // Make sure got -r if required\r
348 //\r
349 if (!RecursiveMode && !EFI_ERROR(ShellIsDirectory(Node->FullName))) {\r
350 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_REQ), gShellLevel2HiiHandle);\r
351 return (SHELL_INVALID_PARAMETER);\r
352 }\r
353\r
354 //\r
355 // make sure got dest as dir if needed\r
356 //\r
357 if (!EFI_ERROR(ShellIsDirectory(Node->FullName)) && EFI_ERROR(ShellIsDirectory(DestDir))) {\r
358 //\r
359 // Error for destination not a directory\r
360 //\r
361 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir);\r
362 return (SHELL_INVALID_PARAMETER);\r
363 }\r
364 }\r
365\r
366 HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_CP_OUTPUT), NULL);\r
367 HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL);\r
b54fd049 368 DestPath = AllocateZeroPool(PathLen);\r
a405b86d 369\r
3e082d58 370 if (DestPath == NULL || HiiOutput == NULL || HiiResultOk == NULL) {\r
9ea69f8a 371 SHELL_FREE_NON_NULL(DestPath);\r
372 SHELL_FREE_NON_NULL(HiiOutput);\r
373 SHELL_FREE_NON_NULL(HiiResultOk);\r
374 return (SHELL_OUT_OF_RESOURCES);\r
375 }\r
376\r
a405b86d 377 //\r
378 // Go through the list of files to copy...\r
379 //\r
380 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)\r
381 ; !IsNull(&FileList->Link, &Node->Link)\r
382 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)\r
f06be00e 383 ){\r
a405b86d 384 if (ShellGetExecutionBreakFlag()) {\r
385 break;\r
386 }\r
387 ASSERT(Node->FileName != NULL);\r
388 ASSERT(Node->FullName != NULL);\r
389\r
390 //\r
391 // skip the directory traversing stuff...\r
392 //\r
393 if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {\r
394 continue;\r
395 }\r
396\r
397 if (FileList->Link.ForwardLink == FileList->Link.BackLink // 1 item\r
398 && EFI_ERROR(ShellIsDirectory(DestDir)) // not an existing directory\r
f06be00e 399 ) {\r
b54fd049 400 if (StrStr(DestDir, L":") == NULL) {\r
401 //\r
402 // simple copy of a single file\r
403 //\r
ed053afe
ED
404 if (Cwd != NULL) {\r
405 StrCpy(DestPath, Cwd);\r
406 } else {\r
407 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, DestDir);\r
408 return (SHELL_INVALID_PARAMETER);\r
409 }\r
b54fd049 410 if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') {\r
411 StrCat(DestPath, L"\\");\r
412 } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') {\r
413 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;\r
414 }\r
415 StrCat(DestPath, DestDir);\r
416 } else {\r
417 StrCpy(DestPath, DestDir);\r
a405b86d 418 }\r
a405b86d 419 } else {\r
420 //\r
421 // we have multiple files or a directory in the DestDir\r
422 //\r
1fc3749d 423 \r
424 //\r
425 // Check for leading slash\r
426 //\r
427 if (DestDir[0] == L'\\') {\r
ed053afe
ED
428 //\r
429 // Copy to the root of CWD\r
430 //\r
431 if (Cwd != NULL) {\r
432 StrCpy(DestPath, Cwd);\r
433 } else {\r
434 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, DestDir);\r
435 return (SHELL_INVALID_PARAMETER);\r
436 }\r
1fc3749d 437 while (PathRemoveLastItem(DestPath));\r
438 StrCat(DestPath, DestDir+1);\r
439 StrCat(DestPath, Node->FileName);\r
440 } else if (StrStr(DestDir, L":") == NULL) {\r
ed053afe
ED
441 if (Cwd != NULL) {\r
442 StrCpy(DestPath, Cwd);\r
443 } else {\r
444 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, DestDir);\r
445 return (SHELL_INVALID_PARAMETER);\r
446 }\r
a405b86d 447 if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') {\r
448 StrCat(DestPath, L"\\");\r
449 } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') {\r
450 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;\r
451 }\r
452 StrCat(DestPath, DestDir);\r
453 if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') {\r
454 StrCat(DestPath, L"\\");\r
455 } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') {\r
456 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;\r
457 }\r
458 StrCat(DestPath, Node->FileName);\r
459\r
460 } else {\r
461 StrCpy(DestPath, DestDir);\r
462 if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') {\r
463 StrCat(DestPath, L"\\");\r
464 } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') {\r
465 ((CHAR16*)DestDir)[StrLen(DestDir)-1] = CHAR_NULL;\r
466 }\r
467 StrCat(DestPath, Node->FileName);\r
468 }\r
469 }\r
470\r
471 //\r
472 // Make sure the path exists\r
473 //\r
474 if (EFI_ERROR(VerifyIntermediateDirectories(DestPath))) {\r
475 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_WNF), gShellLevel2HiiHandle);\r
476 ShellStatus = SHELL_DEVICE_ERROR;\r
477 break;\r
478 }\r
479\r
480 if ( !EFI_ERROR(ShellIsDirectory(Node->FullName))\r
481 && !EFI_ERROR(ShellIsDirectory(DestPath))\r
482 && StrniCmp(Node->FullName, DestPath, StrLen(DestPath)) == NULL\r
f06be00e 483 ){\r
a405b86d 484 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_PARENT), gShellLevel2HiiHandle);\r
485 ShellStatus = SHELL_INVALID_PARAMETER;\r
486 break;\r
487 }\r
488 if (StringNoCaseCompare(&Node->FullName, &DestPath) == 0) {\r
489 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle);\r
490 ShellStatus = SHELL_INVALID_PARAMETER;\r
491 break;\r
492 }\r
493\r
5051c287 494 if ((StrniCmp(Node->FullName, DestPath, StrLen(Node->FullName)) == 0)\r
a405b86d 495 && (DestPath[StrLen(Node->FullName)] == CHAR_NULL || DestPath[StrLen(Node->FullName)] == L'\\')\r
f06be00e 496 ) {\r
a405b86d 497 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle);\r
498 ShellStatus = SHELL_INVALID_PARAMETER;\r
499 break;\r
500 }\r
501\r
ab94587a 502 PathCleanUpDirectories(DestPath);\r
a405b86d 503\r
a737ea73
JC
504 if (!SilentMode) {\r
505 ShellPrintEx(-1, -1, HiiOutput, Node->FullName, DestPath);\r
506 }\r
a405b86d 507\r
508 //\r
509 // copy single file...\r
510 //\r
511 ShellStatus = CopySingleFile(Node->FullName, DestPath, &Response, SilentMode);\r
512 if (ShellStatus != SHELL_SUCCESS) {\r
513 break;\r
514 }\r
515 }\r
516 if (ShellStatus == SHELL_SUCCESS && Resp == NULL) {\r
517 ShellPrintEx(-1, -1, L"%s", HiiResultOk);\r
518 }\r
519\r
520 SHELL_FREE_NON_NULL(DestPath);\r
521 SHELL_FREE_NON_NULL(HiiOutput);\r
522 SHELL_FREE_NON_NULL(HiiResultOk);\r
590c3cb1 523 if (Resp == NULL) {\r
a405b86d 524 SHELL_FREE_NON_NULL(Response);\r
525 }\r
526\r
527 return (ShellStatus);\r
f06be00e 528\r
a405b86d 529}\r
530\r
b54fd049 531/**\r
532 Validate and if successful copy all the files from the list into \r
533 destination directory.\r
534\r
535 @param[in] FileList The list of files to copy.\r
536 @param[in] DestDir The directory to copy files to.\r
537 @param[in] SilentMode TRUE to eliminate screen output.\r
538 @param[in] RecursiveMode TRUE to copy directories.\r
539\r
540 @retval SHELL_INVALID_PARAMETER A parameter was invalid.\r
541 @retval SHELL_SUCCESS The operation was successful.\r
542**/\r
a405b86d 543SHELL_STATUS\r
544EFIAPI\r
545ProcessValidateAndCopyFiles(\r
546 IN EFI_SHELL_FILE_INFO *FileList,\r
547 IN CONST CHAR16 *DestDir,\r
548 IN BOOLEAN SilentMode,\r
549 IN BOOLEAN RecursiveMode\r
550 )\r
551{\r
552 SHELL_STATUS ShellStatus;\r
553 EFI_SHELL_FILE_INFO *List;\r
a405b86d 554 EFI_FILE_INFO *FileInfo;\r
ac8783c8 555 CHAR16 *FullName;\r
a405b86d 556\r
ac8783c8
JC
557 List = NULL;\r
558 FullName = NULL;\r
9f56625f 559 FileInfo = NULL;\r
a405b86d 560\r
e755a4ca 561 ShellOpenFileMetaArg((CHAR16*)DestDir, EFI_FILE_MODE_READ, &List);\r
a405b86d 562 if (List != NULL && List->Link.ForwardLink != List->Link.BackLink) {\r
563 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, DestDir);\r
564 ShellStatus = SHELL_INVALID_PARAMETER;\r
565 ShellCloseFileMetaArg(&List);\r
566 } else if (List != NULL) {\r
a405b86d 567 ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink) != NULL);\r
568 ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName != NULL);\r
a405b86d 569 FileInfo = gEfiShellProtocol->GetFileInfo(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->Handle);\r
570 ASSERT(FileInfo != NULL);\r
ac8783c8
JC
571 StrnCatGrow(&FullName, NULL, ((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName, 0);\r
572 ShellCloseFileMetaArg(&List);\r
a405b86d 573 if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) == 0) {\r
ac8783c8 574 ShellStatus = ValidateAndCopyFiles(FileList, FullName, SilentMode, RecursiveMode, NULL);\r
a405b86d 575 } else {\r
576 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_ERROR), gShellLevel2HiiHandle);\r
577 ShellStatus = SHELL_ACCESS_DENIED;\r
578 }\r
a405b86d 579 } else {\r
ac8783c8 580 ShellCloseFileMetaArg(&List);\r
ed053afe 581 ShellStatus = ValidateAndCopyFiles(FileList, DestDir, SilentMode, RecursiveMode, NULL);\r
a405b86d 582 }\r
583\r
ac8783c8
JC
584 SHELL_FREE_NON_NULL(FileInfo);\r
585 SHELL_FREE_NON_NULL(FullName);\r
a405b86d 586 return (ShellStatus);\r
587}\r
588\r
589STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
590 {L"-r", TypeFlag},\r
591 {L"-q", TypeFlag},\r
592 {NULL, TypeMax}\r
593 };\r
594\r
595/**\r
596 Function for 'cp' command.\r
597\r
598 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
599 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
600**/\r
601SHELL_STATUS\r
602EFIAPI\r
603ShellCommandRunCp (\r
604 IN EFI_HANDLE ImageHandle,\r
605 IN EFI_SYSTEM_TABLE *SystemTable\r
606 )\r
607{\r
608 EFI_STATUS Status;\r
609 LIST_ENTRY *Package;\r
610 CHAR16 *ProblemParam;\r
611 SHELL_STATUS ShellStatus;\r
612 UINTN ParamCount;\r
613 UINTN LoopCounter;\r
614 EFI_SHELL_FILE_INFO *FileList;\r
615 BOOLEAN SilentMode;\r
616 BOOLEAN RecursiveMode;\r
617 CONST CHAR16 *Cwd;\r
618\r
619 ProblemParam = NULL;\r
620 ShellStatus = SHELL_SUCCESS;\r
621 ParamCount = 0;\r
622 FileList = NULL;\r
623\r
624 //\r
625 // initialize the shell lib (we must be in non-auto-init...)\r
626 //\r
627 Status = ShellInitialize();\r
628 ASSERT_EFI_ERROR(Status);\r
629\r
630 Status = CommandInit();\r
631 ASSERT_EFI_ERROR(Status);\r
632\r
633 //\r
634 // parse the command line\r
635 //\r
636 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
637 if (EFI_ERROR(Status)) {\r
638 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
639 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);\r
640 FreePool(ProblemParam);\r
641 ShellStatus = SHELL_INVALID_PARAMETER;\r
642 } else {\r
643 ASSERT(FALSE);\r
644 }\r
645 } else {\r
646 //\r
647 // check for "-?"\r
648 //\r
649 if (ShellCommandLineGetFlag(Package, L"-?")) {\r
650 ASSERT(FALSE);\r
651 }\r
652\r
653 //\r
654 // Initialize SilentMode and RecursiveMode\r
655 //\r
656 if (gEfiShellProtocol->BatchIsActive()) {\r
657 SilentMode = TRUE;\r
658 } else {\r
659 SilentMode = ShellCommandLineGetFlag(Package, L"-q");\r
660 }\r
661 RecursiveMode = ShellCommandLineGetFlag(Package, L"-r");\r
662\r
663 switch (ParamCount = ShellCommandLineGetCount(Package)) {\r
664 case 0:\r
665 case 1:\r
666 //\r
667 // we have insufficient parameters\r
668 //\r
669 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);\r
670 ShellStatus = SHELL_INVALID_PARAMETER;\r
671 break;\r
672 case 2:\r
673 //\r
674 // must have valid CWD for single parameter...\r
675 //\r
676 Cwd = ShellGetCurrentDir(NULL);\r
677 if (Cwd == NULL){\r
678 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);\r
679 ShellStatus = SHELL_INVALID_PARAMETER;\r
680 } else {\r
681 Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);\r
682 if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {\r
683 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));\r
684 ShellStatus = SHELL_NOT_FOUND;\r
685 } else {\r
686 ShellStatus = ProcessValidateAndCopyFiles(FileList, Cwd, SilentMode, RecursiveMode);\r
687 }\r
688 }\r
689\r
690 break;\r
691 default:\r
692 //\r
693 // Make a big list of all the files...\r
694 //\r
695 for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount && ShellStatus == SHELL_SUCCESS ; LoopCounter++) {\r
696 if (ShellGetExecutionBreakFlag()) {\r
697 break;\r
698 }\r
699 Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);\r
700 if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {\r
b2bf9735 701 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, LoopCounter));\r
a405b86d 702 ShellStatus = SHELL_NOT_FOUND;\r
703 }\r
704 }\r
b2bf9735 705 if (ShellStatus != SHELL_SUCCESS) {\r
a405b86d 706 Status = ShellCloseFileMetaArg(&FileList);\r
b2bf9735 707 } else {\r
708 //\r
709 // now copy them all...\r
710 //\r
711 if (FileList != NULL && !IsListEmpty(&FileList->Link)) {\r
ab94587a 712 ShellStatus = ProcessValidateAndCopyFiles(FileList, PathCleanUpDirectories((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount)), SilentMode, RecursiveMode);\r
b2bf9735 713 Status = ShellCloseFileMetaArg(&FileList);\r
714 if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {\r
715 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamCount), ShellStatus|MAX_BIT);\r
716 ShellStatus = SHELL_ACCESS_DENIED;\r
717 }\r
a405b86d 718 }\r
719 }\r
a405b86d 720 break;\r
721 } // switch on parameter count\r
722\r
723 if (FileList != NULL) {\r
724 ShellCloseFileMetaArg(&FileList);\r
725 }\r
726\r
727 //\r
728 // free the command line package\r
729 //\r
730 ShellCommandLineFreeVarList (Package);\r
731 }\r
732\r
733 if (ShellGetExecutionBreakFlag()) {\r
734 return (SHELL_ABORTED);\r
735 }\r
736\r
737 return (ShellStatus);\r
738}\r
739\r