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