]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c
ShellPkg/UefiShellLevel2CommandsLib: Remove unnecessary EFIAPI
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / Ls.c
CommitLineData
a405b86d 1/** @file\r
2 Main file for ls shell level 2 function.\r
3\r
c011b6c9 4 (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>\r
47ec9356 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#include <Guid/FileSystemInfo.h>\r
18\r
fed3be94
JC
19/**\r
20 print out the standard format output volume entry.\r
21\r
22 @param[in] TheList a list of files from the volume.\r
23**/\r
24EFI_STATUS\r
fed3be94
JC
25PrintSfoVolumeInfoTableEntry(\r
26 IN CONST EFI_SHELL_FILE_INFO *TheList\r
27 )\r
28{\r
29 EFI_STATUS Status;\r
30 EFI_SHELL_FILE_INFO *Node;\r
31 CHAR16 *DirectoryName;\r
32 EFI_FILE_SYSTEM_INFO *SysInfo;\r
33 UINTN SysInfoSize;\r
34 SHELL_FILE_HANDLE ShellFileHandle;\r
35 EFI_FILE_PROTOCOL *EfiFpHandle;\r
36\r
37 //\r
38 // Get the first valid handle (directories)\r
39 //\r
40 for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&TheList->Link)\r
41 ; !IsNull(&TheList->Link, &Node->Link) && Node->Handle == NULL\r
42 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&TheList->Link, &Node->Link)\r
43 );\r
44\r
45 if (Node->Handle == NULL) {\r
46 DirectoryName = GetFullyQualifiedPath(((EFI_SHELL_FILE_INFO *)GetFirstNode(&TheList->Link))->FullName);\r
47\r
48 //\r
49 // We need to open something up to get system information\r
50 //\r
51 Status = gEfiShellProtocol->OpenFileByName(\r
52 DirectoryName,\r
53 &ShellFileHandle,\r
54 EFI_FILE_MODE_READ\r
55 );\r
56\r
57 ASSERT_EFI_ERROR(Status);\r
58 FreePool(DirectoryName);\r
59\r
60 //\r
61 // Get the Volume Info from ShellFileHandle\r
62 //\r
63 SysInfo = NULL;\r
64 SysInfoSize = 0;\r
65 EfiFpHandle = ConvertShellHandleToEfiFileProtocol(ShellFileHandle);\r
66 Status = EfiFpHandle->GetInfo(\r
67 EfiFpHandle,\r
68 &gEfiFileSystemInfoGuid,\r
69 &SysInfoSize,\r
70 SysInfo\r
71 );\r
72\r
73 if (Status == EFI_BUFFER_TOO_SMALL) {\r
74 SysInfo = AllocateZeroPool(SysInfoSize);\r
75 Status = EfiFpHandle->GetInfo(\r
76 EfiFpHandle,\r
77 &gEfiFileSystemInfoGuid,\r
78 &SysInfoSize,\r
79 SysInfo\r
80 );\r
81 }\r
82\r
83 ASSERT_EFI_ERROR(Status);\r
84\r
85 gEfiShellProtocol->CloseFile(ShellFileHandle);\r
86 } else {\r
87 //\r
88 // Get the Volume Info from Node->Handle\r
89 //\r
90 SysInfo = NULL;\r
91 SysInfoSize = 0;\r
92 EfiFpHandle = ConvertShellHandleToEfiFileProtocol(Node->Handle);\r
93 Status = EfiFpHandle->GetInfo(\r
94 EfiFpHandle,\r
95 &gEfiFileSystemInfoGuid,\r
96 &SysInfoSize,\r
97 SysInfo\r
98 );\r
99\r
100 if (Status == EFI_BUFFER_TOO_SMALL) {\r
101 SysInfo = AllocateZeroPool(SysInfoSize);\r
102 Status = EfiFpHandle->GetInfo(\r
103 EfiFpHandle,\r
104 &gEfiFileSystemInfoGuid,\r
105 &SysInfoSize,\r
106 SysInfo\r
107 );\r
108 }\r
109\r
110 ASSERT_EFI_ERROR(Status);\r
111 }\r
112\r
113 ShellPrintHiiEx (\r
114 -1,\r
115 -1,\r
116 NULL,\r
117 STRING_TOKEN (STR_GEN_SFO_HEADER),\r
118 gShellLevel2HiiHandle,\r
119 L"ls"\r
120 );\r
121 //\r
122 // print VolumeInfo table\r
123 //\r
124 ASSERT(SysInfo != NULL);\r
125 ShellPrintHiiEx (\r
126 0,\r
127 gST->ConOut->Mode->CursorRow,\r
128 NULL,\r
129 STRING_TOKEN (STR_LS_SFO_VOLINFO),\r
130 gShellLevel2HiiHandle,\r
131 SysInfo->VolumeLabel,\r
132 SysInfo->VolumeSize,\r
133 SysInfo->ReadOnly?L"TRUE":L"FALSE",\r
134 SysInfo->FreeSpace,\r
135 SysInfo->BlockSize\r
136 );\r
137\r
138 SHELL_FREE_NON_NULL(SysInfo);\r
139\r
140 return (Status);\r
141}\r
142\r
143/**\r
144 print out the info on a single file.\r
145\r
146 @param[in] Sfo TRUE if in SFO, false otherwise.\r
147 @param[in] TheNode the EFI_SHELL_FILE_INFO node to print out information on.\r
148 @param[in] Files incremented if a file is printed.\r
149 @param[in] Size incremented by file size.\r
150 @param[in] Dirs incremented if a directory is printed.\r
151\r
152**/\r
153VOID\r
fed3be94
JC
154PrintFileInformation(\r
155 IN CONST BOOLEAN Sfo, \r
156 IN CONST EFI_SHELL_FILE_INFO *TheNode, \r
157 IN UINT64 *Files, \r
158 IN UINT64 *Size, \r
159 IN UINT64 *Dirs\r
160 )\r
161{\r
162 ASSERT(Files != NULL);\r
163 ASSERT(Size != NULL);\r
164 ASSERT(Dirs != NULL);\r
165 ASSERT(TheNode != NULL);\r
166\r
167 if (Sfo) {\r
168 //\r
169 // Print the FileInfo Table\r
170 //\r
171 ShellPrintHiiEx (\r
172 0,\r
173 gST->ConOut->Mode->CursorRow,\r
174 NULL,\r
175 STRING_TOKEN (STR_LS_SFO_FILEINFO),\r
176 gShellLevel2HiiHandle,\r
177 TheNode->FullName,\r
178 TheNode->Info->FileSize,\r
179 TheNode->Info->PhysicalSize,\r
180 (TheNode->Info->Attribute & EFI_FILE_ARCHIVE) != 0?L"a":L"",\r
181 (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"d":L"",\r
182 (TheNode->Info->Attribute & EFI_FILE_HIDDEN) != 0?L"h":L"",\r
183 (TheNode->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L"r":L"",\r
184 (TheNode->Info->Attribute & EFI_FILE_SYSTEM) != 0?L"s":L"",\r
185 TheNode->Info->CreateTime.Hour,\r
186 TheNode->Info->CreateTime.Minute,\r
187 TheNode->Info->CreateTime.Second,\r
188 TheNode->Info->CreateTime.Day,\r
189 TheNode->Info->CreateTime.Month,\r
190 TheNode->Info->CreateTime.Year,\r
191 TheNode->Info->LastAccessTime.Hour,\r
192 TheNode->Info->LastAccessTime.Minute,\r
193 TheNode->Info->LastAccessTime.Second,\r
194 TheNode->Info->LastAccessTime.Day,\r
195 TheNode->Info->LastAccessTime.Month,\r
196 TheNode->Info->LastAccessTime.Year,\r
197 TheNode->Info->ModificationTime.Hour,\r
198 TheNode->Info->ModificationTime.Minute,\r
199 TheNode->Info->ModificationTime.Second,\r
200 TheNode->Info->ModificationTime.Day,\r
201 TheNode->Info->ModificationTime.Month,\r
202 TheNode->Info->ModificationTime.Year\r
203 );\r
204 } else {\r
205 //\r
206 // print this one out...\r
207 // first print the universal start, next print the type specific name format, last print the CRLF\r
208 //\r
209 ShellPrintHiiEx (\r
210 -1,\r
211 -1,\r
212 NULL,\r
213 STRING_TOKEN (STR_LS_LINE_START_ALL),\r
214 gShellLevel2HiiHandle,\r
215 &TheNode->Info->ModificationTime,\r
216 (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"<DIR>":L"",\r
217 (TheNode->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L'r':L' ',\r
218 TheNode->Info->FileSize\r
219 );\r
220 if (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) {\r
221 (*Dirs)++;\r
222 ShellPrintHiiEx (\r
223 -1,\r
224 -1,\r
225 NULL,\r
226 STRING_TOKEN (STR_LS_LINE_END_DIR),\r
227 gShellLevel2HiiHandle,\r
228 TheNode->FileName\r
229 );\r
230 } else {\r
231 (*Files)++;\r
232 (*Size) += TheNode->Info->FileSize;\r
233 if ( (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".nsh", (CHAR16*)&(TheNode->FileName[StrLen (TheNode->FileName) - 4])) == 0)\r
234 || (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".efi", (CHAR16*)&(TheNode->FileName[StrLen (TheNode->FileName) - 4])) == 0)\r
235 ){\r
236 ShellPrintHiiEx (\r
237 -1,\r
238 -1,\r
239 NULL,\r
240 STRING_TOKEN (STR_LS_LINE_END_EXE),\r
241 gShellLevel2HiiHandle,\r
242 TheNode->FileName\r
243 );\r
244 } else {\r
245 ShellPrintHiiEx (\r
246 -1,\r
247 -1,\r
248 NULL,\r
249 STRING_TOKEN (STR_LS_LINE_END_FILE),\r
250 gShellLevel2HiiHandle,\r
251 TheNode->FileName\r
252 );\r
253 }\r
254 }\r
255 }\r
256}\r
257\r
258/**\r
259 print out the header when not using standard format output.\r
260\r
261 @param[in] Path String with starting path.\r
262**/\r
263VOID\r
fed3be94
JC
264PrintNonSfoHeader(\r
265 IN CONST CHAR16 *Path\r
266 )\r
267{\r
268 CHAR16 *DirectoryName;\r
269\r
270 //\r
271 // get directory name from path...\r
272 //\r
273 DirectoryName = GetFullyQualifiedPath(Path);\r
274\r
275 if (DirectoryName != NULL) {\r
276 //\r
277 // print header\r
278 //\r
279 ShellPrintHiiEx (\r
280 0,\r
281 gST->ConOut->Mode->CursorRow,\r
282 NULL,\r
283 STRING_TOKEN (STR_LS_HEADER_LINE1),\r
284 gShellLevel2HiiHandle,\r
285 DirectoryName\r
286 );\r
287\r
288 SHELL_FREE_NON_NULL(DirectoryName);\r
289 }\r
290}\r
291\r
292/**\r
293 print out the footer when not using standard format output.\r
294\r
7bc3ec3d
SQ
295 @param[in] Files The number of files.\r
296 @param[in] Size The size of files in bytes.\r
297 @param[in] Dirs The number of directories.\r
fed3be94
JC
298**/\r
299VOID\r
fed3be94
JC
300PrintNonSfoFooter(\r
301 IN UINT64 Files, \r
302 IN UINT64 Size, \r
303 IN UINT64 Dirs\r
304 )\r
305{\r
306 //\r
307 // print footer\r
308 //\r
309 ShellPrintHiiEx (\r
310 -1,\r
311 -1,\r
312 NULL,\r
313 STRING_TOKEN (STR_LS_FOOTER_LINE),\r
314 gShellLevel2HiiHandle,\r
315 Files,\r
316 Size,\r
317 Dirs\r
318 );\r
319}\r
320\r
a405b86d 321/**\r
322 print out the list of files and directories from the LS command\r
323\r
324 @param[in] Rec TRUE to automatically recurse into each found directory\r
325 FALSE to only list the specified directory.\r
326 @param[in] Attribs List of required Attribute for display.\r
327 If 0 then all non-system and non-hidden files will be printed.\r
328 @param[in] Sfo TRUE to use Standard Format Output, FALSE otherwise\r
929fb3be
JC
329 @param[in] RootPath String with starting path to search in.\r
330 @param[in] SearchString String with search string.\r
331 @param[in] Found Set to TRUE, if anyone were found.\r
a405b86d 332 @param[in] Count The count of bits enabled in Attribs.\r
333 @param[in] TimeZone The current time zone offset.\r
334\r
335 @retval SHELL_SUCCESS the printing was sucessful.\r
336**/\r
337SHELL_STATUS\r
a405b86d 338PrintLsOutput(\r
339 IN CONST BOOLEAN Rec,\r
340 IN CONST UINT64 Attribs,\r
341 IN CONST BOOLEAN Sfo,\r
929fb3be
JC
342 IN CONST CHAR16 *RootPath,\r
343 IN CONST CHAR16 *SearchString,\r
344 IN BOOLEAN *Found,\r
a405b86d 345 IN CONST UINTN Count,\r
346 IN CONST INT16 TimeZone\r
347 )\r
348{\r
349 EFI_STATUS Status;\r
350 EFI_SHELL_FILE_INFO *ListHead;\r
351 EFI_SHELL_FILE_INFO *Node;\r
352 SHELL_STATUS ShellStatus;\r
353 UINT64 FileCount;\r
354 UINT64 DirCount;\r
355 UINT64 FileSize;\r
a405b86d 356 UINTN LongestPath;\r
a405b86d 357 CHAR16 *CorrectedPath;\r
929fb3be
JC
358 BOOLEAN FoundOne;\r
359 BOOLEAN HeaderPrinted;\r
a405b86d 360\r
929fb3be 361 HeaderPrinted = FALSE;\r
a405b86d 362 FileCount = 0;\r
363 DirCount = 0;\r
364 FileSize = 0;\r
365 ListHead = NULL;\r
366 ShellStatus = SHELL_SUCCESS;\r
367 LongestPath = 0;\r
368 CorrectedPath = NULL;\r
369\r
929fb3be
JC
370 if (Found != NULL) {\r
371 FoundOne = *Found;\r
372 } else {\r
373 FoundOne = FALSE;\r
374 }\r
375\r
376 CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, RootPath, 0);\r
3a8406ad
SQ
377 if (CorrectedPath == NULL) {\r
378 return SHELL_OUT_OF_RESOURCES;\r
379 }\r
929fb3be
JC
380 if (CorrectedPath[StrLen(CorrectedPath)-1] != L'\\'\r
381 &&CorrectedPath[StrLen(CorrectedPath)-1] != L'/') {\r
382 CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, L"\\", 0);\r
383 }\r
384 CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, SearchString, 0);\r
74fa83fd 385 if (CorrectedPath == NULL) {\r
386 return (SHELL_OUT_OF_RESOURCES);\r
387 }\r
388\r
ab94587a 389 PathCleanUpDirectories(CorrectedPath);\r
a405b86d 390\r
391 Status = ShellOpenFileMetaArg((CHAR16*)CorrectedPath, EFI_FILE_MODE_READ, &ListHead);\r
929fb3be
JC
392 if (!EFI_ERROR(Status)) {\r
393 if (ListHead == NULL || IsListEmpty(&ListHead->Link)) {\r
394 SHELL_FREE_NON_NULL(CorrectedPath);\r
395 return (SHELL_SUCCESS);\r
74fa83fd 396 }\r
a405b86d 397\r
929fb3be
JC
398 if (Sfo && Found == NULL) {\r
399 PrintSfoVolumeInfoTableEntry(ListHead);\r
a405b86d 400 }\r
929fb3be
JC
401\r
402 for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link), LongestPath = 0\r
403 ; !IsNull(&ListHead->Link, &Node->Link)\r
404 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)\r
405 ){\r
8a3146d4
TS
406 if (ShellGetExecutionBreakFlag ()) {\r
407 ShellStatus = SHELL_ABORTED;\r
408 break;\r
409 }\r
929fb3be
JC
410 ASSERT(Node != NULL);\r
411 if (LongestPath < StrSize(Node->FullName)) {\r
412 LongestPath = StrSize(Node->FullName);\r
a405b86d 413 }\r
929fb3be
JC
414 ASSERT(Node->Info != NULL);\r
415 ASSERT((Node->Info->Attribute & EFI_FILE_VALID_ATTR) == Node->Info->Attribute);\r
416 if (Attribs == 0) {\r
417 //\r
418 // NOT system & NOT hidden\r
419 //\r
420 if ( (Node->Info->Attribute & EFI_FILE_SYSTEM)\r
421 || (Node->Info->Attribute & EFI_FILE_HIDDEN)\r
422 ){\r
423 continue;\r
424 }\r
425 } else if ((Attribs != EFI_FILE_VALID_ATTR) ||\r
426 (Count == 5)) {\r
427 //\r
428 // Only matches the bits which "Attribs" contains, not\r
429 // all files/directories with any of the bits.\r
430 // Count == 5 is used to tell the difference between a user\r
431 // specifying all bits (EX: -arhsda) and just specifying\r
432 // -a (means display all files with any attribute).\r
433 //\r
434 if ( (Node->Info->Attribute & Attribs) != Attribs) {\r
435 continue;\r
436 }\r
a405b86d 437 }\r
a405b86d 438\r
4f344fff 439 if (!Sfo && !HeaderPrinted) {\r
5aeafb3a 440 PathRemoveLastItem (CorrectedPath);\r
929fb3be
JC
441 PrintNonSfoHeader(CorrectedPath);\r
442 }\r
443 PrintFileInformation(Sfo, Node, &FileCount, &FileSize, &DirCount);\r
444 FoundOne = TRUE;\r
445 HeaderPrinted = TRUE;\r
446 }\r
a405b86d 447\r
8a3146d4 448 if (!Sfo && ShellStatus != SHELL_ABORTED) {\r
929fb3be
JC
449 PrintNonSfoFooter(FileCount, FileSize, DirCount);\r
450 }\r
a405b86d 451 }\r
452\r
8a3146d4 453 if (Rec && ShellStatus != SHELL_ABORTED) {\r
929fb3be
JC
454 //\r
455 // Re-Open all the files under the starting path for directories that didnt necessarily match our file filter\r
456 //\r
457 ShellCloseFileMetaArg(&ListHead);\r
458 CorrectedPath[0] = CHAR_NULL;\r
459 CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, RootPath, 0);\r
4f344fff
SQ
460 if (CorrectedPath == NULL) {\r
461 return SHELL_OUT_OF_RESOURCES;\r
462 }\r
929fb3be
JC
463 if (CorrectedPath[StrLen(CorrectedPath)-1] != L'\\'\r
464 &&CorrectedPath[StrLen(CorrectedPath)-1] != L'/') {\r
465 CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, L"\\", 0);\r
466 }\r
467 CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, L"*", 0);\r
468 Status = ShellOpenFileMetaArg((CHAR16*)CorrectedPath, EFI_FILE_MODE_READ, &ListHead);\r
469 \r
470 if (!EFI_ERROR(Status)) {\r
9ea69f8a 471 for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)\r
a7224eef 472 ; !IsNull(&ListHead->Link, &Node->Link) && ShellStatus == SHELL_SUCCESS\r
9ea69f8a 473 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)\r
474 ){\r
a7224eef 475 if (ShellGetExecutionBreakFlag ()) {\r
476 ShellStatus = SHELL_ABORTED;\r
477 break;\r
478 }\r
479\r
9ea69f8a 480 //\r
481 // recurse on any directory except the traversing ones...\r
482 //\r
483 if (((Node->Info->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY)\r
484 && StrCmp(Node->FileName, L".") != 0\r
485 && StrCmp(Node->FileName, L"..") != 0\r
486 ){\r
a7224eef 487 ShellStatus = PrintLsOutput(\r
9ea69f8a 488 Rec,\r
489 Attribs,\r
490 Sfo,\r
929fb3be
JC
491 Node->FullName,\r
492 SearchString,\r
493 &FoundOne,\r
9ea69f8a 494 Count,\r
495 TimeZone);\r
8a3146d4
TS
496 \r
497 //\r
498 // Since it's running recursively, we have to break immediately when returned SHELL_ABORTED\r
499 //\r
500 if (ShellStatus == SHELL_ABORTED) {\r
501 break;\r
502 }\r
9ea69f8a 503 }\r
a405b86d 504 }\r
505 }\r
a405b86d 506 }\r
507\r
929fb3be 508 SHELL_FREE_NON_NULL(CorrectedPath);\r
a405b86d 509 ShellCloseFileMetaArg(&ListHead);\r
929fb3be 510\r
4f344fff 511 if (Found == NULL && !FoundOne) {\r
929fb3be
JC
512 return (SHELL_NOT_FOUND);\r
513 }\r
514\r
515 if (Found != NULL) {\r
516 *Found = FoundOne;\r
517 }\r
518\r
a405b86d 519 return (ShellStatus);\r
520}\r
521\r
522STATIC CONST SHELL_PARAM_ITEM LsParamList[] = {\r
523 {L"-r", TypeFlag},\r
524 {L"-a", TypeStart},\r
525 {L"-sfo", TypeFlag},\r
526 {NULL, TypeMax}\r
527 };\r
528\r
529/**\r
530 Function for 'ls' command.\r
531\r
532 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
533 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
534**/\r
535SHELL_STATUS\r
536EFIAPI\r
537ShellCommandRunLs (\r
538 IN EFI_HANDLE ImageHandle,\r
539 IN EFI_SYSTEM_TABLE *SystemTable\r
540 )\r
541{\r
542 EFI_STATUS Status;\r
543 LIST_ENTRY *Package;\r
544 CHAR16 *ProblemParam;\r
545 CONST CHAR16 *Attribs;\r
546 SHELL_STATUS ShellStatus;\r
547 UINT64 RequiredAttributes;\r
548 CONST CHAR16 *PathName;\r
549 CONST CHAR16 *CurDir;\r
550 UINTN Count;\r
551 CHAR16 *FullPath;\r
552 UINTN Size;\r
b54fd049 553 EFI_TIME TheTime;\r
929fb3be 554 CHAR16 *SearchString;\r
a405b86d 555\r
556 Size = 0;\r
557 FullPath = NULL;\r
558 ProblemParam = NULL;\r
559 Attribs = NULL;\r
560 ShellStatus = SHELL_SUCCESS;\r
561 RequiredAttributes = 0;\r
562 PathName = NULL;\r
929fb3be 563 SearchString = NULL;\r
a405b86d 564 CurDir = NULL;\r
565 Count = 0;\r
566\r
567 //\r
568 // initialize the shell lib (we must be in non-auto-init...)\r
569 //\r
570 Status = ShellInitialize();\r
571 ASSERT_EFI_ERROR(Status);\r
572\r
573 //\r
574 // Fix local copies of the protocol pointers\r
575 //\r
576 Status = CommandInit();\r
577 ASSERT_EFI_ERROR(Status);\r
578\r
579 //\r
580 // parse the command line\r
581 //\r
582 Status = ShellCommandLineParse (LsParamList, &Package, &ProblemParam, TRUE);\r
583 if (EFI_ERROR(Status)) {\r
584 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
099e8ff5 585 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"ls", ProblemParam); \r
a405b86d 586 FreePool(ProblemParam);\r
587 ShellStatus = SHELL_INVALID_PARAMETER;\r
588 } else {\r
589 ASSERT(FALSE);\r
590 }\r
591 } else {\r
592 //\r
593 // check for "-?"\r
594 //\r
595 if (ShellCommandLineGetFlag(Package, L"-?")) {\r
596 ASSERT(FALSE);\r
597 }\r
598\r
599 if (ShellCommandLineGetCount(Package) > 2) {\r
099e8ff5 600 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"ls"); \r
a405b86d 601 ShellStatus = SHELL_INVALID_PARAMETER;\r
602 } else {\r
603 //\r
604 // check for -a\r
605 //\r
606 if (ShellCommandLineGetFlag(Package, L"-a")) {\r
607 for ( Attribs = ShellCommandLineGetValue(Package, L"-a")\r
608 ; Attribs != NULL && *Attribs != CHAR_NULL && ShellStatus == SHELL_SUCCESS\r
609 ; Attribs++\r
610 ){\r
611 switch (*Attribs) {\r
612 case L'a':\r
613 case L'A':\r
614 RequiredAttributes |= EFI_FILE_ARCHIVE;\r
615 Count++;\r
616 continue;\r
617 case L's':\r
618 case L'S':\r
619 RequiredAttributes |= EFI_FILE_SYSTEM;\r
620 Count++;\r
621 continue;\r
622 case L'h':\r
623 case L'H':\r
624 RequiredAttributes |= EFI_FILE_HIDDEN;\r
625 Count++;\r
626 continue;\r
627 case L'r':\r
628 case L'R':\r
629 RequiredAttributes |= EFI_FILE_READ_ONLY;\r
630 Count++;\r
631 continue;\r
632 case L'd':\r
633 case L'D':\r
634 RequiredAttributes |= EFI_FILE_DIRECTORY;\r
635 Count++;\r
636 continue;\r
637 default:\r
099e8ff5 638 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ATTRIBUTE), gShellLevel2HiiHandle, L"ls", ShellCommandLineGetValue(Package, L"-a")); \r
a405b86d 639 ShellStatus = SHELL_INVALID_PARAMETER;\r
640 break;\r
641 } // switch\r
642 } // for loop\r
643 //\r
644 // if nothing is specified all are specified\r
645 //\r
646 if (RequiredAttributes == 0) {\r
647 RequiredAttributes = EFI_FILE_VALID_ATTR;\r
648 }\r
649 } // if -a present\r
650 if (ShellStatus == SHELL_SUCCESS) {\r
651 PathName = ShellCommandLineGetRawValue(Package, 1);\r
652 if (PathName == NULL) {\r
929fb3be
JC
653 //\r
654 // Nothing specified... must start from current directory\r
655 //\r
a405b86d 656 CurDir = gEfiShellProtocol->GetCurDir(NULL);\r
657 if (CurDir == NULL) {\r
658 ShellStatus = SHELL_NOT_FOUND;\r
099e8ff5 659 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"ls"); \r
a405b86d 660 }\r
929fb3be
JC
661 //\r
662 // Copy to the 2 strings for starting path and file search string\r
663 //\r
664 ASSERT(SearchString == NULL);\r
665 ASSERT(FullPath == NULL);\r
666 StrnCatGrow(&SearchString, NULL, L"*", 0);\r
667 StrnCatGrow(&FullPath, NULL, CurDir, 0);\r
fbd2dfad
QS
668 Size = FullPath != NULL? StrSize(FullPath) : 0;\r
669 StrnCatGrow(&FullPath, &Size, L"\\", 0);\r
929fb3be 670 } else {\r
2ec013ce 671 if (StrStr(PathName, L":") == NULL && gEfiShellProtocol->GetCurDir(NULL) == NULL) {\r
929fb3be
JC
672 //\r
673 // If we got something and it doesnt have a fully qualified path, then we needed to have a CWD.\r
674 //\r
2ec013ce 675 ShellStatus = SHELL_NOT_FOUND;\r
099e8ff5 676 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"ls"); \r
2ec013ce 677 } else {\r
929fb3be
JC
678 //\r
679 // We got a valid fully qualified path or we have a CWD\r
680 //\r
2ec013ce 681 ASSERT((FullPath == NULL && Size == 0) || (FullPath != NULL));\r
929fb3be
JC
682 if (StrStr(PathName, L":") == NULL) {\r
683 StrnCatGrow(&FullPath, &Size, gEfiShellProtocol->GetCurDir(NULL), 0);\r
3a8406ad
SQ
684 if (FullPath == NULL) {\r
685 ShellCommandLineFreeVarList (Package);\r
686 return SHELL_OUT_OF_RESOURCES;\r
687 }\r
fbd2dfad
QS
688 Size = FullPath != NULL? StrSize(FullPath) : 0;\r
689 StrnCatGrow(&FullPath, &Size, L"\\", 0);\r
929fb3be 690 }\r
2ec013ce 691 StrnCatGrow(&FullPath, &Size, PathName, 0);\r
3a8406ad
SQ
692 if (FullPath == NULL) {\r
693 ShellCommandLineFreeVarList (Package);\r
694 return SHELL_OUT_OF_RESOURCES;\r
695 }\r
696 \r
2ec013ce 697 if (ShellIsDirectory(PathName) == EFI_SUCCESS) {\r
929fb3be
JC
698 //\r
699 // is listing ends with a directory, then we list all files in that directory\r
700 //\r
701 StrnCatGrow(&SearchString, NULL, L"*", 0);\r
702 } else {\r
703 //\r
704 // must split off the search part that applies to files from the end of the directory part\r
705 //\r
47ec9356 706 StrnCatGrow(&SearchString, NULL, FullPath, 0);\r
795c78cf
RN
707 if (SearchString == NULL) {\r
708 FreePool (FullPath);\r
709 ShellCommandLineFreeVarList (Package);\r
710 return SHELL_OUT_OF_RESOURCES;\r
711 }\r
47ec9356
RN
712 PathRemoveLastItem (FullPath);\r
713 CopyMem (SearchString, SearchString + StrLen (FullPath), StrSize (SearchString + StrLen (FullPath)));\r
2ec013ce 714 }\r
a405b86d 715 }\r
a405b86d 716 }\r
b54fd049 717 Status = gRT->GetTime(&TheTime, NULL);\r
2e8e9ed5 718 if (EFI_ERROR(Status)) {\r
099e8ff5 719 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"ls", L"gRT->GetTime", Status); \r
2e8e9ed5 720 TheTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
721 }\r
722\r
a405b86d 723 if (ShellStatus == SHELL_SUCCESS) {\r
724 ShellStatus = PrintLsOutput(\r
725 ShellCommandLineGetFlag(Package, L"-r"),\r
726 RequiredAttributes,\r
929fb3be 727 ShellCommandLineGetFlag(Package, L"-sfo"),\r
a405b86d 728 FullPath,\r
929fb3be
JC
729 SearchString,\r
730 NULL,\r
a405b86d 731 Count,\r
1a670f63 732 TheTime.TimeZone\r
a405b86d 733 );\r
734 if (ShellStatus == SHELL_NOT_FOUND) {\r
099e8ff5 735 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LS_FILE_NOT_FOUND), gShellLevel2HiiHandle, L"ls", FullPath); \r
a405b86d 736 } else if (ShellStatus == SHELL_INVALID_PARAMETER) {\r
099e8ff5 737 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"ls", FullPath); \r
a7224eef 738 } else if (ShellStatus == SHELL_ABORTED) {\r
739 //\r
740 // Ignore aborting.\r
741 //\r
a405b86d 742 } else if (ShellStatus != SHELL_SUCCESS) {\r
099e8ff5 743 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"ls", FullPath); \r
a405b86d 744 }\r
745 }\r
746 }\r
747 }\r
748 }\r
749\r
a405b86d 750 //\r
929fb3be 751 // Free memory allocated\r
a405b86d 752 //\r
929fb3be
JC
753 SHELL_FREE_NON_NULL(SearchString);\r
754 SHELL_FREE_NON_NULL(FullPath);\r
a405b86d 755 ShellCommandLineFreeVarList (Package);\r
756\r
757 return (ShellStatus);\r
758}\r