TianoCore EDK2 master
Loading...
Searching...
No Matches
Ls.c
Go to the documentation of this file.
1
11#include <Guid/FileSystemInfo.h>
12
13UINTN mDayOfMonth[] = { 31, 28, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30 };
14
23 )
24{
25 EFI_STATUS Status;
27 CHAR16 *DirectoryName;
28 EFI_FILE_SYSTEM_INFO *SysInfo;
29 UINTN SysInfoSize;
30 SHELL_FILE_HANDLE ShellFileHandle;
31 EFI_FILE_PROTOCOL *EfiFpHandle;
32
33 //
34 // Get the first valid handle (directories)
35 //
36 for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode (&TheList->Link)
37 ; !IsNull (&TheList->Link, &Node->Link) && Node->Handle == NULL
38 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode (&TheList->Link, &Node->Link)
39 )
40 {
41 }
42
43 if (Node->Handle == NULL) {
44 DirectoryName = GetFullyQualifiedPath (((EFI_SHELL_FILE_INFO *)GetFirstNode (&TheList->Link))->FullName);
45 if (DirectoryName == NULL) {
46 return (EFI_OUT_OF_RESOURCES);
47 }
48
49 //
50 // We need to open something up to get system information
51 //
52 Status = gEfiShellProtocol->OpenFileByName (
53 DirectoryName,
54 &ShellFileHandle,
55 EFI_FILE_MODE_READ
56 );
57
58 ASSERT_EFI_ERROR (Status);
59 FreePool (DirectoryName);
60
61 //
62 // Get the Volume Info from ShellFileHandle
63 //
64 SysInfo = NULL;
65 SysInfoSize = 0;
66 EfiFpHandle = ConvertShellHandleToEfiFileProtocol (ShellFileHandle);
67 Status = EfiFpHandle->GetInfo (
68 EfiFpHandle,
69 &gEfiFileSystemInfoGuid,
70 &SysInfoSize,
71 SysInfo
72 );
73
74 if (Status == EFI_BUFFER_TOO_SMALL) {
75 SysInfo = AllocateZeroPool (SysInfoSize);
76 if (SysInfo == NULL) {
77 gEfiShellProtocol->CloseFile (ShellFileHandle);
78 return (EFI_OUT_OF_RESOURCES);
79 }
80
81 Status = EfiFpHandle->GetInfo (
82 EfiFpHandle,
83 &gEfiFileSystemInfoGuid,
84 &SysInfoSize,
85 SysInfo
86 );
87 }
88
89 ASSERT_EFI_ERROR (Status);
90
91 gEfiShellProtocol->CloseFile (ShellFileHandle);
92 } else {
93 //
94 // Get the Volume Info from Node->Handle
95 //
96 SysInfo = NULL;
97 SysInfoSize = 0;
98 EfiFpHandle = ConvertShellHandleToEfiFileProtocol (Node->Handle);
99 Status = EfiFpHandle->GetInfo (
100 EfiFpHandle,
101 &gEfiFileSystemInfoGuid,
102 &SysInfoSize,
103 SysInfo
104 );
105
106 if (Status == EFI_BUFFER_TOO_SMALL) {
107 SysInfo = AllocateZeroPool (SysInfoSize);
108 if (SysInfo == NULL) {
109 return (EFI_OUT_OF_RESOURCES);
110 }
111
112 Status = EfiFpHandle->GetInfo (
113 EfiFpHandle,
114 &gEfiFileSystemInfoGuid,
115 &SysInfoSize,
116 SysInfo
117 );
118 }
119
120 ASSERT_EFI_ERROR (Status);
121 }
122
124 -1,
125 -1,
126 NULL,
127 STRING_TOKEN (STR_GEN_SFO_HEADER),
128 gShellLevel2HiiHandle,
129 L"ls"
130 );
131 //
132 // print VolumeInfo table
133 //
134 ASSERT (SysInfo != NULL);
136 0,
138 NULL,
139 STRING_TOKEN (STR_LS_SFO_VOLINFO),
140 gShellLevel2HiiHandle,
141 SysInfo->VolumeLabel,
142 SysInfo->VolumeSize,
143 SysInfo->ReadOnly ? L"TRUE" : L"FALSE",
144 SysInfo->FreeSpace,
145 SysInfo->BlockSize
146 );
147
148 SHELL_FREE_NON_NULL (SysInfo);
149
150 return (Status);
151}
152
163VOID
165 IN CONST BOOLEAN Sfo,
167 IN UINT64 *Files,
168 IN UINT64 *Size,
169 IN UINT64 *Dirs
170 )
171{
172 ASSERT (Files != NULL);
173 ASSERT (Size != NULL);
174 ASSERT (Dirs != NULL);
175 ASSERT (TheNode != NULL);
176
177 if (Sfo) {
178 //
179 // Print the FileInfo Table
180 //
182 0,
184 NULL,
185 STRING_TOKEN (STR_LS_SFO_FILEINFO),
186 gShellLevel2HiiHandle,
187 TheNode->FullName,
188 TheNode->Info->FileSize,
189 TheNode->Info->PhysicalSize,
190 (TheNode->Info->Attribute & EFI_FILE_ARCHIVE) != 0 ? L"a" : L"",
191 (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) != 0 ? L"d" : L"",
192 (TheNode->Info->Attribute & EFI_FILE_HIDDEN) != 0 ? L"h" : L"",
193 (TheNode->Info->Attribute & EFI_FILE_READ_ONLY) != 0 ? L"r" : L"",
194 (TheNode->Info->Attribute & EFI_FILE_SYSTEM) != 0 ? L"s" : L"",
195 TheNode->Info->CreateTime.Hour,
196 TheNode->Info->CreateTime.Minute,
197 TheNode->Info->CreateTime.Second,
198 TheNode->Info->CreateTime.Day,
199 TheNode->Info->CreateTime.Month,
200 TheNode->Info->CreateTime.Year,
201 TheNode->Info->LastAccessTime.Hour,
202 TheNode->Info->LastAccessTime.Minute,
203 TheNode->Info->LastAccessTime.Second,
204 TheNode->Info->LastAccessTime.Day,
205 TheNode->Info->LastAccessTime.Month,
206 TheNode->Info->LastAccessTime.Year,
207 TheNode->Info->ModificationTime.Hour,
208 TheNode->Info->ModificationTime.Minute,
209 TheNode->Info->ModificationTime.Second,
210 TheNode->Info->ModificationTime.Day,
211 TheNode->Info->ModificationTime.Month,
212 TheNode->Info->ModificationTime.Year
213 );
214 } else {
215 //
216 // print this one out...
217 // first print the universal start, next print the type specific name format, last print the CRLF
218 //
220 -1,
221 -1,
222 NULL,
223 STRING_TOKEN (STR_LS_LINE_START_ALL),
224 gShellLevel2HiiHandle,
225 &TheNode->Info->ModificationTime,
226 (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) != 0 ? L"<DIR>" : L"",
227 (TheNode->Info->Attribute & EFI_FILE_READ_ONLY) != 0 ? L'r' : L' ',
228 TheNode->Info->FileSize
229 );
230 if (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) {
231 (*Dirs)++;
233 -1,
234 -1,
235 NULL,
236 STRING_TOKEN (STR_LS_LINE_END_DIR),
237 gShellLevel2HiiHandle,
238 TheNode->FileName
239 );
240 } else {
241 (*Files)++;
242 (*Size) += TheNode->Info->FileSize;
243 if ( (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)L".nsh", (CHAR16 *)&(TheNode->FileName[StrLen (TheNode->FileName) - 4])) == 0)
244 || (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)L".efi", (CHAR16 *)&(TheNode->FileName[StrLen (TheNode->FileName) - 4])) == 0)
245 )
246 {
248 -1,
249 -1,
250 NULL,
251 STRING_TOKEN (STR_LS_LINE_END_EXE),
252 gShellLevel2HiiHandle,
253 TheNode->FileName
254 );
255 } else {
257 -1,
258 -1,
259 NULL,
260 STRING_TOKEN (STR_LS_LINE_END_FILE),
261 gShellLevel2HiiHandle,
262 TheNode->FileName
263 );
264 }
265 }
266 }
267}
268
274VOID
276 IN CONST CHAR16 *Path
277 )
278{
279 CHAR16 *DirectoryName;
280
281 //
282 // get directory name from path...
283 //
284 DirectoryName = GetFullyQualifiedPath (Path);
285
286 if (DirectoryName != NULL) {
287 //
288 // print header
289 //
291 0,
293 NULL,
294 STRING_TOKEN (STR_LS_HEADER_LINE1),
295 gShellLevel2HiiHandle,
296 DirectoryName
297 );
298
299 SHELL_FREE_NON_NULL (DirectoryName);
300 }
301}
302
310VOID
312 IN UINT64 Files,
313 IN UINT64 Size,
314 IN UINT64 Dirs
315 )
316{
317 //
318 // print footer
319 //
321 -1,
322 -1,
323 NULL,
324 STRING_TOKEN (STR_LS_FOOTER_LINE),
325 gShellLevel2HiiHandle,
326 Files,
327 Size,
328 Dirs
329 );
330}
331
338VOID
340 IN EFI_TIME *Time,
341 IN INT16 LocalTimeZone
342 )
343{
344 INTN MinuteDiff;
345 INTN TempMinute;
346 INTN HourNumberOfTempMinute;
347 INTN TempHour;
348 INTN DayNumberOfTempHour;
349 INTN TempDay;
350 INTN MonthNumberOfTempDay;
351 INTN TempMonth;
352 INTN YearNumberOfTempMonth;
353 INTN MonthRecord;
354
355 ASSERT ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440));
356 ASSERT ((LocalTimeZone >= -1440) && (LocalTimeZone <= 1440));
357 ASSERT ((Time->Month >= 1) && (Time->Month <= 12));
358
359 if (Time->TimeZone == LocalTimeZone) {
360 //
361 // if the file timezone is equal to the local timezone, there is no need to adjust the file time.
362 //
363 return;
364 }
365
366 if (((Time->Year % 4 == 0) && (Time->Year / 100 != 0)) || (Time->Year % 400 == 0)) {
367 //
368 // Day in February of leap year is 29.
369 //
370 mDayOfMonth[1] = 29;
371 }
372
373 MinuteDiff = Time->TimeZone - LocalTimeZone;
374 TempMinute = Time->Minute + MinuteDiff;
375
376 //
377 // Calculate Time->Minute
378 // TempHour will be used to calculate Time->Hour
379 //
380 HourNumberOfTempMinute = TempMinute / 60;
381 if (TempMinute < 0) {
382 HourNumberOfTempMinute--;
383 }
384
385 TempHour = Time->Hour + HourNumberOfTempMinute;
386 Time->Minute = (UINT8)(TempMinute - 60 * HourNumberOfTempMinute);
387
388 //
389 // Calculate Time->Hour
390 // TempDay will be used to calculate Time->Day
391 //
392 DayNumberOfTempHour = TempHour / 24;
393 if (TempHour < 0) {
394 DayNumberOfTempHour--;
395 }
396
397 TempDay = Time->Day + DayNumberOfTempHour;
398 Time->Hour = (UINT8)(TempHour - 24 * DayNumberOfTempHour);
399
400 //
401 // Calculate Time->Day
402 // TempMonth will be used to calculate Time->Month
403 //
404 MonthNumberOfTempDay = (TempDay - 1) / (INTN)mDayOfMonth[Time->Month - 1];
405 MonthRecord = (INTN)(Time->Month);
406 if (TempDay - 1 < 0) {
407 MonthNumberOfTempDay--;
408 MonthRecord--;
409 }
410
411 TempMonth = Time->Month + MonthNumberOfTempDay;
412 Time->Day = (UINT8)(TempDay - (INTN)mDayOfMonth[(MonthRecord - 1 + 12) % 12] * MonthNumberOfTempDay);
413
414 //
415 // Calculate Time->Month, Time->Year
416 //
417 YearNumberOfTempMonth = (TempMonth - 1) / 12;
418 if (TempMonth - 1 < 0) {
419 YearNumberOfTempMonth--;
420 }
421
422 Time->Month = (UINT8)(TempMonth - 12 * (YearNumberOfTempMonth));
423 Time->Year = (UINT16)(Time->Year + YearNumberOfTempMonth);
424}
425
446 IN CONST BOOLEAN Rec,
447 IN CONST UINT64 Attribs,
448 IN CONST BOOLEAN Sfo,
449 IN CONST CHAR16 *RootPath,
450 IN CONST CHAR16 *SearchString,
451 IN BOOLEAN *Found,
452 IN CONST UINTN Count,
453 IN CONST INT16 TimeZone,
454 IN CONST BOOLEAN ListUnfiltered
455 )
456{
457 EFI_STATUS Status;
458 EFI_SHELL_FILE_INFO *ListHead;
460 SHELL_STATUS ShellStatus;
461 UINT64 FileCount;
462 UINT64 DirCount;
463 UINT64 FileSize;
464 UINTN LongestPath;
465 CHAR16 *CorrectedPath;
466 BOOLEAN FoundOne;
467 BOOLEAN HeaderPrinted;
468 EFI_TIME LocalTime;
469
470 HeaderPrinted = FALSE;
471 FileCount = 0;
472 DirCount = 0;
473 FileSize = 0;
474 ListHead = NULL;
475 ShellStatus = SHELL_SUCCESS;
476 LongestPath = 0;
477 CorrectedPath = NULL;
478
479 if (Found != NULL) {
480 FoundOne = *Found;
481 } else {
482 FoundOne = FALSE;
483 }
484
485 CorrectedPath = StrnCatGrow (&CorrectedPath, &LongestPath, RootPath, 0);
486 if (CorrectedPath == NULL) {
488 }
489
490 if ( (CorrectedPath[StrLen (CorrectedPath)-1] != L'\\')
491 && (CorrectedPath[StrLen (CorrectedPath)-1] != L'/'))
492 {
493 CorrectedPath = StrnCatGrow (&CorrectedPath, &LongestPath, L"\\", 0);
494 }
495
496 CorrectedPath = StrnCatGrow (&CorrectedPath, &LongestPath, SearchString, 0);
497 if (CorrectedPath == NULL) {
498 return (SHELL_OUT_OF_RESOURCES);
499 }
500
501 PathCleanUpDirectories (CorrectedPath);
502
503 Status = ShellOpenFileMetaArg ((CHAR16 *)CorrectedPath, EFI_FILE_MODE_READ, &ListHead);
504 if (!EFI_ERROR (Status)) {
505 if ((ListHead == NULL) || IsListEmpty (&ListHead->Link)) {
506 SHELL_FREE_NON_NULL (CorrectedPath);
507 return (SHELL_SUCCESS);
508 }
509
510 if (Sfo && (Found == NULL)) {
512 }
513
514 if (!Sfo) {
515 //
516 // Sort the file list by FileName, stably.
517 //
518 // If the call below fails, then the EFI_SHELL_FILE_INFO list anchored to
519 // ListHead will not be changed in any way.
520 //
522 &ListHead,
523 NULL, // Duplicates
524 ShellSortFileListByFileName
525 );
526 }
527
528 for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode (&ListHead->Link), LongestPath = 0
529 ; !IsNull (&ListHead->Link, &Node->Link)
530 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode (&ListHead->Link, &Node->Link)
531 )
532 {
534 ShellStatus = SHELL_ABORTED;
535 break;
536 }
537
538 ASSERT (Node != NULL);
539
540 //
541 // Change the file time to local time.
542 //
543 Status = gRT->GetTime (&LocalTime, NULL);
544 if (!EFI_ERROR (Status) && (LocalTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE)) {
545 if ((Node->Info->CreateTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) &&
546 ((Node->Info->CreateTime.Month >= 1) && (Node->Info->CreateTime.Month <= 12)))
547 {
548 //
549 // FileTimeToLocalTime () requires Month is in a valid range, other buffer out-of-band access happens.
550 //
551 FileTimeToLocalTime (&Node->Info->CreateTime, LocalTime.TimeZone);
552 }
553
554 if ((Node->Info->LastAccessTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) &&
555 ((Node->Info->LastAccessTime.Month >= 1) && (Node->Info->LastAccessTime.Month <= 12)))
556 {
557 FileTimeToLocalTime (&Node->Info->LastAccessTime, LocalTime.TimeZone);
558 }
559
560 if ((Node->Info->ModificationTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) &&
561 ((Node->Info->ModificationTime.Month >= 1) && (Node->Info->ModificationTime.Month <= 12)))
562 {
563 FileTimeToLocalTime (&Node->Info->ModificationTime, LocalTime.TimeZone);
564 }
565 }
566
567 if (LongestPath < StrSize (Node->FullName)) {
568 LongestPath = StrSize (Node->FullName);
569 }
570
571 ASSERT (Node->Info != NULL);
572 ASSERT ((Node->Info->Attribute & EFI_FILE_VALID_ATTR) == Node->Info->Attribute);
573 if (Attribs == 0) {
574 //
575 // NOT system & NOT hidden
576 //
577 if ( (Node->Info->Attribute & EFI_FILE_SYSTEM)
578 || (Node->Info->Attribute & EFI_FILE_HIDDEN)
579 )
580 {
581 continue;
582 }
583 } else if ((Attribs != EFI_FILE_VALID_ATTR) ||
584 (Count == 5))
585 {
586 //
587 // Only matches the bits which "Attribs" contains, not
588 // all files/directories with any of the bits.
589 // Count == 5 is used to tell the difference between a user
590 // specifying all bits (EX: -arhsda) and just specifying
591 // -a (means display all files with any attribute).
592 //
593 if ((Node->Info->Attribute & Attribs) != Attribs) {
594 continue;
595 }
596 }
597
598 if (!Sfo && !HeaderPrinted) {
599 PathRemoveLastItem (CorrectedPath);
600 PrintNonSfoHeader (CorrectedPath);
601 }
602
603 PrintFileInformation (Sfo, Node, &FileCount, &FileSize, &DirCount);
604 FoundOne = TRUE;
605 HeaderPrinted = TRUE;
606 }
607
608 if (!Sfo && (ShellStatus != SHELL_ABORTED) && HeaderPrinted) {
609 PrintNonSfoFooter (FileCount, FileSize, DirCount);
610 }
611 }
612
613 if (Rec && (ShellStatus != SHELL_ABORTED)) {
614 //
615 // Re-Open all the files under the starting path for directories that didnt necessarily match our file filter
616 //
617 ShellCloseFileMetaArg (&ListHead);
618 CorrectedPath[0] = CHAR_NULL;
619 CorrectedPath = StrnCatGrow (&CorrectedPath, &LongestPath, RootPath, 0);
620 if (CorrectedPath == NULL) {
622 }
623
624 if ( (CorrectedPath[StrLen (CorrectedPath)-1] != L'\\')
625 && (CorrectedPath[StrLen (CorrectedPath)-1] != L'/'))
626 {
627 CorrectedPath = StrnCatGrow (&CorrectedPath, &LongestPath, L"\\", 0);
628 }
629
630 CorrectedPath = StrnCatGrow (&CorrectedPath, &LongestPath, L"*", 0);
631 if (CorrectedPath == NULL) {
633 }
634
635 Status = ShellOpenFileMetaArg ((CHAR16 *)CorrectedPath, EFI_FILE_MODE_READ, &ListHead);
636
637 if (!EFI_ERROR (Status)) {
638 for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode (&ListHead->Link)
639 ; !IsNull (&ListHead->Link, &Node->Link) && ShellStatus == SHELL_SUCCESS
640 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode (&ListHead->Link, &Node->Link)
641 )
642 {
644 ShellStatus = SHELL_ABORTED;
645 break;
646 }
647
648 //
649 // recurse on any directory except the traversing ones...
650 //
651 if ( ((Node->Info->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY)
652 && (StrCmp (Node->FileName, L".") != 0)
653 && (StrCmp (Node->FileName, L"..") != 0)
654 )
655 {
656 ShellStatus = PrintLsOutput (
657 Rec,
658 Attribs,
659 Sfo,
660 Node->FullName,
661 SearchString,
662 &FoundOne,
663 Count,
664 TimeZone,
665 FALSE
666 );
667
668 //
669 // Since it's running recursively, we have to break immediately when returned SHELL_ABORTED
670 //
671 if (ShellStatus == SHELL_ABORTED) {
672 break;
673 }
674 }
675 }
676 }
677 }
678
679 SHELL_FREE_NON_NULL (CorrectedPath);
680 ShellCloseFileMetaArg (&ListHead);
681
682 if ((Found == NULL) && !FoundOne) {
683 if (ListUnfiltered) {
684 //
685 // When running "ls" without any filtering request, avoid outputing
686 // "File not found" when the directory is entirely empty, but print
687 // header and footer stating "0 File(s), 0 Dir(s)".
688 //
689 if (!Sfo) {
690 PrintNonSfoHeader (RootPath);
691 if (ShellStatus != SHELL_ABORTED) {
692 PrintNonSfoFooter (FileCount, FileSize, DirCount);
693 }
694 }
695 } else {
696 return (SHELL_NOT_FOUND);
697 }
698 }
699
700 if (Found != NULL) {
701 *Found = FoundOne;
702 }
703
704 return (ShellStatus);
705}
706
707STATIC CONST SHELL_PARAM_ITEM LsParamList[] = {
708 { L"-r", TypeFlag },
709 { L"-a", TypeStart },
710 { L"-sfo", TypeFlag },
711 { NULL, TypeMax }
712};
713
721EFIAPI
723 IN EFI_HANDLE ImageHandle,
724 IN EFI_SYSTEM_TABLE *SystemTable
725 )
726{
727 EFI_STATUS Status;
728 LIST_ENTRY *Package;
729 CHAR16 *ProblemParam;
730 CONST CHAR16 *Attribs;
731 SHELL_STATUS ShellStatus;
732 UINT64 RequiredAttributes;
733 CONST CHAR16 *PathName;
734 CONST CHAR16 *CurDir;
735 UINTN Count;
736 CHAR16 *FullPath;
737 UINTN Size;
738 EFI_TIME TheTime;
739 CHAR16 *SearchString;
740 BOOLEAN ListUnfiltered;
741
742 Size = 0;
743 FullPath = NULL;
744 ProblemParam = NULL;
745 Attribs = NULL;
746 ShellStatus = SHELL_SUCCESS;
747 RequiredAttributes = 0;
748 PathName = NULL;
749 SearchString = NULL;
750 CurDir = NULL;
751 Count = 0;
752 ListUnfiltered = FALSE;
753
754 //
755 // initialize the shell lib (we must be in non-auto-init...)
756 //
757 Status = ShellInitialize ();
758 ASSERT_EFI_ERROR (Status);
759
760 //
761 // Fix local copies of the protocol pointers
762 //
763 Status = CommandInit ();
764 ASSERT_EFI_ERROR (Status);
765
766 //
767 // parse the command line
768 //
769 Status = ShellCommandLineParse (LsParamList, &Package, &ProblemParam, TRUE);
770 if (EFI_ERROR (Status)) {
771 if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
772 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"ls", ProblemParam);
773 FreePool (ProblemParam);
774 ShellStatus = SHELL_INVALID_PARAMETER;
775 } else {
776 ASSERT (FALSE);
777 }
778 } else {
779 //
780 // check for "-?"
781 //
782 if (ShellCommandLineGetFlag (Package, L"-?")) {
783 ASSERT (FALSE);
784 }
785
786 if (ShellCommandLineGetCount (Package) > 2) {
787 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"ls");
788 ShellStatus = SHELL_INVALID_PARAMETER;
789 } else {
790 //
791 // check for -a
792 //
793 if (ShellCommandLineGetFlag (Package, L"-a")) {
794 for ( Attribs = ShellCommandLineGetValue (Package, L"-a")
795 ; Attribs != NULL && *Attribs != CHAR_NULL && ShellStatus == SHELL_SUCCESS
796 ; Attribs++
797 )
798 {
799 switch (*Attribs) {
800 case L'a':
801 case L'A':
802 RequiredAttributes |= EFI_FILE_ARCHIVE;
803 Count++;
804 continue;
805 case L's':
806 case L'S':
807 RequiredAttributes |= EFI_FILE_SYSTEM;
808 Count++;
809 continue;
810 case L'h':
811 case L'H':
812 RequiredAttributes |= EFI_FILE_HIDDEN;
813 Count++;
814 continue;
815 case L'r':
816 case L'R':
817 RequiredAttributes |= EFI_FILE_READ_ONLY;
818 Count++;
819 continue;
820 case L'd':
821 case L'D':
822 RequiredAttributes |= EFI_FILE_DIRECTORY;
823 Count++;
824 continue;
825 default:
826 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ATTRIBUTE), gShellLevel2HiiHandle, L"ls", ShellCommandLineGetValue (Package, L"-a"));
827 ShellStatus = SHELL_INVALID_PARAMETER;
828 break;
829 } // switch
830 } // for loop
831
832 //
833 // if nothing is specified all are specified
834 //
835 if (RequiredAttributes == 0) {
836 RequiredAttributes = EFI_FILE_VALID_ATTR;
837 }
838 } // if -a present
839
840 if (ShellStatus == SHELL_SUCCESS) {
841 PathName = ShellCommandLineGetRawValue (Package, 1);
842 if (PathName == NULL) {
843 //
844 // Nothing specified... must start from current directory
845 //
846 CurDir = gEfiShellProtocol->GetCurDir (NULL);
847 if (CurDir == NULL) {
848 ShellStatus = SHELL_NOT_FOUND;
849 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"ls");
850 }
851
852 ListUnfiltered = TRUE;
853 //
854 // Copy to the 2 strings for starting path and file search string
855 //
856 ASSERT (SearchString == NULL);
857 ASSERT (FullPath == NULL);
858 StrnCatGrow (&SearchString, NULL, L"*", 0);
859 StrnCatGrow (&FullPath, NULL, CurDir, 0);
860 Size = FullPath != NULL ? StrSize (FullPath) : 0;
861 StrnCatGrow (&FullPath, &Size, L"\\", 0);
862 } else {
863 if ((StrStr (PathName, L":") == NULL) && (gEfiShellProtocol->GetCurDir (NULL) == NULL)) {
864 //
865 // If we got something and it doesnt have a fully qualified path, then we needed to have a CWD.
866 //
867 ShellStatus = SHELL_NOT_FOUND;
868 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"ls");
869 } else {
870 //
871 // We got a valid fully qualified path or we have a CWD
872 //
873 ASSERT ((FullPath == NULL && Size == 0) || (FullPath != NULL));
874 if (StrStr (PathName, L":") == NULL) {
875 StrnCatGrow (&FullPath, &Size, gEfiShellProtocol->GetCurDir (NULL), 0);
876 if (FullPath == NULL) {
879 }
880
881 Size = FullPath != NULL ? StrSize (FullPath) : 0;
882 StrnCatGrow (&FullPath, &Size, L"\\", 0);
883 }
884
885 StrnCatGrow (&FullPath, &Size, PathName, 0);
886 if (FullPath == NULL) {
889 }
890
891 if (ShellIsDirectory (PathName) == EFI_SUCCESS) {
892 //
893 // is listing ends with a directory, then we list all files in that directory
894 //
895 ListUnfiltered = TRUE;
896 StrnCatGrow (&SearchString, NULL, L"*", 0);
897 } else {
898 //
899 // must split off the search part that applies to files from the end of the directory part
900 //
901 StrnCatGrow (&SearchString, NULL, FullPath, 0);
902 if (SearchString == NULL) {
903 FreePool (FullPath);
906 }
907
908 PathRemoveLastItem (FullPath);
909 CopyMem (SearchString, SearchString + StrLen (FullPath), StrSize (SearchString + StrLen (FullPath)));
910 }
911 }
912 }
913
914 Status = gRT->GetTime (&TheTime, NULL);
915 if (EFI_ERROR (Status)) {
916 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"ls", L"gRT->GetTime", Status);
917 TheTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
918 }
919
920 if (ShellStatus == SHELL_SUCCESS) {
921 ShellStatus = PrintLsOutput (
922 ShellCommandLineGetFlag (Package, L"-r"),
923 RequiredAttributes,
924 ShellCommandLineGetFlag (Package, L"-sfo"),
925 FullPath,
926 SearchString,
927 NULL,
928 Count,
929 TheTime.TimeZone,
930 ListUnfiltered
931 );
932 if (ShellStatus == SHELL_NOT_FOUND) {
933 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_LS_FILE_NOT_FOUND), gShellLevel2HiiHandle, L"ls", FullPath);
934 } else if (ShellStatus == SHELL_INVALID_PARAMETER) {
935 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"ls", FullPath);
936 } else if (ShellStatus == SHELL_ABORTED) {
937 //
938 // Ignore aborting.
939 //
940 } else if (ShellStatus != SHELL_SUCCESS) {
941 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"ls", FullPath);
942 }
943 }
944 }
945 }
946 }
947
948 //
949 // Free memory allocated
950 //
951 SHELL_FREE_NON_NULL (SearchString);
952 SHELL_FREE_NON_NULL (FullPath);
954
955 return (ShellStatus);
956}
UINT64 UINTN
INT64 INTN
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
INTN EFIAPI StrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
Definition: String.c:109
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
CHAR16 *EFIAPI PathCleanUpDirectories(IN CHAR16 *Path)
Definition: FilePaths.c:68
BOOLEAN EFIAPI PathRemoveLastItem(IN OUT CHAR16 *Path)
Definition: FilePaths.c:22
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
CHAR16 *EFIAPI StrStr(IN CONST CHAR16 *String, IN CONST CHAR16 *SearchString)
Definition: String.c:224
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS PrintSfoVolumeInfoTableEntry(IN CONST EFI_SHELL_FILE_INFO *TheList)
Definition: Ls.c:21
VOID FileTimeToLocalTime(IN EFI_TIME *Time, IN INT16 LocalTimeZone)
Definition: Ls.c:339
VOID PrintNonSfoHeader(IN CONST CHAR16 *Path)
Definition: Ls.c:275
VOID PrintNonSfoFooter(IN UINT64 Files, IN UINT64 Size, IN UINT64 Dirs)
Definition: Ls.c:311
SHELL_STATUS PrintLsOutput(IN CONST BOOLEAN Rec, IN CONST UINT64 Attribs, IN CONST BOOLEAN Sfo, IN CONST CHAR16 *RootPath, IN CONST CHAR16 *SearchString, IN BOOLEAN *Found, IN CONST UINTN Count, IN CONST INT16 TimeZone, IN CONST BOOLEAN ListUnfiltered)
Definition: Ls.c:445
VOID PrintFileInformation(IN CONST BOOLEAN Sfo, IN CONST EFI_SHELL_FILE_INFO *TheNode, IN UINT64 *Files, IN UINT64 *Size, IN UINT64 *Dirs)
Definition: Ls.c:164
SHELL_STATUS EFIAPI ShellCommandRunLs(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: Ls.c:722
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
SHELL_STATUS
Definition: Shell.h:21
@ SHELL_OUT_OF_RESOURCES
Definition: Shell.h:73
@ SHELL_ABORTED
Definition: Shell.h:128
@ SHELL_SUCCESS
Definition: Shell.h:25
@ SHELL_NOT_FOUND
Definition: Shell.h:101
@ SHELL_INVALID_PARAMETER
Definition: Shell.h:35
EFI_STATUS EFIAPI CommandInit(VOID)
EFI_FILE_PROTOCOL *EFIAPI ConvertShellHandleToEfiFileProtocol(IN CONST SHELL_FILE_HANDLE Handle)
EFI_STATUS EFIAPI ShellSortFileList(IN OUT EFI_SHELL_FILE_INFO **FileList, OUT EFI_SHELL_FILE_INFO **Duplicates OPTIONAL, IN SHELL_SORT_FILE_LIST Order)
CONST CHAR16 *EFIAPI ShellCommandLineGetValue(IN CONST LIST_ENTRY *CheckPackage, IN CHAR16 *KeyString)
BOOLEAN EFIAPI ShellGetExecutionBreakFlag(VOID)
EFI_STATUS EFIAPI ShellCloseFileMetaArg(IN OUT EFI_SHELL_FILE_INFO **ListHead)
#define ShellCommandLineParse(CheckList, CheckPackage, ProblemParam, AutoPageBreak)
Make it easy to upgrade from older versions of the shell library.
Definition: ShellLib.h:755
EFI_STATUS EFIAPI ShellPrintHiiEx(IN INT32 Col OPTIONAL, IN INT32 Row OPTIONAL, IN CONST CHAR8 *Language OPTIONAL, IN CONST EFI_STRING_ID HiiFormatStringId, IN CONST EFI_HII_HANDLE HiiFormatHandle,...)
BOOLEAN EFIAPI ShellCommandLineGetFlag(IN CONST LIST_ENTRY *CONST CheckPackage, IN CONST CHAR16 *CONST KeyString)
@ TypeStart
A flag that has variable value appended to the end (IE "-ad", "-afd", "-adf", etc....
Definition: ShellLib.h:702
@ TypeFlag
A flag that is present or not present only (IE "-a").
Definition: ShellLib.h:699
CHAR16 *EFIAPI StrnCatGrow(IN OUT CHAR16 **Destination, IN OUT UINTN *CurrentSize, IN CONST CHAR16 *Source, IN UINTN Count)
EFI_STATUS EFIAPI ShellOpenFileMetaArg(IN CHAR16 *Arg, IN UINT64 OpenMode, IN OUT EFI_SHELL_FILE_INFO **ListHead)
VOID EFIAPI ShellCommandLineFreeVarList(IN LIST_ENTRY *CheckPackage)
EFI_STATUS EFIAPI ShellInitialize(VOID)
Definition: UefiShellLib.c:532
EFI_STATUS EFIAPI ShellIsDirectory(IN CONST CHAR16 *DirName)
CONST CHAR16 *EFIAPI ShellCommandLineGetRawValue(IN CONST LIST_ENTRY *CONST CheckPackage, IN UINTN Position)
UINTN EFIAPI ShellCommandLineGetCount(IN CONST LIST_ENTRY *CheckPackage)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_SYSTEM_TABLE * gST
#define STRING_TOKEN(t)
CHAR16 * GetFullyQualifiedPath(IN CONST CHAR16 *Path)
#define EFI_UNSPECIFIED_TIMEZONE
Definition: UefiSpec.h:58
EFI_SIMPLE_TEXT_OUTPUT_MODE * Mode
EFI_TIME ModificationTime
Definition: FileInfo.h:43
EFI_TIME CreateTime
Definition: FileInfo.h:35
UINT64 Attribute
Definition: FileInfo.h:47
EFI_TIME LastAccessTime
Definition: FileInfo.h:39
LIST_ENTRY Link
Linked list members.
Definition: Shell.h:153
SHELL_FILE_HANDLE Handle
Handle for interacting with the opened file or NULL if closed.
Definition: Shell.h:157
EFI_FILE_INFO * Info
Pointer to the FileInfo struct for this file or NULL.
Definition: Shell.h:158
CONST CHAR16 * FullName
Fully qualified filename.
Definition: Shell.h:155
CONST CHAR16 * FileName
name of this file.
Definition: Shell.h:156
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * ConOut
Definition: UefiSpec.h:2064