mirror of https://github.com/acidanthera/audk.git
ShellPkg: Add pipe support for parse command
parse reads data from StdIn when pipe is used and does not require –sfo output stored in a file. (e.g.: fs0:\> ls *.nsh –sfo | parse FileInfo 2) Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Tapan Shah <tapandshah@hp.com> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17555 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
c1993157bd
commit
421fbf99f8
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
Provides interface to shell internal functions for shell commands.
|
||||
|
||||
(C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.<BR>
|
||||
(C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
|
||||
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
|
@ -1622,7 +1622,6 @@ ShellFileHandleEof(
|
|||
|
||||
gEfiShellProtocol->GetFilePosition(Handle, &Pos);
|
||||
Info = gEfiShellProtocol->GetFileInfo (Handle);
|
||||
ASSERT(Info != NULL);
|
||||
gEfiShellProtocol->SetFilePosition(Handle, Pos);
|
||||
|
||||
if (Info == NULL) {
|
||||
|
|
|
@ -15,6 +15,179 @@
|
|||
|
||||
#include "UefiShellLevel2CommandsLib.h"
|
||||
|
||||
/**
|
||||
Check if data is coming from StdIn output.
|
||||
|
||||
@param[in] None
|
||||
|
||||
@retval TRUE StdIn stream data available to parse
|
||||
@retval FALSE StdIn stream data is not available to parse.
|
||||
**/
|
||||
BOOLEAN
|
||||
IsStdInDataAvailable (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
SHELL_FILE_HANDLE FileHandle;
|
||||
EFI_STATUS Status;
|
||||
CHAR16 CharBuffer;
|
||||
UINTN CharSize;
|
||||
UINT64 OriginalFilePosition;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
FileHandle = NULL;
|
||||
OriginalFilePosition = 0;
|
||||
|
||||
if (ShellOpenFileByName (L">i", &FileHandle, EFI_FILE_MODE_READ, 0) == EFI_SUCCESS) {
|
||||
CharSize = sizeof(CHAR16);
|
||||
gEfiShellProtocol->GetFilePosition (FileHandle, &OriginalFilePosition);
|
||||
Status = gEfiShellProtocol->ReadFile (FileHandle, &CharSize, &CharBuffer);
|
||||
if (EFI_ERROR (Status) || (CharSize != sizeof(CHAR16))) {
|
||||
return FALSE;
|
||||
}
|
||||
gEfiShellProtocol->SetFilePosition(FileHandle, OriginalFilePosition);
|
||||
}
|
||||
|
||||
if (FileHandle == NULL) {
|
||||
return FALSE;
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Function to read a single line (up to but not including the \n) using StdIn data from a SHELL_FILE_HANDLE.
|
||||
|
||||
If the position upon start is 0, then the Ascii Boolean will be set. This should be
|
||||
maintained and not changed for all operations with the same file.
|
||||
|
||||
@param[in] Handle SHELL_FILE_HANDLE to read from.
|
||||
@param[in, out] Buffer The pointer to buffer to read into.
|
||||
@param[in, out] Size The pointer to number of bytes in Buffer.
|
||||
@param[in] Truncate If the buffer is large enough, this has no effect.
|
||||
If the buffer is is too small and Truncate is TRUE,
|
||||
the line will be truncated.
|
||||
If the buffer is is too small and Truncate is FALSE,
|
||||
then no read will occur.
|
||||
|
||||
@retval EFI_SUCCESS The operation was successful. The line is stored in
|
||||
Buffer.
|
||||
@retval EFI_INVALID_PARAMETER Handle was NULL.
|
||||
@retval EFI_INVALID_PARAMETER Size was NULL.
|
||||
@retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line.
|
||||
Size was updated to the minimum space required.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ShellFileHandleReadStdInLine(
|
||||
IN SHELL_FILE_HANDLE Handle,
|
||||
IN OUT CHAR16 *Buffer,
|
||||
IN OUT UINTN *Size,
|
||||
IN BOOLEAN Truncate
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CHAR16 CharBuffer;
|
||||
UINTN CharSize;
|
||||
UINTN CountSoFar;
|
||||
UINT64 OriginalFilePosition;
|
||||
|
||||
|
||||
if (Handle == NULL
|
||||
||Size == NULL
|
||||
){
|
||||
return (EFI_INVALID_PARAMETER);
|
||||
}
|
||||
if (Buffer == NULL) {
|
||||
ASSERT(*Size == 0);
|
||||
} else {
|
||||
*Buffer = CHAR_NULL;
|
||||
}
|
||||
gEfiShellProtocol->GetFilePosition (Handle, &OriginalFilePosition);
|
||||
|
||||
for (CountSoFar = 0;;CountSoFar++){
|
||||
CharBuffer = 0;
|
||||
CharSize = sizeof(CHAR16);
|
||||
Status = gEfiShellProtocol->ReadFile (Handle, &CharSize, &CharBuffer);
|
||||
if ( EFI_ERROR(Status)
|
||||
|| CharSize == 0
|
||||
|| (CharBuffer == L'\n')
|
||||
){
|
||||
break;
|
||||
}
|
||||
//
|
||||
// if we have space save it...
|
||||
//
|
||||
if ((CountSoFar+1)*sizeof(CHAR16) < *Size){
|
||||
ASSERT(Buffer != NULL);
|
||||
((CHAR16*)Buffer)[CountSoFar] = CharBuffer;
|
||||
((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// if we ran out of space tell when...
|
||||
//
|
||||
if ((CountSoFar+1)*sizeof(CHAR16) > *Size){
|
||||
*Size = (CountSoFar+1)*sizeof(CHAR16);
|
||||
if (!Truncate) {
|
||||
gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);
|
||||
} else {
|
||||
DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine"));
|
||||
}
|
||||
return (EFI_BUFFER_TOO_SMALL);
|
||||
}
|
||||
while(Buffer[StrLen(Buffer)-1] == L'\r') {
|
||||
Buffer[StrLen(Buffer)-1] = CHAR_NULL;
|
||||
}
|
||||
|
||||
return (Status);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Function to read a single line using StdIn from a SHELL_FILE_HANDLE. The \n is not included in the returned
|
||||
buffer. The returned buffer must be callee freed.
|
||||
|
||||
If the position upon start is 0, then the Ascii Boolean will be set. This should be
|
||||
maintained and not changed for all operations with the same file.
|
||||
|
||||
@param[in] Handle SHELL_FILE_HANDLE to read from.
|
||||
|
||||
@return The line of text from the file.
|
||||
@retval NULL There was not enough memory available.
|
||||
|
||||
@sa ShellFileHandleReadLine
|
||||
**/
|
||||
CHAR16*
|
||||
EFIAPI
|
||||
ParseReturnStdInLine (
|
||||
IN SHELL_FILE_HANDLE Handle
|
||||
)
|
||||
{
|
||||
CHAR16 *RetVal;
|
||||
UINTN Size;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Size = 0;
|
||||
RetVal = NULL;
|
||||
|
||||
Status = ShellFileHandleReadStdInLine (Handle, RetVal, &Size, FALSE);
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
RetVal = AllocateZeroPool(Size);
|
||||
if (RetVal == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
Status = ShellFileHandleReadStdInLine (Handle, RetVal, &Size, FALSE);
|
||||
|
||||
}
|
||||
if (EFI_ERROR(Status) && (RetVal != NULL)) {
|
||||
FreePool(RetVal);
|
||||
RetVal = NULL;
|
||||
}
|
||||
return (RetVal);
|
||||
}
|
||||
|
||||
/**
|
||||
Do the actual parsing of the file. the file should be SFO output from a
|
||||
shell command or a similar format.
|
||||
|
@ -24,6 +197,7 @@
|
|||
@param[in] ColumnIndex The column number to get.
|
||||
@param[in] TableNameInstance Which instance of the table to get (row).
|
||||
@param[in] ShellCommandInstance Which instance of the command to get.
|
||||
@param[in] StreamingUnicode Indicates Input file is StdIn Unicode streaming data or not
|
||||
|
||||
@retval SHELL_NOT_FOUND The requested instance was not found.
|
||||
@retval SHELL_SUCCESS The operation was successful.
|
||||
|
@ -35,7 +209,8 @@ PerformParsing(
|
|||
IN CONST CHAR16 *TableName,
|
||||
IN CONST UINTN ColumnIndex,
|
||||
IN CONST UINTN TableNameInstance,
|
||||
IN CONST UINTN ShellCommandInstance
|
||||
IN CONST UINTN ShellCommandInstance,
|
||||
IN BOOLEAN StreamingUnicode
|
||||
)
|
||||
{
|
||||
SHELL_FILE_HANDLE FileHandle;
|
||||
|
@ -62,8 +237,13 @@ PerformParsing(
|
|||
ShellStatus = SHELL_NOT_FOUND;
|
||||
} else {
|
||||
for (LoopVariable = 0 ; LoopVariable < ShellCommandInstance && !ShellFileHandleEof(FileHandle);) {
|
||||
if (StreamingUnicode) {
|
||||
TempLine = ParseReturnStdInLine (FileHandle);
|
||||
} else {
|
||||
TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii);
|
||||
if (TempLine == NULL) {
|
||||
}
|
||||
|
||||
if ((TempLine == NULL) || (*TempLine == CHAR_NULL && StreamingUnicode == TRUE)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -80,7 +260,11 @@ PerformParsing(
|
|||
if (LoopVariable == ShellCommandInstance) {
|
||||
LoopVariable = 0;
|
||||
while(1) {
|
||||
if (StreamingUnicode) {
|
||||
TempLine = ParseReturnStdInLine (FileHandle);
|
||||
} else {
|
||||
TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii);
|
||||
}
|
||||
if (TempLine == NULL
|
||||
|| *TempLine == CHAR_NULL
|
||||
|| StrStr (TempLine, L"ShellCommand,") == TempLine) {
|
||||
|
@ -156,9 +340,11 @@ ShellCommandRunParse (
|
|||
SHELL_STATUS ShellStatus;
|
||||
UINTN ShellCommandInstance;
|
||||
UINTN TableNameInstance;
|
||||
BOOLEAN StreamingUnicode;
|
||||
|
||||
ShellStatus = SHELL_SUCCESS;
|
||||
ProblemParam = NULL;
|
||||
StreamingUnicode = FALSE;
|
||||
|
||||
//
|
||||
// initialize the shell lib (we must be in non-auto-init...)
|
||||
|
@ -169,7 +355,7 @@ ShellCommandRunParse (
|
|||
//
|
||||
// parse the command line
|
||||
//
|
||||
Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
|
||||
Status = ShellCommandLineParseEx (ParamList, &Package, &ProblemParam, TRUE, FALSE);
|
||||
if (EFI_ERROR(Status)) {
|
||||
if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"parse", ProblemParam);
|
||||
|
@ -179,17 +365,25 @@ ShellCommandRunParse (
|
|||
ASSERT(FALSE);
|
||||
}
|
||||
} else {
|
||||
if (ShellCommandLineGetCount(Package) < 4) {
|
||||
StreamingUnicode = IsStdInDataAvailable ();
|
||||
if ((!StreamingUnicode && (ShellCommandLineGetCount(Package) < 4)) ||
|
||||
(ShellCommandLineGetCount(Package) < 3)) {
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"parse");
|
||||
ShellStatus = SHELL_INVALID_PARAMETER;
|
||||
} else if (ShellCommandLineGetCount(Package) > 4) {
|
||||
} else if ((StreamingUnicode && (ShellCommandLineGetCount(Package) > 3)) ||
|
||||
(ShellCommandLineGetCount(Package) > 4)) {
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"parse");
|
||||
ShellStatus = SHELL_INVALID_PARAMETER;
|
||||
} else {
|
||||
if (StreamingUnicode) {
|
||||
FileName = L">i";
|
||||
TableName = ShellCommandLineGetRawValue(Package, 1);
|
||||
ColumnString = ShellCommandLineGetRawValue(Package, 2);
|
||||
} else {
|
||||
FileName = ShellCommandLineGetRawValue(Package, 1);
|
||||
TableName = ShellCommandLineGetRawValue(Package, 2);
|
||||
ColumnString = ShellCommandLineGetRawValue(Package, 3);
|
||||
|
||||
}
|
||||
if (ShellCommandLineGetValue(Package, L"-i") == NULL) {
|
||||
TableNameInstance = (UINTN)-1;
|
||||
} else {
|
||||
|
@ -201,7 +395,7 @@ ShellCommandRunParse (
|
|||
ShellCommandInstance = ShellStrToUintn(ShellCommandLineGetValue(Package, L"-s"));
|
||||
}
|
||||
|
||||
ShellStatus = PerformParsing(FileName, TableName, ShellStrToUintn(ColumnString), TableNameInstance, ShellCommandInstance);
|
||||
ShellStatus = PerformParsing(FileName, TableName, ShellStrToUintn(ColumnString), TableNameInstance, ShellCommandInstance, StreamingUnicode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue