/** @file\r
Provides interface to shell functionality for shell commands and applications.\r
\r
+ Copyright 2016 Dell Inc.\r
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
EFI_STATUS Status;\r
EFI_FILE_INFO *FileInfo;\r
CHAR16 *FileNameCopy;\r
+ EFI_STATUS Status2;\r
\r
//\r
// ASSERT if FileName is NULL\r
}\r
PathCleanUpDirectories (FileNameCopy);\r
if (PathRemoveLastItem (FileNameCopy)) {\r
- ShellCreateDirectory (FileNameCopy, FileHandle);\r
- ShellCloseFile (FileHandle);\r
+ if (!EFI_ERROR(ShellCreateDirectory (FileNameCopy, FileHandle))) {\r
+ ShellCloseFile (FileHandle);\r
+ }\r
}\r
SHELL_FREE_NON_NULL (FileNameCopy);\r
}\r
FileInfo = FileFunctionMap.GetFileInfo(*FileHandle);\r
ASSERT(FileInfo != NULL);\r
FileInfo->Attribute = Attributes;\r
- Status = FileFunctionMap.SetFileInfo(*FileHandle, FileInfo);\r
+ Status2 = FileFunctionMap.SetFileInfo(*FileHandle, FileInfo);\r
FreePool(FileInfo);\r
+ if (EFI_ERROR (Status2)) {\r
+ gEfiShellProtocol->CloseFile(*FileHandle);\r
+ }\r
+ Status = Status2;\r
}\r
return (Status);\r
}\r
name. If the DeviceName is not NULL, it returns the current directory name\r
on specified drive.\r
\r
+ Note that the current directory string should exclude the tailing backslash character.\r
+\r
@param DeviceName the name of the drive to get directory on\r
\r
@retval NULL the directory does not exist\r
\r
Path = ShellGetEnvironmentVariable(L"cwd");\r
if (Path != NULL) {\r
- Size = StrSize(Path);\r
+ Size = StrSize(Path) + sizeof(CHAR16);\r
Size += StrSize(FileName);\r
TestPath = AllocateZeroPool(Size);\r
if (TestPath == NULL) {\r
return (NULL);\r
}\r
StrCpyS(TestPath, Size/sizeof(CHAR16), Path);\r
+ StrCatS(TestPath, Size/sizeof(CHAR16), L"\\");\r
StrCatS(TestPath, Size/sizeof(CHAR16), FileName);\r
Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);\r
if (!EFI_ERROR(Status)){\r
}\r
\r
/**\r
- Determins if a parameter is duplicated.\r
+ Determines if a parameter is duplicated.\r
\r
If Param is not NULL then it will point to a callee allocated string buffer\r
with the parameter value if a duplicate is found.\r
*CurrentSize = NewSize;\r
}\r
} else {\r
- *Destination = AllocateZeroPool((Count+1)*sizeof(CHAR16));\r
+ NewSize = (Count+1)*sizeof(CHAR16);\r
+ *Destination = AllocateZeroPool(NewSize);\r
}\r
\r
//\r
return (NULL);\r
}\r
\r
- StrCatS(*Destination, Count + 1, Source);\r
+ StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, Count);\r
return *Destination;\r
}\r
\r
/**\r
Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64.\r
\r
- This function returns a value of type UINTN by interpreting the contents\r
+ This function returns a value of type UINT64 by interpreting the contents\r
of the Unicode string specified by String as a hexadecimal number.\r
The format of the input Unicode string String is:\r
\r
Result = 0;\r
\r
//\r
- // Skip spaces if requested\r
+ // there is a space where there should't be\r
//\r
- while (StopAtSpace && *String == L' ') {\r
- String++;\r
+ if (*String == L' ') {\r
+ return (EFI_INVALID_PARAMETER);\r
}\r
\r
while (ShellIsHexaDecimalDigitCharacter (*String)) {\r
//\r
// If the Hex Number represented by String overflows according\r
- // to the range defined by UINTN, then ASSERT().\r
+ // to the range defined by UINT64, then return EFI_DEVICE_ERROR.\r
//\r
if (!(Result <= (RShiftU64((((UINT64) ~0) - InternalShellHexCharToUintn (*String)), 4)))) {\r
// if (!(Result <= ((((UINT64) ~0) - InternalShellHexCharToUintn (*String)) >> 4))) {\r
Result = 0;\r
\r
//\r
- // Skip spaces if requested\r
+ // Stop upon space if requested \r
+ // (if the whole value was 0)\r
//\r
- while (StopAtSpace && *String == L' ') {\r
- String++;\r
+ if (StopAtSpace && *String == L' ') {\r
+ *Value = Result;\r
+ return (EFI_SUCCESS);\r
}\r
+\r
while (ShellIsDecimalDigitCharacter (*String)) {\r
//\r
// If the number represented by String overflows according\r
- // to the range defined by UINT64, then ASSERT().\r
+ // to the range defined by UINT64, then return EFI_DEVICE_ERROR.\r
//\r
\r
if (!(Result <= (DivU64x32((((UINT64) ~0) - (*String - L'0')),10)))) {\r
If the position upon start is 0, then the Ascii Boolean will be set. This should be\r
maintained and not changed for all operations with the same file.\r
\r
+ NOTE: LINES THAT ARE RETURNED BY THIS FUNCTION ARE UCS2, EVEN IF THE FILE BEING READ\r
+ IS IN ASCII FORMAT.\r
+\r
@param[in] Handle SHELL_FILE_HANDLE to read from.\r
- @param[in, out] Buffer The pointer to buffer to read into.\r
- @param[in, out] Size The pointer to number of bytes in Buffer.\r
+ @param[in, out] Buffer The pointer to buffer to read into. If this function\r
+ returns EFI_SUCCESS, then on output Buffer will\r
+ contain a UCS2 string, even if the file being\r
+ read is ASCII.\r
+ @param[in, out] Size On input, pointer to number of bytes in Buffer.\r
+ On output, unchanged unless Buffer is too small\r
+ to contain the next line of the file. In that\r
+ case Size is set to the number of bytes needed\r
+ to hold the next line of the file (as a UCS2\r
+ string, even if it is an ASCII file).\r
@param[in] Truncate If the buffer is large enough, this has no effect.\r
If the buffer is is too small and Truncate is TRUE,\r
the line will be truncated.\r
\r
@retval EFI_SUCCESS The operation was successful. The line is stored in\r
Buffer.\r
+ @retval EFI_END_OF_FILE There are no more lines in the file.\r
@retval EFI_INVALID_PARAMETER Handle was NULL.\r
@retval EFI_INVALID_PARAMETER Size was NULL.\r
@retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line.\r
}\r
}\r
\r
+ if (*Ascii) {\r
+ CharSize = sizeof(CHAR8);\r
+ } else {\r
+ CharSize = sizeof(CHAR16);\r
+ }\r
for (CountSoFar = 0;;CountSoFar++){\r
CharBuffer = 0;\r
- if (*Ascii) {\r
- CharSize = sizeof(CHAR8);\r
- } else {\r
- CharSize = sizeof(CHAR16);\r
- }\r
Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
if ( EFI_ERROR(Status)\r
|| CharSize == 0\r
|| (CharBuffer == L'\n' && !(*Ascii))\r
|| (CharBuffer == '\n' && *Ascii)\r
){\r
+ if (CharSize == 0) {\r
+ Status = EFI_END_OF_FILE;\r
+ }\r
break;\r
}\r
//\r
// if we have space save it...\r
//\r
- if ((CountSoFar+1)*sizeof(CHAR16) < *Size){\r
+ if ((CountSoFar + 1) * CharSize < *Size){\r
ASSERT(Buffer != NULL);\r
- ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;\r
- ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;\r
+ if (*Ascii) {\r
+ ((CHAR8*)Buffer)[CountSoFar] = (CHAR8) CharBuffer;\r
+ ((CHAR8*)Buffer)[CountSoFar+1] = '\0';\r
+ }\r
+ else {\r
+ ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;\r
+ ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;\r
+ }\r
}\r
}\r
\r
//\r
// if we ran out of space tell when...\r
//\r
- if ((CountSoFar+1)*sizeof(CHAR16) > *Size){\r
- *Size = (CountSoFar+1)*sizeof(CHAR16);\r
- if (!Truncate) {\r
- gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
- } else {\r
- DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine"));\r
+ if (Status != EFI_END_OF_FILE){\r
+ if ((CountSoFar + 1) * CharSize > *Size){\r
+ *Size = (CountSoFar + 1) * CharSize;\r
+ if (!Truncate) {\r
+ gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
+ } else {\r
+ DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine"));\r
+ }\r
+ return (EFI_BUFFER_TOO_SMALL);\r
+ }\r
+\r
+ if (*Ascii) {\r
+ if (CountSoFar && ((CHAR8*)Buffer)[CountSoFar - 1] == '\r') {\r
+ ((CHAR8*)Buffer)[CountSoFar - 1] = '\0';\r
+ }\r
+ }\r
+ else {\r
+ if (CountSoFar && Buffer[CountSoFar - 1] == L'\r') {\r
+ Buffer[CountSoFar - 1] = CHAR_NULL;\r
+ }\r
}\r
- return (EFI_BUFFER_TOO_SMALL);\r
- }\r
- while(Buffer[StrLen(Buffer)-1] == L'\r') {\r
- Buffer[StrLen(Buffer)-1] = CHAR_NULL;\r
}\r
\r
return (Status);\r