]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellLib/UefiShellLib.c
ShellPkg: fix string to number conversion with "0 "
[mirror_edk2.git] / ShellPkg / Library / UefiShellLib / UefiShellLib.c
index 5e03400aebae112815e339a7499f49594219a49a..0bf034f682b724a4ca8cfb63ccbb1ac0ac10481e 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Provides interface to shell functionality for shell commands and applications.\r
 \r
-  Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\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
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -15,6 +15,7 @@
 #include "UefiShellLib.h"\r
 #include <ShellBase.h>\r
 #include <Library/SortLib.h>\r
+#include <Library/BaseLib.h>\r
 \r
 #define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN)\r
 \r
@@ -671,6 +672,7 @@ ShellOpenFileByName(
   EFI_DEVICE_PATH_PROTOCOL      *FilePath;\r
   EFI_STATUS                    Status;\r
   EFI_FILE_INFO                 *FileInfo;\r
+  CHAR16                        *FileNameCopy;\r
 \r
   //\r
   // ASSERT if FileName is NULL\r
@@ -682,11 +684,32 @@ ShellOpenFileByName(
   }\r
 \r
   if (gEfiShellProtocol != NULL) {\r
-    if ((OpenMode & EFI_FILE_MODE_CREATE) == EFI_FILE_MODE_CREATE && (Attributes & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {\r
-      return ShellCreateDirectory(FileName, FileHandle);\r
+    if ((OpenMode & EFI_FILE_MODE_CREATE) == EFI_FILE_MODE_CREATE) {\r
+\r
+      //\r
+      // Create only a directory\r
+      //\r
+      if ((Attributes & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {\r
+        return ShellCreateDirectory(FileName, FileHandle);\r
+      }\r
+\r
+      //\r
+      // Create the directory to create the file in\r
+      //\r
+      FileNameCopy = AllocateCopyPool (StrSize (FileName), FileName);\r
+      if (FileName == NULL) {\r
+        return (EFI_OUT_OF_RESOURCES);\r
+      }\r
+      PathCleanUpDirectories (FileNameCopy);\r
+      if (PathRemoveLastItem (FileNameCopy)) {\r
+        ShellCreateDirectory (FileNameCopy, FileHandle);\r
+        ShellCloseFile (FileHandle);\r
+      }\r
+      SHELL_FREE_NON_NULL (FileNameCopy);\r
     }\r
+\r
     //\r
-    // Use UEFI Shell 2.0 method\r
+    // Use UEFI Shell 2.0 method to create the file\r
     //\r
     Status = gEfiShellProtocol->OpenFileByName(FileName,\r
                                                FileHandle,\r
@@ -1690,8 +1713,8 @@ ShellFindFilePath (
     if (TestPath == NULL) {\r
       return (NULL);\r
     }\r
-    StrnCpy(TestPath, Path, Size/sizeof(CHAR16) - 1);\r
-    StrnCat(TestPath, FileName, Size/sizeof(CHAR16) - 1 - StrLen(TestPath));\r
+    StrCpyS(TestPath, Size/sizeof(CHAR16), Path);\r
+    StrCatS(TestPath, Size/sizeof(CHAR16), FileName);\r
     Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);\r
     if (!EFI_ERROR(Status)){\r
       if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {\r
@@ -1723,12 +1746,12 @@ ShellFindFilePath (
           *TempChar = CHAR_NULL;\r
         }\r
         if (TestPath[StrLen(TestPath)-1] != L'\\') {\r
-          StrnCat(TestPath, L"\\", Size/sizeof(CHAR16) - 1 - StrLen(TestPath));\r
+          StrCatS(TestPath, Size/sizeof(CHAR16), L"\\");\r
         }\r
         if (FileName[0] == L'\\') {\r
           FileName++;\r
         }\r
-        StrnCat(TestPath, FileName, Size/sizeof(CHAR16) - 1 - StrLen(TestPath));\r
+        StrCatS(TestPath, Size/sizeof(CHAR16), FileName);\r
         if (StrStr(Walker, L";") != NULL) {\r
           Walker = StrStr(Walker, L";") + 1;\r
         } else {\r
@@ -1797,9 +1820,9 @@ ShellFindFilePathEx (
     return (NULL);\r
   }\r
   for (ExtensionWalker = FileExtension, TempChar2 = (CHAR16*)FileExtension;  TempChar2 != NULL ; ExtensionWalker = TempChar2 + 1){\r
-    StrnCpy(TestPath, FileName, Size/sizeof(CHAR16) - 1);\r
+    StrCpyS(TestPath, Size/sizeof(CHAR16), FileName);\r
     if (ExtensionWalker != NULL) {\r
-      StrnCat(TestPath, ExtensionWalker, Size/sizeof(CHAR16) - 1 - StrLen(TestPath));\r
+      StrCatS(TestPath, Size/sizeof(CHAR16), ExtensionWalker);\r
     }\r
     TempChar = StrStr(TestPath, L";");\r
     if (TempChar != NULL) {\r
@@ -1903,6 +1926,7 @@ InternalIsOnCheckList (
 \r
   @param[in] Name               pointer to Name of parameter found\r
   @param[in] AlwaysAllowNumbers TRUE to allow numbers, FALSE to not.\r
+  @param[in] TimeNumbers        TRUE to allow numbers with ":", FALSE otherwise.\r
 \r
   @retval TRUE                  the Parameter is a flag.\r
   @retval FALSE                 the Parameter not a flag.\r
@@ -1911,7 +1935,8 @@ BOOLEAN
 EFIAPI\r
 InternalIsFlag (\r
   IN CONST CHAR16               *Name,\r
-  IN BOOLEAN                    AlwaysAllowNumbers\r
+  IN CONST BOOLEAN              AlwaysAllowNumbers,\r
+  IN CONST BOOLEAN              TimeNumbers\r
   )\r
 {\r
   //\r
@@ -1922,7 +1947,7 @@ InternalIsFlag (
   //\r
   // If we accept numbers then dont return TRUE. (they will be values)\r
   //\r
-  if (((Name[0] == L'-' || Name[0] == L'+') && InternalShellIsHexOrDecimalNumber(Name+1, FALSE, FALSE)) && AlwaysAllowNumbers) {\r
+  if (((Name[0] == L'-' || Name[0] == L'+') && InternalShellIsHexOrDecimalNumber(Name+1, FALSE, FALSE, TimeNumbers)) && AlwaysAllowNumbers) {\r
     return (FALSE);\r
   }\r
 \r
@@ -2056,6 +2081,7 @@ InternalCommandLineParse (
         // possibly trigger the next loop(s) to populate the value of this item\r
         //\r
         case TypeValue:\r
+        case TypeTimeValue:\r
           GetItemValue = 1;\r
           ValueSize = 0;\r
           break;\r
@@ -2075,46 +2101,35 @@ InternalCommandLineParse (
           ASSERT(GetItemValue == 0);\r
           break;\r
       }\r
-    } else if (GetItemValue != 0 && !InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers)) {\r
-      ASSERT(CurrentItemPackage != NULL);\r
+    } else if (GetItemValue != 0 && CurrentItemPackage != NULL && !InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers, (BOOLEAN)(CurrentItemPackage->Type == TypeTimeValue))) {\r
       //\r
       // get the item VALUE for a previous flag\r
       //\r
-      if (StrStr(Argv[LoopCounter], L" ") == NULL) {\r
-        CurrentValueSize = ValueSize + StrSize(Argv[LoopCounter]) + sizeof(CHAR16);\r
-        CurrentItemPackage->Value = ReallocatePool(ValueSize, CurrentValueSize, CurrentItemPackage->Value);\r
-        ASSERT(CurrentItemPackage->Value != NULL);\r
-        if (ValueSize == 0) {\r
-          StrnCpy(CurrentItemPackage->Value, Argv[LoopCounter], CurrentValueSize/sizeof(CHAR16) - 1);\r
-        } else {\r
-          StrnCat(CurrentItemPackage->Value, L" ", CurrentValueSize/sizeof(CHAR16) - 1 - StrLen(CurrentItemPackage->Value));\r
-          StrnCat(CurrentItemPackage->Value, Argv[LoopCounter], CurrentValueSize/sizeof(CHAR16) - 1 - StrLen(CurrentItemPackage->Value));\r
-        }\r
-        ValueSize += StrSize(Argv[LoopCounter]) + sizeof(CHAR16);\r
+      CurrentValueSize = ValueSize + StrSize(Argv[LoopCounter]) + sizeof(CHAR16);\r
+      CurrentItemPackage->Value = ReallocatePool(ValueSize, CurrentValueSize, CurrentItemPackage->Value);\r
+      ASSERT(CurrentItemPackage->Value != NULL);\r
+      if (ValueSize == 0) {\r
+        StrCpyS( CurrentItemPackage->Value, \r
+                  CurrentValueSize/sizeof(CHAR16), \r
+                  Argv[LoopCounter]\r
+                  );\r
       } else {\r
-        //\r
-        // the parameter has spaces.  must be quoted.\r
-        //\r
-        CurrentValueSize =  ValueSize + StrSize(Argv[LoopCounter]) + sizeof(CHAR16) + sizeof(CHAR16) + sizeof(CHAR16);\r
-        CurrentItemPackage->Value = ReallocatePool(ValueSize, CurrentValueSize, CurrentItemPackage->Value);\r
-        ASSERT(CurrentItemPackage->Value != NULL);\r
-        if (ValueSize == 0) {\r
-          StrnCpy(CurrentItemPackage->Value, L"\"", CurrentValueSize/sizeof(CHAR16) - 1);\r
-          StrnCat(CurrentItemPackage->Value, Argv[LoopCounter], CurrentValueSize/sizeof(CHAR16) - 1 - StrLen(CurrentItemPackage->Value));\r
-          StrnCat(CurrentItemPackage->Value, L"\"", CurrentValueSize/sizeof(CHAR16) - 1 - StrLen(CurrentItemPackage->Value));\r
-        } else {\r
-          StrnCat(CurrentItemPackage->Value, L" ", CurrentValueSize/sizeof(CHAR16) - 1 - StrLen(CurrentItemPackage->Value));\r
-          StrnCat(CurrentItemPackage->Value, L"\"", CurrentValueSize/sizeof(CHAR16) - 1 - StrLen(CurrentItemPackage->Value));\r
-          StrnCat(CurrentItemPackage->Value, Argv[LoopCounter], CurrentValueSize/sizeof(CHAR16) - 1 - StrLen(CurrentItemPackage->Value));\r
-          StrnCat(CurrentItemPackage->Value, L"\"", CurrentValueSize/sizeof(CHAR16) - 1 - StrLen(CurrentItemPackage->Value));\r
-       }\r
-        ValueSize += StrSize(Argv[LoopCounter]) + sizeof(CHAR16);\r
+        StrCatS( CurrentItemPackage->Value, \r
+                  CurrentValueSize/sizeof(CHAR16), \r
+                  L" "\r
+                  );\r
+        StrCatS( CurrentItemPackage->Value, \r
+                  CurrentValueSize/sizeof(CHAR16), \r
+                  Argv[LoopCounter]\r
+                  );\r
       }\r
+      ValueSize += StrSize(Argv[LoopCounter]) + sizeof(CHAR16);\r
+      \r
       GetItemValue--;\r
       if (GetItemValue == 0) {\r
         InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
       }\r
-    } else if (!InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers) ){ //|| ProblemParam == NULL) {\r
+    } else if (!InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers, FALSE)){\r
       //\r
       // add this one as a non-flag\r
       //\r
@@ -2629,14 +2644,14 @@ ShellCopySearchAndReplace(
         FreePool(Replace);\r
         return (EFI_BUFFER_TOO_SMALL);\r
       }\r
-      StrnCat(NewString, Replace, NewSize/sizeof(CHAR16) - 1 - StrLen(NewString));\r
+      StrCatS(NewString, NewSize/sizeof(CHAR16), Replace);\r
     } else {\r
       Size = StrSize(NewString);\r
       if (Size + sizeof(CHAR16) > NewSize) {\r
         FreePool(Replace);\r
         return (EFI_BUFFER_TOO_SMALL);\r
       }\r
-      StrnCat(NewString, SourceString, 1);\r
+      StrnCatS(NewString, NewSize/sizeof(CHAR16), SourceString, 1);\r
       SourceString++;\r
     }\r
   }\r
@@ -3134,7 +3149,7 @@ ShellStrToUintn(
 \r
   Hex = FALSE;\r
 \r
-  if (!InternalShellIsHexOrDecimalNumber(String, Hex, TRUE)) {\r
+  if (!InternalShellIsHexOrDecimalNumber(String, Hex, TRUE, FALSE)) {\r
     Hex = TRUE;\r
   }\r
 \r
@@ -3239,7 +3254,8 @@ StrnCatGrow (
       *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
@@ -3248,7 +3264,9 @@ StrnCatGrow (
   if (*Destination == NULL) {\r
     return (NULL);\r
   }\r
-  return StrnCat(*Destination, Source, Count);\r
+  \r
+  StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, Count);\r
+  return *Destination;\r
 }\r
 \r
 /**\r
@@ -3551,6 +3569,7 @@ ShellPromptForResponseHii (
   @param[in] String       The string to evaluate.\r
   @param[in] ForceHex     TRUE - always assume hex.\r
   @param[in] StopAtSpace  TRUE to halt upon finding a space, FALSE to keep going.\r
+  @param[in] TimeNumbers        TRUE to allow numbers with ":", FALSE otherwise.\r
 \r
   @retval TRUE        It is all numeric (dec/hex) characters.\r
   @retval FALSE       There is a non-numeric character.\r
@@ -3560,7 +3579,8 @@ EFIAPI
 InternalShellIsHexOrDecimalNumber (\r
   IN CONST CHAR16   *String,\r
   IN CONST BOOLEAN  ForceHex,\r
-  IN CONST BOOLEAN  StopAtSpace\r
+  IN CONST BOOLEAN  StopAtSpace,\r
+  IN CONST BOOLEAN  TimeNumbers\r
   )\r
 {\r
   BOOLEAN Hex;\r
@@ -3604,6 +3624,9 @@ InternalShellIsHexOrDecimalNumber (
   // loop through the remaining characters and use the lib function\r
   //\r
   for ( ; String != NULL && *String != CHAR_NULL && !(StopAtSpace && *String == L' ') ; String++){\r
+    if (TimeNumbers && (String[0] == L':')) {\r
+      continue;\r
+    }\r
     if (Hex) {\r
       if (!ShellIsHexaDecimalDigitCharacter(*String)) {\r
         return (FALSE);\r
@@ -3706,7 +3729,7 @@ InternalShellHexCharToUintn (
 /**\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
@@ -3774,16 +3797,16 @@ InternalShellStrHexToUint64 (
   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
@@ -3866,15 +3889,18 @@ InternalShellStrDecimalToUint64 (
   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
@@ -3927,10 +3953,10 @@ ShellConvertStringToUint64(
 \r
   Hex = ForceHex;\r
 \r
-  if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace)) {\r
+  if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace, FALSE)) {\r
     if (!Hex) {\r
       Hex = TRUE;\r
-      if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace)) {\r
+      if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace, FALSE)) {\r
         return (EFI_INVALID_PARAMETER);\r
       }\r
     } else {\r
@@ -3946,7 +3972,7 @@ ShellConvertStringToUint64(
   //\r
   // make sure we have something left that is numeric.\r
   //\r
-  if (Walker == NULL || *Walker == CHAR_NULL || !InternalShellIsHexOrDecimalNumber(Walker, Hex, StopAtSpace)) {\r
+  if (Walker == NULL || *Walker == CHAR_NULL || !InternalShellIsHexOrDecimalNumber(Walker, Hex, StopAtSpace, FALSE)) {\r
     return (EFI_INVALID_PARAMETER);\r
   }\r
 \r