]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c
Removed the assumption on APIC timer initial Count is all 1s and updated it to handle...
[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
54c9a68d 4 Copyright (c) 2009 - 2013, 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
134 return (SHELL_ACCESS_DENIED);\r
135 }\r
136\r
137 //\r
138 // Now copy all the files under the directory...\r
139 //\r
140 TempName = NULL;\r
f06be00e 141 Size = 0;\r
a405b86d 142 StrnCatGrow(&TempName, &Size, Source, 0);\r
143 StrnCatGrow(&TempName, &Size, L"\\*", 0);\r
7dd05623 144 if (TempName != NULL) {\r
145 ShellOpenFileMetaArg((CHAR16*)TempName, EFI_FILE_MODE_READ, &List);\r
146 *TempName = CHAR_NULL;\r
147 StrnCatGrow(&TempName, &Size, Dest, 0);\r
148 StrnCatGrow(&TempName, &Size, L"\\", 0);\r
149 ShellStatus = ValidateAndCopyFiles(List, TempName, SilentMode, TRUE, Resp);\r
150 ShellCloseFileMetaArg(&List);\r
151 SHELL_FREE_NON_NULL(TempName);\r
152 Size = 0;\r
153 }\r
a405b86d 154 } else {\r
ac8783c8 155 Status = ShellDeleteFileByName(Dest);\r
a405b86d 156\r
ac8783c8
JC
157 //\r
158 // open file with create enabled\r
159 //\r
160 Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);\r
161 if (EFI_ERROR(Status)) {\r
162 return (SHELL_ACCESS_DENIED);\r
163 }\r
f06be00e 164\r
ac8783c8
JC
165 //\r
166 // open source file\r
167 //\r
168 Status = ShellOpenFileByName(Source, &SourceHandle, EFI_FILE_MODE_READ, 0);\r
169 ASSERT_EFI_ERROR(Status);\r
f06be00e 170\r
ac8783c8
JC
171 //\r
172 //get file size of source file and freespace available on destination volume\r
173 //\r
174 ShellGetFileSize(SourceHandle, &SourceFileSize);\r
175 ShellGetFileSize(DestHandle, &DestFileSize);\r
f06be00e 176\r
ac8783c8
JC
177 //\r
178 //if the destination file already exists then it will be replaced, meaning the sourcefile effectively needs less storage space\r
179 //\r
180 if(DestFileSize < SourceFileSize){\r
181 SourceFileSize -= DestFileSize;\r
182 } else {\r
183 SourceFileSize = 0;\r
184 }\r
185\r
186 //\r
187 //get the system volume info to check the free space\r
188 //\r
189 DestVolumeFP = ConvertShellHandleToEfiFileProtocol(DestHandle);\r
190 DestVolumeInfo = NULL;\r
191 DestVolumeInfoSize = 0;\r
192 Status = DestVolumeFP->GetInfo(\r
193 DestVolumeFP,\r
194 &gEfiFileSystemInfoGuid,\r
195 &DestVolumeInfoSize,\r
196 DestVolumeInfo\r
197 );\r
198\r
199 if (Status == EFI_BUFFER_TOO_SMALL) {\r
200 DestVolumeInfo = AllocateZeroPool(DestVolumeInfoSize);\r
f06be00e 201 Status = DestVolumeFP->GetInfo(\r
202 DestVolumeFP,\r
203 &gEfiFileSystemInfoGuid,\r
204 &DestVolumeInfoSize,\r
205 DestVolumeInfo\r
206 );\r
ac8783c8 207 }\r
f06be00e 208\r
ac8783c8
JC
209 //\r
210 //check if enough space available on destination drive to complete copy\r
211 //\r
212 if (DestVolumeInfo!= NULL && (DestVolumeInfo->FreeSpace < SourceFileSize)) {\r
f06be00e 213 //\r
ac8783c8 214 //not enough space on destination directory to copy file\r
f06be00e 215 //\r
f06be00e 216 SHELL_FREE_NON_NULL(DestVolumeInfo);\r
ac8783c8
JC
217 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_FAIL), gShellLevel2HiiHandle);\r
218 return(SHELL_VOLUME_FULL);\r
219 } else {\r
220 //\r
221 // copy data between files\r
222 //\r
223 Buffer = AllocateZeroPool(ReadSize);\r
224 ASSERT(Buffer != NULL);\r
225 while (ReadSize == PcdGet32(PcdShellFileOperationSize) && !EFI_ERROR(Status)) {\r
226 Status = ShellReadFile(SourceHandle, &ReadSize, Buffer);\r
227 Status = ShellWriteFile(DestHandle, &ReadSize, Buffer);\r
228 }\r
a405b86d 229 }\r
ac8783c8
JC
230 SHELL_FREE_NON_NULL(DestVolumeInfo);\r
231 }\r
a405b86d 232\r
233 //\r
234 // close files\r
235 //\r
236 if (DestHandle != NULL) {\r
237 ShellCloseFile(&DestHandle);\r
238 DestHandle = NULL;\r
239 }\r
240 if (SourceHandle != NULL) {\r
241 ShellCloseFile(&SourceHandle);\r
242 SourceHandle = NULL;\r
243 }\r
244\r
245 //\r
246 // return\r
247 //\r
e755a4ca 248 return ShellStatus;\r
a405b86d 249}\r
250\r
251/**\r
252 function to take a list of files to copy and a destination location and do\r
253 the verification and copying of those files to that location. This function\r
254 will report any errors to the user and halt.\r
255\r
256 The key is to have this function called ONLY once. this allows for the parameter\r
257 verification to happen correctly.\r
258\r
b54fd049 259 @param[in] FileList A LIST_ENTRY* based list of files to move.\r
260 @param[in] DestDir The destination location.\r
261 @param[in] SilentMode TRUE to eliminate screen output.\r
262 @param[in] RecursiveMode TRUE to copy directories.\r
263 @param[in] Resp The response to the overwrite query (if always).\r
a405b86d 264\r
265 @retval SHELL_SUCCESS the files were all moved.\r
266 @retval SHELL_INVALID_PARAMETER a parameter was invalid\r
267 @retval SHELL_SECURITY_VIOLATION a security violation ocurred\r
268 @retval SHELL_WRITE_PROTECTED the destination was write protected\r
269 @retval SHELL_OUT_OF_RESOURCES a memory allocation failed\r
270**/\r
271SHELL_STATUS\r
272EFIAPI\r
273ValidateAndCopyFiles(\r
274 IN CONST EFI_SHELL_FILE_INFO *FileList,\r
275 IN CONST CHAR16 *DestDir,\r
276 IN BOOLEAN SilentMode,\r
277 IN BOOLEAN RecursiveMode,\r
278 IN VOID **Resp\r
279 )\r
280{\r
281 CHAR16 *HiiOutput;\r
282 CHAR16 *HiiResultOk;\r
283 CONST EFI_SHELL_FILE_INFO *Node;\r
284 SHELL_STATUS ShellStatus;\r
285 CHAR16 *DestPath;\r
286 VOID *Response;\r
287 UINTN PathLen;\r
288 CONST CHAR16 *Cwd;\r
289 CONST CHAR16 *TempLocation;\r
290 UINTN NewSize;\r
291\r
292 if (Resp == NULL) {\r
293 Response = NULL;\r
294 } else {\r
295 Response = *Resp;\r
296 }\r
297\r
298 DestPath = NULL;\r
299 ShellStatus = SHELL_SUCCESS;\r
300 PathLen = 0;\r
301 Cwd = ShellGetCurrentDir(NULL);\r
302\r
303 ASSERT(FileList != NULL);\r
304 ASSERT(DestDir != NULL);\r
305\r
306 //\r
307 // If we are trying to copy multiple files... make sure we got a directory for the target...\r
308 //\r
309 if (EFI_ERROR(ShellIsDirectory(DestDir)) && FileList->Link.ForwardLink != FileList->Link.BackLink) {\r
310 //\r
311 // Error for destination not a directory\r
312 //\r
313 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir);\r
314 return (SHELL_INVALID_PARAMETER);\r
315 }\r
316 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)\r
317 ; !IsNull(&FileList->Link, &Node->Link)\r
318 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)\r
f06be00e 319 ){\r
a405b86d 320 //\r
321 // skip the directory traversing stuff...\r
322 //\r
323 if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {\r
324 continue;\r
325 }\r
326\r
327 NewSize = StrSize(DestDir);\r
b54fd049 328 NewSize += StrSize(Node->FullName);\r
ed053afe 329 NewSize += (Cwd == NULL)? 0 : StrSize(Cwd);\r
a405b86d 330 if (NewSize > PathLen) {\r
331 PathLen = NewSize;\r
332 }\r
333\r
334 //\r
335 // Make sure got -r if required\r
336 //\r
337 if (!RecursiveMode && !EFI_ERROR(ShellIsDirectory(Node->FullName))) {\r
338 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_REQ), gShellLevel2HiiHandle);\r
339 return (SHELL_INVALID_PARAMETER);\r
340 }\r
341\r
342 //\r
343 // make sure got dest as dir if needed\r
344 //\r
345 if (!EFI_ERROR(ShellIsDirectory(Node->FullName)) && EFI_ERROR(ShellIsDirectory(DestDir))) {\r
346 //\r
347 // Error for destination not a directory\r
348 //\r
349 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, DestDir);\r
350 return (SHELL_INVALID_PARAMETER);\r
351 }\r
352 }\r
353\r
354 HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_CP_OUTPUT), NULL);\r
355 HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL);\r
b54fd049 356 DestPath = AllocateZeroPool(PathLen);\r
a405b86d 357\r
3e082d58 358 if (DestPath == NULL || HiiOutput == NULL || HiiResultOk == NULL) {\r
9ea69f8a 359 SHELL_FREE_NON_NULL(DestPath);\r
360 SHELL_FREE_NON_NULL(HiiOutput);\r
361 SHELL_FREE_NON_NULL(HiiResultOk);\r
362 return (SHELL_OUT_OF_RESOURCES);\r
363 }\r
364\r
a405b86d 365 //\r
366 // Go through the list of files to copy...\r
367 //\r
368 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)\r
369 ; !IsNull(&FileList->Link, &Node->Link)\r
370 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)\r
f06be00e 371 ){\r
a405b86d 372 if (ShellGetExecutionBreakFlag()) {\r
373 break;\r
374 }\r
375 ASSERT(Node->FileName != NULL);\r
376 ASSERT(Node->FullName != NULL);\r
377\r
378 //\r
379 // skip the directory traversing stuff...\r
380 //\r
381 if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {\r
382 continue;\r
383 }\r
384\r
385 if (FileList->Link.ForwardLink == FileList->Link.BackLink // 1 item\r
386 && EFI_ERROR(ShellIsDirectory(DestDir)) // not an existing directory\r
f06be00e 387 ) {\r
b54fd049 388 if (StrStr(DestDir, L":") == NULL) {\r
389 //\r
390 // simple copy of a single file\r
391 //\r
ed053afe
ED
392 if (Cwd != NULL) {\r
393 StrCpy(DestPath, Cwd);\r
394 } else {\r
395 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, DestDir);\r
396 return (SHELL_INVALID_PARAMETER);\r
397 }\r
b54fd049 398 if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') {\r
399 StrCat(DestPath, L"\\");\r
400 } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') {\r
401 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;\r
402 }\r
403 StrCat(DestPath, DestDir);\r
404 } else {\r
405 StrCpy(DestPath, DestDir);\r
a405b86d 406 }\r
a405b86d 407 } else {\r
408 //\r
409 // we have multiple files or a directory in the DestDir\r
410 //\r
1fc3749d 411 \r
412 //\r
413 // Check for leading slash\r
414 //\r
415 if (DestDir[0] == L'\\') {\r
ed053afe
ED
416 //\r
417 // Copy to the root of CWD\r
418 //\r
419 if (Cwd != NULL) {\r
420 StrCpy(DestPath, Cwd);\r
421 } else {\r
422 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, DestDir);\r
423 return (SHELL_INVALID_PARAMETER);\r
424 }\r
1fc3749d 425 while (PathRemoveLastItem(DestPath));\r
426 StrCat(DestPath, DestDir+1);\r
427 StrCat(DestPath, Node->FileName);\r
428 } else if (StrStr(DestDir, L":") == NULL) {\r
ed053afe
ED
429 if (Cwd != NULL) {\r
430 StrCpy(DestPath, Cwd);\r
431 } else {\r
432 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, DestDir);\r
433 return (SHELL_INVALID_PARAMETER);\r
434 }\r
a405b86d 435 if (DestPath[StrLen(DestPath)-1] != L'\\' && DestDir[0] != L'\\') {\r
436 StrCat(DestPath, L"\\");\r
437 } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestDir[0] == L'\\') {\r
438 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;\r
439 }\r
440 StrCat(DestPath, DestDir);\r
441 if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') {\r
442 StrCat(DestPath, L"\\");\r
443 } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') {\r
444 ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;\r
445 }\r
446 StrCat(DestPath, Node->FileName);\r
447\r
448 } else {\r
449 StrCpy(DestPath, DestDir);\r
450 if (DestDir[StrLen(DestDir)-1] != L'\\' && Node->FileName[0] != L'\\') {\r
451 StrCat(DestPath, L"\\");\r
452 } else if (DestDir[StrLen(DestDir)-1] == L'\\' && Node->FileName[0] == L'\\') {\r
453 ((CHAR16*)DestDir)[StrLen(DestDir)-1] = CHAR_NULL;\r
454 }\r
455 StrCat(DestPath, Node->FileName);\r
456 }\r
457 }\r
458\r
459 //\r
460 // Make sure the path exists\r
461 //\r
462 if (EFI_ERROR(VerifyIntermediateDirectories(DestPath))) {\r
463 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_WNF), gShellLevel2HiiHandle);\r
464 ShellStatus = SHELL_DEVICE_ERROR;\r
465 break;\r
466 }\r
467\r
468 if ( !EFI_ERROR(ShellIsDirectory(Node->FullName))\r
469 && !EFI_ERROR(ShellIsDirectory(DestPath))\r
470 && StrniCmp(Node->FullName, DestPath, StrLen(DestPath)) == NULL\r
f06be00e 471 ){\r
a405b86d 472 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_PARENT), gShellLevel2HiiHandle);\r
473 ShellStatus = SHELL_INVALID_PARAMETER;\r
474 break;\r
475 }\r
476 if (StringNoCaseCompare(&Node->FullName, &DestPath) == 0) {\r
477 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle);\r
478 ShellStatus = SHELL_INVALID_PARAMETER;\r
479 break;\r
480 }\r
481\r
482 if ((TempLocation = StrniCmp(Node->FullName, DestPath, StrLen(Node->FullName))) == 0\r
483 && (DestPath[StrLen(Node->FullName)] == CHAR_NULL || DestPath[StrLen(Node->FullName)] == L'\\')\r
f06be00e 484 ) {\r
a405b86d 485 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle);\r
486 ShellStatus = SHELL_INVALID_PARAMETER;\r
487 break;\r
488 }\r
489\r
ab94587a 490 PathCleanUpDirectories(DestPath);\r
a405b86d 491\r
492 ShellPrintEx(-1, -1, HiiOutput, Node->FullName, DestPath);\r
493\r
494 //\r
495 // copy single file...\r
496 //\r
497 ShellStatus = CopySingleFile(Node->FullName, DestPath, &Response, SilentMode);\r
498 if (ShellStatus != SHELL_SUCCESS) {\r
499 break;\r
500 }\r
501 }\r
502 if (ShellStatus == SHELL_SUCCESS && Resp == NULL) {\r
503 ShellPrintEx(-1, -1, L"%s", HiiResultOk);\r
504 }\r
505\r
506 SHELL_FREE_NON_NULL(DestPath);\r
507 SHELL_FREE_NON_NULL(HiiOutput);\r
508 SHELL_FREE_NON_NULL(HiiResultOk);\r
590c3cb1 509 if (Resp == NULL) {\r
a405b86d 510 SHELL_FREE_NON_NULL(Response);\r
511 }\r
512\r
513 return (ShellStatus);\r
f06be00e 514\r
a405b86d 515}\r
516\r
b54fd049 517/**\r
518 Validate and if successful copy all the files from the list into \r
519 destination directory.\r
520\r
521 @param[in] FileList The list of files to copy.\r
522 @param[in] DestDir The directory to copy files to.\r
523 @param[in] SilentMode TRUE to eliminate screen output.\r
524 @param[in] RecursiveMode TRUE to copy directories.\r
525\r
526 @retval SHELL_INVALID_PARAMETER A parameter was invalid.\r
527 @retval SHELL_SUCCESS The operation was successful.\r
528**/\r
a405b86d 529SHELL_STATUS\r
530EFIAPI\r
531ProcessValidateAndCopyFiles(\r
532 IN EFI_SHELL_FILE_INFO *FileList,\r
533 IN CONST CHAR16 *DestDir,\r
534 IN BOOLEAN SilentMode,\r
535 IN BOOLEAN RecursiveMode\r
536 )\r
537{\r
538 SHELL_STATUS ShellStatus;\r
539 EFI_SHELL_FILE_INFO *List;\r
a405b86d 540 EFI_FILE_INFO *FileInfo;\r
ac8783c8 541 CHAR16 *FullName;\r
a405b86d 542\r
ac8783c8
JC
543 List = NULL;\r
544 FullName = NULL;\r
9f56625f 545 FileInfo = NULL;\r
a405b86d 546\r
e755a4ca 547 ShellOpenFileMetaArg((CHAR16*)DestDir, EFI_FILE_MODE_READ, &List);\r
a405b86d 548 if (List != NULL && List->Link.ForwardLink != List->Link.BackLink) {\r
549 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, DestDir);\r
550 ShellStatus = SHELL_INVALID_PARAMETER;\r
551 ShellCloseFileMetaArg(&List);\r
552 } else if (List != NULL) {\r
a405b86d 553 ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink) != NULL);\r
554 ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName != NULL);\r
555 FileInfo = NULL;\r
556 FileInfo = gEfiShellProtocol->GetFileInfo(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->Handle);\r
557 ASSERT(FileInfo != NULL);\r
ac8783c8
JC
558 StrnCatGrow(&FullName, NULL, ((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName, 0);\r
559 ShellCloseFileMetaArg(&List);\r
a405b86d 560 if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) == 0) {\r
ac8783c8 561 ShellStatus = ValidateAndCopyFiles(FileList, FullName, SilentMode, RecursiveMode, NULL);\r
a405b86d 562 } else {\r
563 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_ERROR), gShellLevel2HiiHandle);\r
564 ShellStatus = SHELL_ACCESS_DENIED;\r
565 }\r
a405b86d 566 } else {\r
ac8783c8 567 ShellCloseFileMetaArg(&List);\r
ed053afe 568 ShellStatus = ValidateAndCopyFiles(FileList, DestDir, SilentMode, RecursiveMode, NULL);\r
a405b86d 569 }\r
570\r
ac8783c8
JC
571 SHELL_FREE_NON_NULL(FileInfo);\r
572 SHELL_FREE_NON_NULL(FullName);\r
a405b86d 573 return (ShellStatus);\r
574}\r
575\r
576STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
577 {L"-r", TypeFlag},\r
578 {L"-q", TypeFlag},\r
579 {NULL, TypeMax}\r
580 };\r
581\r
582/**\r
583 Function for 'cp' command.\r
584\r
585 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
586 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
587**/\r
588SHELL_STATUS\r
589EFIAPI\r
590ShellCommandRunCp (\r
591 IN EFI_HANDLE ImageHandle,\r
592 IN EFI_SYSTEM_TABLE *SystemTable\r
593 )\r
594{\r
595 EFI_STATUS Status;\r
596 LIST_ENTRY *Package;\r
597 CHAR16 *ProblemParam;\r
598 SHELL_STATUS ShellStatus;\r
599 UINTN ParamCount;\r
600 UINTN LoopCounter;\r
601 EFI_SHELL_FILE_INFO *FileList;\r
602 BOOLEAN SilentMode;\r
603 BOOLEAN RecursiveMode;\r
604 CONST CHAR16 *Cwd;\r
605\r
606 ProblemParam = NULL;\r
607 ShellStatus = SHELL_SUCCESS;\r
608 ParamCount = 0;\r
609 FileList = NULL;\r
610\r
611 //\r
612 // initialize the shell lib (we must be in non-auto-init...)\r
613 //\r
614 Status = ShellInitialize();\r
615 ASSERT_EFI_ERROR(Status);\r
616\r
617 Status = CommandInit();\r
618 ASSERT_EFI_ERROR(Status);\r
619\r
620 //\r
621 // parse the command line\r
622 //\r
623 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
624 if (EFI_ERROR(Status)) {\r
625 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
626 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);\r
627 FreePool(ProblemParam);\r
628 ShellStatus = SHELL_INVALID_PARAMETER;\r
629 } else {\r
630 ASSERT(FALSE);\r
631 }\r
632 } else {\r
633 //\r
634 // check for "-?"\r
635 //\r
636 if (ShellCommandLineGetFlag(Package, L"-?")) {\r
637 ASSERT(FALSE);\r
638 }\r
639\r
640 //\r
641 // Initialize SilentMode and RecursiveMode\r
642 //\r
643 if (gEfiShellProtocol->BatchIsActive()) {\r
644 SilentMode = TRUE;\r
645 } else {\r
646 SilentMode = ShellCommandLineGetFlag(Package, L"-q");\r
647 }\r
648 RecursiveMode = ShellCommandLineGetFlag(Package, L"-r");\r
649\r
650 switch (ParamCount = ShellCommandLineGetCount(Package)) {\r
651 case 0:\r
652 case 1:\r
653 //\r
654 // we have insufficient parameters\r
655 //\r
656 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle);\r
657 ShellStatus = SHELL_INVALID_PARAMETER;\r
658 break;\r
659 case 2:\r
660 //\r
661 // must have valid CWD for single parameter...\r
662 //\r
663 Cwd = ShellGetCurrentDir(NULL);\r
664 if (Cwd == NULL){\r
665 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);\r
666 ShellStatus = SHELL_INVALID_PARAMETER;\r
667 } else {\r
668 Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);\r
669 if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {\r
670 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));\r
671 ShellStatus = SHELL_NOT_FOUND;\r
672 } else {\r
673 ShellStatus = ProcessValidateAndCopyFiles(FileList, Cwd, SilentMode, RecursiveMode);\r
674 }\r
675 }\r
676\r
677 break;\r
678 default:\r
679 //\r
680 // Make a big list of all the files...\r
681 //\r
682 for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount && ShellStatus == SHELL_SUCCESS ; LoopCounter++) {\r
683 if (ShellGetExecutionBreakFlag()) {\r
684 break;\r
685 }\r
686 Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);\r
687 if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {\r
b2bf9735 688 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, LoopCounter));\r
a405b86d 689 ShellStatus = SHELL_NOT_FOUND;\r
690 }\r
691 }\r
b2bf9735 692 if (ShellStatus != SHELL_SUCCESS) {\r
a405b86d 693 Status = ShellCloseFileMetaArg(&FileList);\r
b2bf9735 694 } else {\r
695 //\r
696 // now copy them all...\r
697 //\r
698 if (FileList != NULL && !IsListEmpty(&FileList->Link)) {\r
ab94587a 699 ShellStatus = ProcessValidateAndCopyFiles(FileList, PathCleanUpDirectories((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount)), SilentMode, RecursiveMode);\r
b2bf9735 700 Status = ShellCloseFileMetaArg(&FileList);\r
701 if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {\r
702 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, ParamCount), ShellStatus|MAX_BIT);\r
703 ShellStatus = SHELL_ACCESS_DENIED;\r
704 }\r
a405b86d 705 }\r
706 }\r
a405b86d 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
720 if (ShellGetExecutionBreakFlag()) {\r
721 return (SHELL_ABORTED);\r
722 }\r
723\r
724 return (ShellStatus);\r
725}\r
726\r