/*++ Copyright (c) 1998 Intel Corporation Module Name: ls.c Abstract: Shell app "ls" Revision History --*/ #include "shell.h" /* * */ EFI_STATUS InitializeLS ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ); VOID LsCurDir ( IN CHAR16 *CurDir ); VOID LsDir ( IN SHELL_FILE_ARG *Arg ); VOID LsDumpFileInfo ( IN EFI_FILE_INFO *Info ); /* * */ CHAR16 *LsLastDir; UINTN LsCount; UINTN LsDirs; UINTN LsFiles; UINT64 LsDirSize; UINT64 LsFileSize; UINTN LsTotalDirs; UINTN LsTotalFiles; UINT64 LsTotalDirSize; UINT64 LsTotalFileSize; BOOLEAN PageBreaks; UINTN TempColumn; UINTN ScreenCount; UINTN ScreenSize; /* * */ EFI_DRIVER_ENTRY_POINT(InitializeLS) EFI_STATUS InitializeLS ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { CHAR16 **Argv; UINTN Argc; CHAR16 *p; UINTN Index; LIST_ENTRY DirList; LIST_ENTRY *Link; SHELL_FILE_ARG *Arg; /* * Check to see if the app is to install as a "internal command" * to the shell */ InstallInternalShellCommand ( ImageHandle, SystemTable, InitializeLS, L"ls", /* command */ L"ls [-b] [dir] [dir] ...", /* command syntax */ L"Obtain directory listing", /* 1 line descriptor */ NULL /* command help page */ ); /* * We are no being installed as an internal command driver, initialize * as an nshell app and run */ InitializeShellApplication (ImageHandle, SystemTable); Argv = SI->Argv; Argc = SI->Argc; LsTotalDirs = 0; LsTotalFiles = 0; LsTotalDirSize = 0; LsTotalFileSize = 0; LsLastDir = NULL; LsCount = 0; InitializeListHead (&DirList); /* * Scan args for flags */ PageBreaks = FALSE; for (Index = 1; Index < Argc; Index += 1) { if (Argv[Index][0] == '-') { for (p = Argv[Index]+1; *p; p++) { switch (*p) { case 'b' : case 'B' : PageBreaks = TRUE; ST->ConOut->QueryMode (ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize); ScreenCount = 0; break; default: Print (L"ls: Unkown flag %s\n", Argv[Index]); goto Done; } } } } /* * Dir each directory indicated by the args */ for (Index = 1; Index < Argc; Index += 1) { if (Argv[Index][0] != '-') { ShellFileMetaArg (Argv[Index], &DirList); } } /* * If no directory arguments supplied, then dir the current directory */ if (IsListEmpty(&DirList)) { ShellFileMetaArg(L".", &DirList); } /* * Perform dir's on the directories */ for (Link=DirList.Flink; Link!=&DirList; Link=Link->Flink) { Arg = CR(Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE); LsDir (Arg); } /* * Dump final totals */ LsCurDir (NULL); if (LsCount > 1) { Print (L"\n Total %10,d File%c %12,ld bytes", LsTotalFiles, LsTotalFiles <= 1 ? ' ':'s', LsTotalFileSize ); Print (L"\n Total %10,d Dir%c %12,ld bytes\n\n", LsTotalDirs, LsTotalDirs <= 1 ? ' ':'s', LsTotalDirSize ); } Done: ShellFreeFileList (&DirList); return EFI_SUCCESS; } VOID LsCurDir ( IN CHAR16 *CurDir ) { if (!LsLastDir || !CurDir || StriCmp(LsLastDir, CurDir)) { if (LsLastDir) { Print (L"\n %10,d File%c %12,ld bytes", LsFiles, LsFiles <= 1 ? ' ':'s', LsFileSize ); Print (L"\n %10,d Dir%c %12,ld bytes\n\n", LsDirs, LsDirs <= 1 ? ' ':'s', LsTotalDirSize ); LsCount += 1; } LsDirs = 0; LsFiles = 0; LsDirSize = 0; LsFileSize = 0; LsLastDir = CurDir; if (CurDir) { Print (L"Directory of %hs\n", CurDir); } } } VOID LsDir ( IN SHELL_FILE_ARG *Arg ) { EFI_FILE_INFO *Info; UINTN BufferSize, bs; EFI_STATUS Status; Info = NULL; if (EFI_ERROR(Arg->Status)) { Print(L"ls: could not list file %hs - %r\n", Arg->FullName, Arg->Status); goto Done; } BufferSize = SIZE_OF_EFI_FILE_INFO + 1024; Info = AllocatePool (BufferSize); if (!Info) { goto Done; } if (Arg->Info->Attribute & EFI_FILE_DIRECTORY) { /* BUGBUG: dump volume info here */ LsCurDir (Arg->FullName); /* * Read all the file entries */ Arg->Handle->SetPosition (Arg->Handle, 0); for (; ;) { bs = BufferSize; Status = Arg->Handle->Read (Arg->Handle, &bs, Info); if (EFI_ERROR(Status)) { goto Done; } if (bs == 0) { break; } LsDumpFileInfo (Info); } } else { /* Dump the single file */ LsCurDir (Arg->ParentName); LsDumpFileInfo (Arg->Info); } Done: if (Info) { FreePool (Info); } } VOID LsDumpFileInfo ( IN EFI_FILE_INFO *Info ) { CHAR16 ReturnStr[1]; Print (L" %t %s %c %11,ld ", &Info->ModificationTime, Info->Attribute & EFI_FILE_DIRECTORY ? L"" : L" ", Info->Attribute & EFI_FILE_READ_ONLY ? 'r' : ' ', Info->FileSize, Info->FileName ); Print (L"%s\n", Info->FileName); if (Info->Attribute & EFI_FILE_DIRECTORY) { LsTotalDirs++; LsDirs++; LsTotalDirSize += Info->FileSize; LsDirSize += Info->FileSize; } else { LsTotalFiles++; LsFiles++; LsTotalFileSize += Info->FileSize; LsFileSize += Info->FileSize; } if (PageBreaks) { ScreenCount++; if (ScreenCount > ScreenSize - 4) { ScreenCount = 0; Print (L"\nPress Return to contiue :"); Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16)); Print (L"\n\n"); } } }