windows-nt/Source/XPSP1/NT/base/efiutil/sdk/shell/ls/ls.c
2020-09-26 16:20:57 +08:00

337 lines
6.7 KiB
C

/*++
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"<DIR>" : 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");
}
}
}