2 Main file for ls shell level 2 function.
4 (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "UefiShellLevel2CommandsLib.h"
11 #include <Guid/FileSystemInfo.h>
13 UINTN mDayOfMonth
[] = { 31, 28, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30 };
16 print out the standard format output volume entry.
18 @param[in] TheList a list of files from the volume.
21 PrintSfoVolumeInfoTableEntry (
22 IN CONST EFI_SHELL_FILE_INFO
*TheList
26 EFI_SHELL_FILE_INFO
*Node
;
27 CHAR16
*DirectoryName
;
28 EFI_FILE_SYSTEM_INFO
*SysInfo
;
30 SHELL_FILE_HANDLE ShellFileHandle
;
31 EFI_FILE_PROTOCOL
*EfiFpHandle
;
34 // Get the first valid handle (directories)
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
)
43 if (Node
->Handle
== NULL
) {
44 DirectoryName
= GetFullyQualifiedPath (((EFI_SHELL_FILE_INFO
*)GetFirstNode (&TheList
->Link
))->FullName
);
47 // We need to open something up to get system information
49 Status
= gEfiShellProtocol
->OpenFileByName (
55 ASSERT_EFI_ERROR (Status
);
56 FreePool (DirectoryName
);
59 // Get the Volume Info from ShellFileHandle
63 EfiFpHandle
= ConvertShellHandleToEfiFileProtocol (ShellFileHandle
);
64 Status
= EfiFpHandle
->GetInfo (
66 &gEfiFileSystemInfoGuid
,
71 if (Status
== EFI_BUFFER_TOO_SMALL
) {
72 SysInfo
= AllocateZeroPool (SysInfoSize
);
73 Status
= EfiFpHandle
->GetInfo (
75 &gEfiFileSystemInfoGuid
,
81 ASSERT_EFI_ERROR (Status
);
83 gEfiShellProtocol
->CloseFile (ShellFileHandle
);
86 // Get the Volume Info from Node->Handle
90 EfiFpHandle
= ConvertShellHandleToEfiFileProtocol (Node
->Handle
);
91 Status
= EfiFpHandle
->GetInfo (
93 &gEfiFileSystemInfoGuid
,
98 if (Status
== EFI_BUFFER_TOO_SMALL
) {
99 SysInfo
= AllocateZeroPool (SysInfoSize
);
100 Status
= EfiFpHandle
->GetInfo (
102 &gEfiFileSystemInfoGuid
,
108 ASSERT_EFI_ERROR (Status
);
115 STRING_TOKEN (STR_GEN_SFO_HEADER
),
116 gShellLevel2HiiHandle
,
120 // print VolumeInfo table
122 ASSERT (SysInfo
!= NULL
);
125 gST
->ConOut
->Mode
->CursorRow
,
127 STRING_TOKEN (STR_LS_SFO_VOLINFO
),
128 gShellLevel2HiiHandle
,
129 SysInfo
->VolumeLabel
,
131 SysInfo
->ReadOnly
? L
"TRUE" : L
"FALSE",
136 SHELL_FREE_NON_NULL (SysInfo
);
142 print out the info on a single file.
144 @param[in] Sfo TRUE if in SFO, false otherwise.
145 @param[in] TheNode the EFI_SHELL_FILE_INFO node to print out information on.
146 @param[in] Files incremented if a file is printed.
147 @param[in] Size incremented by file size.
148 @param[in] Dirs incremented if a directory is printed.
152 PrintFileInformation (
153 IN CONST BOOLEAN Sfo
,
154 IN CONST EFI_SHELL_FILE_INFO
*TheNode
,
160 ASSERT (Files
!= NULL
);
161 ASSERT (Size
!= NULL
);
162 ASSERT (Dirs
!= NULL
);
163 ASSERT (TheNode
!= NULL
);
167 // Print the FileInfo Table
171 gST
->ConOut
->Mode
->CursorRow
,
173 STRING_TOKEN (STR_LS_SFO_FILEINFO
),
174 gShellLevel2HiiHandle
,
176 TheNode
->Info
->FileSize
,
177 TheNode
->Info
->PhysicalSize
,
178 (TheNode
->Info
->Attribute
& EFI_FILE_ARCHIVE
) != 0 ? L
"a" : L
"",
179 (TheNode
->Info
->Attribute
& EFI_FILE_DIRECTORY
) != 0 ? L
"d" : L
"",
180 (TheNode
->Info
->Attribute
& EFI_FILE_HIDDEN
) != 0 ? L
"h" : L
"",
181 (TheNode
->Info
->Attribute
& EFI_FILE_READ_ONLY
) != 0 ? L
"r" : L
"",
182 (TheNode
->Info
->Attribute
& EFI_FILE_SYSTEM
) != 0 ? L
"s" : L
"",
183 TheNode
->Info
->CreateTime
.Hour
,
184 TheNode
->Info
->CreateTime
.Minute
,
185 TheNode
->Info
->CreateTime
.Second
,
186 TheNode
->Info
->CreateTime
.Day
,
187 TheNode
->Info
->CreateTime
.Month
,
188 TheNode
->Info
->CreateTime
.Year
,
189 TheNode
->Info
->LastAccessTime
.Hour
,
190 TheNode
->Info
->LastAccessTime
.Minute
,
191 TheNode
->Info
->LastAccessTime
.Second
,
192 TheNode
->Info
->LastAccessTime
.Day
,
193 TheNode
->Info
->LastAccessTime
.Month
,
194 TheNode
->Info
->LastAccessTime
.Year
,
195 TheNode
->Info
->ModificationTime
.Hour
,
196 TheNode
->Info
->ModificationTime
.Minute
,
197 TheNode
->Info
->ModificationTime
.Second
,
198 TheNode
->Info
->ModificationTime
.Day
,
199 TheNode
->Info
->ModificationTime
.Month
,
200 TheNode
->Info
->ModificationTime
.Year
204 // print this one out...
205 // first print the universal start, next print the type specific name format, last print the CRLF
211 STRING_TOKEN (STR_LS_LINE_START_ALL
),
212 gShellLevel2HiiHandle
,
213 &TheNode
->Info
->ModificationTime
,
214 (TheNode
->Info
->Attribute
& EFI_FILE_DIRECTORY
) != 0 ? L
"<DIR>" : L
"",
215 (TheNode
->Info
->Attribute
& EFI_FILE_READ_ONLY
) != 0 ? L
'r' : L
' ',
216 TheNode
->Info
->FileSize
218 if (TheNode
->Info
->Attribute
& EFI_FILE_DIRECTORY
) {
224 STRING_TOKEN (STR_LS_LINE_END_DIR
),
225 gShellLevel2HiiHandle
,
230 (*Size
) += TheNode
->Info
->FileSize
;
231 if ( (gUnicodeCollation
->StriColl (gUnicodeCollation
, (CHAR16
*)L
".nsh", (CHAR16
*)&(TheNode
->FileName
[StrLen (TheNode
->FileName
) - 4])) == 0)
232 || (gUnicodeCollation
->StriColl (gUnicodeCollation
, (CHAR16
*)L
".efi", (CHAR16
*)&(TheNode
->FileName
[StrLen (TheNode
->FileName
) - 4])) == 0)
239 STRING_TOKEN (STR_LS_LINE_END_EXE
),
240 gShellLevel2HiiHandle
,
248 STRING_TOKEN (STR_LS_LINE_END_FILE
),
249 gShellLevel2HiiHandle
,
258 print out the header when not using standard format output.
260 @param[in] Path String with starting path.
264 IN CONST CHAR16
*Path
267 CHAR16
*DirectoryName
;
270 // get directory name from path...
272 DirectoryName
= GetFullyQualifiedPath (Path
);
274 if (DirectoryName
!= NULL
) {
280 gST
->ConOut
->Mode
->CursorRow
,
282 STRING_TOKEN (STR_LS_HEADER_LINE1
),
283 gShellLevel2HiiHandle
,
287 SHELL_FREE_NON_NULL (DirectoryName
);
292 print out the footer when not using standard format output.
294 @param[in] Files The number of files.
295 @param[in] Size The size of files in bytes.
296 @param[in] Dirs The number of directories.
312 STRING_TOKEN (STR_LS_FOOTER_LINE
),
313 gShellLevel2HiiHandle
,
321 Change the file time to local time based on the timezone.
323 @param[in] Time The file time.
324 @param[in] LocalTimeZone Local time zone.
327 FileTimeToLocalTime (
329 IN INT16 LocalTimeZone
334 INTN HourNumberOfTempMinute
;
336 INTN DayNumberOfTempHour
;
338 INTN MonthNumberOfTempDay
;
340 INTN YearNumberOfTempMonth
;
343 ASSERT ((Time
->TimeZone
>= -1440) && (Time
->TimeZone
<= 1440));
344 ASSERT ((LocalTimeZone
>= -1440) && (LocalTimeZone
<= 1440));
345 ASSERT ((Time
->Month
>= 1) && (Time
->Month
<= 12));
347 if (Time
->TimeZone
== LocalTimeZone
) {
349 // if the file timezone is equal to the local timezone, there is no need to adjust the file time.
354 if (((Time
->Year
% 4 == 0) && (Time
->Year
/ 100 != 0)) || (Time
->Year
% 400 == 0)) {
356 // Day in February of leap year is 29.
361 MinuteDiff
= Time
->TimeZone
- LocalTimeZone
;
362 TempMinute
= Time
->Minute
+ MinuteDiff
;
365 // Calculate Time->Minute
366 // TempHour will be used to calculate Time->Hour
368 HourNumberOfTempMinute
= TempMinute
/ 60;
369 if (TempMinute
< 0) {
370 HourNumberOfTempMinute
--;
373 TempHour
= Time
->Hour
+ HourNumberOfTempMinute
;
374 Time
->Minute
= (UINT8
)(TempMinute
- 60 * HourNumberOfTempMinute
);
377 // Calculate Time->Hour
378 // TempDay will be used to calculate Time->Day
380 DayNumberOfTempHour
= TempHour
/ 24;
382 DayNumberOfTempHour
--;
385 TempDay
= Time
->Day
+ DayNumberOfTempHour
;
386 Time
->Hour
= (UINT8
)(TempHour
- 24 * DayNumberOfTempHour
);
389 // Calculate Time->Day
390 // TempMonth will be used to calculate Time->Month
392 MonthNumberOfTempDay
= (TempDay
- 1) / (INTN
)mDayOfMonth
[Time
->Month
- 1];
393 MonthRecord
= (INTN
)(Time
->Month
);
394 if (TempDay
- 1 < 0) {
395 MonthNumberOfTempDay
--;
399 TempMonth
= Time
->Month
+ MonthNumberOfTempDay
;
400 Time
->Day
= (UINT8
)(TempDay
- (INTN
)mDayOfMonth
[(MonthRecord
- 1 + 12) % 12] * MonthNumberOfTempDay
);
403 // Calculate Time->Month, Time->Year
405 YearNumberOfTempMonth
= (TempMonth
- 1) / 12;
406 if (TempMonth
- 1 < 0) {
407 YearNumberOfTempMonth
--;
410 Time
->Month
= (UINT8
)(TempMonth
- 12 * (YearNumberOfTempMonth
));
411 Time
->Year
= (UINT16
)(Time
->Year
+ YearNumberOfTempMonth
);
415 print out the list of files and directories from the LS command
417 @param[in] Rec TRUE to automatically recurse into each found directory
418 FALSE to only list the specified directory.
419 @param[in] Attribs List of required Attribute for display.
420 If 0 then all non-system and non-hidden files will be printed.
421 @param[in] Sfo TRUE to use Standard Format Output, FALSE otherwise
422 @param[in] RootPath String with starting path to search in.
423 @param[in] SearchString String with search string.
424 @param[in] Found Set to TRUE, if anyone were found.
425 @param[in] Count The count of bits enabled in Attribs.
426 @param[in] TimeZone The current time zone offset.
427 @param[in] ListUnfiltered TRUE to request listing the directory contents
430 @retval SHELL_SUCCESS the printing was sucessful.
434 IN CONST BOOLEAN Rec
,
435 IN CONST UINT64 Attribs
,
436 IN CONST BOOLEAN Sfo
,
437 IN CONST CHAR16
*RootPath
,
438 IN CONST CHAR16
*SearchString
,
440 IN CONST UINTN Count
,
441 IN CONST INT16 TimeZone
,
442 IN CONST BOOLEAN ListUnfiltered
446 EFI_SHELL_FILE_INFO
*ListHead
;
447 EFI_SHELL_FILE_INFO
*Node
;
448 SHELL_STATUS ShellStatus
;
453 CHAR16
*CorrectedPath
;
455 BOOLEAN HeaderPrinted
;
458 HeaderPrinted
= FALSE
;
463 ShellStatus
= SHELL_SUCCESS
;
465 CorrectedPath
= NULL
;
473 CorrectedPath
= StrnCatGrow (&CorrectedPath
, &LongestPath
, RootPath
, 0);
474 if (CorrectedPath
== NULL
) {
475 return SHELL_OUT_OF_RESOURCES
;
478 if ( (CorrectedPath
[StrLen (CorrectedPath
)-1] != L
'\\')
479 && (CorrectedPath
[StrLen (CorrectedPath
)-1] != L
'/'))
481 CorrectedPath
= StrnCatGrow (&CorrectedPath
, &LongestPath
, L
"\\", 0);
484 CorrectedPath
= StrnCatGrow (&CorrectedPath
, &LongestPath
, SearchString
, 0);
485 if (CorrectedPath
== NULL
) {
486 return (SHELL_OUT_OF_RESOURCES
);
489 PathCleanUpDirectories (CorrectedPath
);
491 Status
= ShellOpenFileMetaArg ((CHAR16
*)CorrectedPath
, EFI_FILE_MODE_READ
, &ListHead
);
492 if (!EFI_ERROR (Status
)) {
493 if ((ListHead
== NULL
) || IsListEmpty (&ListHead
->Link
)) {
494 SHELL_FREE_NON_NULL (CorrectedPath
);
495 return (SHELL_SUCCESS
);
498 if (Sfo
&& (Found
== NULL
)) {
499 PrintSfoVolumeInfoTableEntry (ListHead
);
504 // Sort the file list by FileName, stably.
506 // If the call below fails, then the EFI_SHELL_FILE_INFO list anchored to
507 // ListHead will not be changed in any way.
512 ShellSortFileListByFileName
516 for ( Node
= (EFI_SHELL_FILE_INFO
*)GetFirstNode (&ListHead
->Link
), LongestPath
= 0
517 ; !IsNull (&ListHead
->Link
, &Node
->Link
)
518 ; Node
= (EFI_SHELL_FILE_INFO
*)GetNextNode (&ListHead
->Link
, &Node
->Link
)
521 if (ShellGetExecutionBreakFlag ()) {
522 ShellStatus
= SHELL_ABORTED
;
526 ASSERT (Node
!= NULL
);
529 // Change the file time to local time.
531 Status
= gRT
->GetTime (&LocalTime
, NULL
);
532 if (!EFI_ERROR (Status
) && (LocalTime
.TimeZone
!= EFI_UNSPECIFIED_TIMEZONE
)) {
533 if ((Node
->Info
->CreateTime
.TimeZone
!= EFI_UNSPECIFIED_TIMEZONE
) &&
534 ((Node
->Info
->CreateTime
.Month
>= 1) && (Node
->Info
->CreateTime
.Month
<= 12)))
537 // FileTimeToLocalTime () requires Month is in a valid range, other buffer out-of-band access happens.
539 FileTimeToLocalTime (&Node
->Info
->CreateTime
, LocalTime
.TimeZone
);
542 if ((Node
->Info
->LastAccessTime
.TimeZone
!= EFI_UNSPECIFIED_TIMEZONE
) &&
543 ((Node
->Info
->LastAccessTime
.Month
>= 1) && (Node
->Info
->LastAccessTime
.Month
<= 12)))
545 FileTimeToLocalTime (&Node
->Info
->LastAccessTime
, LocalTime
.TimeZone
);
548 if ((Node
->Info
->ModificationTime
.TimeZone
!= EFI_UNSPECIFIED_TIMEZONE
) &&
549 ((Node
->Info
->ModificationTime
.Month
>= 1) && (Node
->Info
->ModificationTime
.Month
<= 12)))
551 FileTimeToLocalTime (&Node
->Info
->ModificationTime
, LocalTime
.TimeZone
);
555 if (LongestPath
< StrSize (Node
->FullName
)) {
556 LongestPath
= StrSize (Node
->FullName
);
559 ASSERT (Node
->Info
!= NULL
);
560 ASSERT ((Node
->Info
->Attribute
& EFI_FILE_VALID_ATTR
) == Node
->Info
->Attribute
);
563 // NOT system & NOT hidden
565 if ( (Node
->Info
->Attribute
& EFI_FILE_SYSTEM
)
566 || (Node
->Info
->Attribute
& EFI_FILE_HIDDEN
)
571 } else if ((Attribs
!= EFI_FILE_VALID_ATTR
) ||
575 // Only matches the bits which "Attribs" contains, not
576 // all files/directories with any of the bits.
577 // Count == 5 is used to tell the difference between a user
578 // specifying all bits (EX: -arhsda) and just specifying
579 // -a (means display all files with any attribute).
581 if ((Node
->Info
->Attribute
& Attribs
) != Attribs
) {
586 if (!Sfo
&& !HeaderPrinted
) {
587 PathRemoveLastItem (CorrectedPath
);
588 PrintNonSfoHeader (CorrectedPath
);
591 PrintFileInformation (Sfo
, Node
, &FileCount
, &FileSize
, &DirCount
);
593 HeaderPrinted
= TRUE
;
596 if (!Sfo
&& (ShellStatus
!= SHELL_ABORTED
) && HeaderPrinted
) {
597 PrintNonSfoFooter (FileCount
, FileSize
, DirCount
);
601 if (Rec
&& (ShellStatus
!= SHELL_ABORTED
)) {
603 // Re-Open all the files under the starting path for directories that didnt necessarily match our file filter
605 ShellCloseFileMetaArg (&ListHead
);
606 CorrectedPath
[0] = CHAR_NULL
;
607 CorrectedPath
= StrnCatGrow (&CorrectedPath
, &LongestPath
, RootPath
, 0);
608 if (CorrectedPath
== NULL
) {
609 return SHELL_OUT_OF_RESOURCES
;
612 if ( (CorrectedPath
[StrLen (CorrectedPath
)-1] != L
'\\')
613 && (CorrectedPath
[StrLen (CorrectedPath
)-1] != L
'/'))
615 CorrectedPath
= StrnCatGrow (&CorrectedPath
, &LongestPath
, L
"\\", 0);
618 CorrectedPath
= StrnCatGrow (&CorrectedPath
, &LongestPath
, L
"*", 0);
619 Status
= ShellOpenFileMetaArg ((CHAR16
*)CorrectedPath
, EFI_FILE_MODE_READ
, &ListHead
);
621 if (!EFI_ERROR (Status
)) {
622 for ( Node
= (EFI_SHELL_FILE_INFO
*)GetFirstNode (&ListHead
->Link
)
623 ; !IsNull (&ListHead
->Link
, &Node
->Link
) && ShellStatus
== SHELL_SUCCESS
624 ; Node
= (EFI_SHELL_FILE_INFO
*)GetNextNode (&ListHead
->Link
, &Node
->Link
)
627 if (ShellGetExecutionBreakFlag ()) {
628 ShellStatus
= SHELL_ABORTED
;
633 // recurse on any directory except the traversing ones...
635 if ( ((Node
->Info
->Attribute
& EFI_FILE_DIRECTORY
) == EFI_FILE_DIRECTORY
)
636 && (StrCmp (Node
->FileName
, L
".") != 0)
637 && (StrCmp (Node
->FileName
, L
"..") != 0)
640 ShellStatus
= PrintLsOutput (
653 // Since it's running recursively, we have to break immediately when returned SHELL_ABORTED
655 if (ShellStatus
== SHELL_ABORTED
) {
663 SHELL_FREE_NON_NULL (CorrectedPath
);
664 ShellCloseFileMetaArg (&ListHead
);
666 if ((Found
== NULL
) && !FoundOne
) {
667 if (ListUnfiltered
) {
669 // When running "ls" without any filtering request, avoid outputing
670 // "File not found" when the directory is entirely empty, but print
671 // header and footer stating "0 File(s), 0 Dir(s)".
674 PrintNonSfoHeader (RootPath
);
675 if (ShellStatus
!= SHELL_ABORTED
) {
676 PrintNonSfoFooter (FileCount
, FileSize
, DirCount
);
680 return (SHELL_NOT_FOUND
);
688 return (ShellStatus
);
691 STATIC CONST SHELL_PARAM_ITEM LsParamList
[] = {
693 { L
"-a", TypeStart
},
694 { L
"-sfo", TypeFlag
},
699 Function for 'ls' command.
701 @param[in] ImageHandle Handle to the Image (NULL if Internal).
702 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
707 IN EFI_HANDLE ImageHandle
,
708 IN EFI_SYSTEM_TABLE
*SystemTable
713 CHAR16
*ProblemParam
;
714 CONST CHAR16
*Attribs
;
715 SHELL_STATUS ShellStatus
;
716 UINT64 RequiredAttributes
;
717 CONST CHAR16
*PathName
;
718 CONST CHAR16
*CurDir
;
723 CHAR16
*SearchString
;
724 BOOLEAN ListUnfiltered
;
730 ShellStatus
= SHELL_SUCCESS
;
731 RequiredAttributes
= 0;
736 ListUnfiltered
= FALSE
;
739 // initialize the shell lib (we must be in non-auto-init...)
741 Status
= ShellInitialize ();
742 ASSERT_EFI_ERROR (Status
);
745 // Fix local copies of the protocol pointers
747 Status
= CommandInit ();
748 ASSERT_EFI_ERROR (Status
);
751 // parse the command line
753 Status
= ShellCommandLineParse (LsParamList
, &Package
, &ProblemParam
, TRUE
);
754 if (EFI_ERROR (Status
)) {
755 if ((Status
== EFI_VOLUME_CORRUPTED
) && (ProblemParam
!= NULL
)) {
756 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PROBLEM
), gShellLevel2HiiHandle
, L
"ls", ProblemParam
);
757 FreePool (ProblemParam
);
758 ShellStatus
= SHELL_INVALID_PARAMETER
;
766 if (ShellCommandLineGetFlag (Package
, L
"-?")) {
770 if (ShellCommandLineGetCount (Package
) > 2) {
771 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_TOO_MANY
), gShellLevel2HiiHandle
, L
"ls");
772 ShellStatus
= SHELL_INVALID_PARAMETER
;
777 if (ShellCommandLineGetFlag (Package
, L
"-a")) {
778 for ( Attribs
= ShellCommandLineGetValue (Package
, L
"-a")
779 ; Attribs
!= NULL
&& *Attribs
!= CHAR_NULL
&& ShellStatus
== SHELL_SUCCESS
786 RequiredAttributes
|= EFI_FILE_ARCHIVE
;
791 RequiredAttributes
|= EFI_FILE_SYSTEM
;
796 RequiredAttributes
|= EFI_FILE_HIDDEN
;
801 RequiredAttributes
|= EFI_FILE_READ_ONLY
;
806 RequiredAttributes
|= EFI_FILE_DIRECTORY
;
810 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_ATTRIBUTE
), gShellLevel2HiiHandle
, L
"ls", ShellCommandLineGetValue (Package
, L
"-a"));
811 ShellStatus
= SHELL_INVALID_PARAMETER
;
817 // if nothing is specified all are specified
819 if (RequiredAttributes
== 0) {
820 RequiredAttributes
= EFI_FILE_VALID_ATTR
;
824 if (ShellStatus
== SHELL_SUCCESS
) {
825 PathName
= ShellCommandLineGetRawValue (Package
, 1);
826 if (PathName
== NULL
) {
828 // Nothing specified... must start from current directory
830 CurDir
= gEfiShellProtocol
->GetCurDir (NULL
);
831 if (CurDir
== NULL
) {
832 ShellStatus
= SHELL_NOT_FOUND
;
833 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_CWD
), gShellLevel2HiiHandle
, L
"ls");
836 ListUnfiltered
= TRUE
;
838 // Copy to the 2 strings for starting path and file search string
840 ASSERT (SearchString
== NULL
);
841 ASSERT (FullPath
== NULL
);
842 StrnCatGrow (&SearchString
, NULL
, L
"*", 0);
843 StrnCatGrow (&FullPath
, NULL
, CurDir
, 0);
844 Size
= FullPath
!= NULL
? StrSize (FullPath
) : 0;
845 StrnCatGrow (&FullPath
, &Size
, L
"\\", 0);
847 if ((StrStr (PathName
, L
":") == NULL
) && (gEfiShellProtocol
->GetCurDir (NULL
) == NULL
)) {
849 // If we got something and it doesnt have a fully qualified path, then we needed to have a CWD.
851 ShellStatus
= SHELL_NOT_FOUND
;
852 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_NO_CWD
), gShellLevel2HiiHandle
, L
"ls");
855 // We got a valid fully qualified path or we have a CWD
857 ASSERT ((FullPath
== NULL
&& Size
== 0) || (FullPath
!= NULL
));
858 if (StrStr (PathName
, L
":") == NULL
) {
859 StrnCatGrow (&FullPath
, &Size
, gEfiShellProtocol
->GetCurDir (NULL
), 0);
860 if (FullPath
== NULL
) {
861 ShellCommandLineFreeVarList (Package
);
862 return SHELL_OUT_OF_RESOURCES
;
865 Size
= FullPath
!= NULL
? StrSize (FullPath
) : 0;
866 StrnCatGrow (&FullPath
, &Size
, L
"\\", 0);
869 StrnCatGrow (&FullPath
, &Size
, PathName
, 0);
870 if (FullPath
== NULL
) {
871 ShellCommandLineFreeVarList (Package
);
872 return SHELL_OUT_OF_RESOURCES
;
875 if (ShellIsDirectory (PathName
) == EFI_SUCCESS
) {
877 // is listing ends with a directory, then we list all files in that directory
879 ListUnfiltered
= TRUE
;
880 StrnCatGrow (&SearchString
, NULL
, L
"*", 0);
883 // must split off the search part that applies to files from the end of the directory part
885 StrnCatGrow (&SearchString
, NULL
, FullPath
, 0);
886 if (SearchString
== NULL
) {
888 ShellCommandLineFreeVarList (Package
);
889 return SHELL_OUT_OF_RESOURCES
;
892 PathRemoveLastItem (FullPath
);
893 CopyMem (SearchString
, SearchString
+ StrLen (FullPath
), StrSize (SearchString
+ StrLen (FullPath
)));
898 Status
= gRT
->GetTime (&TheTime
, NULL
);
899 if (EFI_ERROR (Status
)) {
900 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN
), gShellLevel2HiiHandle
, L
"ls", L
"gRT->GetTime", Status
);
901 TheTime
.TimeZone
= EFI_UNSPECIFIED_TIMEZONE
;
904 if (ShellStatus
== SHELL_SUCCESS
) {
905 ShellStatus
= PrintLsOutput (
906 ShellCommandLineGetFlag (Package
, L
"-r"),
908 ShellCommandLineGetFlag (Package
, L
"-sfo"),
916 if (ShellStatus
== SHELL_NOT_FOUND
) {
917 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_LS_FILE_NOT_FOUND
), gShellLevel2HiiHandle
, L
"ls", FullPath
);
918 } else if (ShellStatus
== SHELL_INVALID_PARAMETER
) {
919 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellLevel2HiiHandle
, L
"ls", FullPath
);
920 } else if (ShellStatus
== SHELL_ABORTED
) {
924 } else if (ShellStatus
!= SHELL_SUCCESS
) {
925 ShellPrintHiiEx (-1, -1, NULL
, STRING_TOKEN (STR_GEN_PARAM_INV
), gShellLevel2HiiHandle
, L
"ls", FullPath
);
933 // Free memory allocated
935 SHELL_FREE_NON_NULL (SearchString
);
936 SHELL_FREE_NON_NULL (FullPath
);
937 ShellCommandLineFreeVarList (Package
);
939 return (ShellStatus
);