]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c
MdePkg/BaseSafeIntLib: fix undefined behavior in SafeInt64Add()
[mirror_edk2.git] / MdePkg / Library / UefiFileHandleLib / UefiFileHandleLib.c
index be66c57bb8f50e67826e4ced1eef4354188de0cd..57aad77bc13542ce7828853a1500f75e79a43ab3 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Provides interface to EFI_FILE_HANDLE functionality.\r
 \r
-  Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved. <BR>\r
+  Copyright (c) 2006 - 2017, 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
@@ -231,7 +231,7 @@ FileHandleWrite(
 \r
 @param FileHandle               the file handle to close.\r
 \r
-@retval EFI_SUCCESS             the file handle was closed sucessfully.\r
+@retval EFI_SUCCESS             the file handle was closed successfully.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -261,7 +261,7 @@ FileHandleClose (
 \r
   @param FileHandle             the file handle to delete\r
 \r
-  @retval EFI_SUCCESS           the file was closed sucessfully\r
+  @retval EFI_SUCCESS           the file was closed successfully\r
   @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not\r
                                 deleted\r
   @retval INVALID_PARAMETER     One of the parameters has an invalid value.\r
@@ -297,9 +297,9 @@ FileHandleDelete (
   has the effect of starting the read process of the directory entries over.\r
 \r
   @param FileHandle             The file handle on which the position is being set\r
-  @param Position               Byte position from begining of file\r
+  @param Position               Byte position from beginning of file\r
 \r
-  @retval EFI_SUCCESS           Operation completed sucessfully.\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
   @retval EFI_UNSUPPORTED       the seek request for non-zero is not valid on\r
                                 directories.\r
   @retval INVALID_PARAMETER     One of the parameters has an invalid value.\r
@@ -330,9 +330,9 @@ FileHandleSetPosition (
   if FileHandle is a directory.\r
 \r
   @param FileHandle             The open file handle on which to get the position.\r
-  @param Position               Byte position from begining of file.\r
+  @param Position               Byte position from beginning of file.\r
 \r
-  @retval EFI_SUCCESS           the operation completed sucessfully.\r
+  @retval EFI_SUCCESS           the operation completed successfully.\r
   @retval INVALID_PARAMETER     One of the parameters has an invalid value.\r
   @retval EFI_UNSUPPORTED       the request is not valid on directories.\r
 **/\r
@@ -383,18 +383,17 @@ FileHandleFlush (
 }\r
 \r
 /**\r
-  function to determine if a given handle is a directory handle\r
+  Function to determine if a given handle is a directory handle.\r
 \r
-  if DirHandle is NULL then return error\r
-\r
-  open the file information on the DirHandle and verify that the Attribute\r
+  Open the file information on the DirHandle and verify that the Attribute\r
   includes EFI_FILE_DIRECTORY bit set.\r
 \r
-  @param DirHandle              Handle to open file\r
+  @param[in] DirHandle          Handle to open file.\r
 \r
-  @retval EFI_SUCCESS           DirHandle is a directory\r
-  @retval EFI_INVALID_PARAMETER DirHandle did not have EFI_FILE_INFO available\r
-  @retval EFI_NOT_FOUND         DirHandle is not a directory\r
+  @retval EFI_SUCCESS           DirHandle is a directory.\r
+  @retval EFI_INVALID_PARAMETER DirHandle is NULL. \r
+                                The file information returns from FileHandleGetInfo is NULL. \r
+  @retval EFI_NOT_FOUND         DirHandle is not a directory.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -490,7 +489,7 @@ FileHandleFindFirstFile (
   }\r
 \r
   //\r
-  // reset to the begining of the directory\r
+  // reset to the beginning of the directory\r
   //\r
   Status = FileHandleSetPosition(DirHandle, 0);\r
   if (EFI_ERROR(Status)) {\r
@@ -576,17 +575,16 @@ FileHandleFindNextFile(
 /**\r
   Retrieve the size of a file.\r
 \r
-  if FileHandle is NULL then return error\r
-  if Size is NULL then return error\r
-\r
   This function extracts the file size info from the FileHandle's EFI_FILE_INFO\r
   data.\r
 \r
-  @param FileHandle             file handle from which size is retrieved\r
-  @param Size                   pointer to size\r
+  @param[in] FileHandle         The file handle from which size is retrieved.\r
+  @param[out] Size              The pointer to size.\r
 \r
-  @retval EFI_SUCCESS           operation was completed sucessfully\r
-  @retval EFI_DEVICE_ERROR      cannot access the file\r
+  @retval EFI_SUCCESS           Operation was completed successfully.\r
+  @retval EFI_DEVICE_ERROR      Cannot access the file.\r
+  @retval EFI_INVALID_PARAMETER FileHandle is NULL.\r
+                                Size is NULL.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -625,16 +623,15 @@ FileHandleGetSize (
 /**\r
   Set the size of a file.\r
 \r
-  If FileHandle is NULL then return error.\r
-\r
   This function changes the file size info from the FileHandle's EFI_FILE_INFO\r
   data.\r
 \r
-  @param FileHandle             File handle whose size is to be changed.\r
-  @param Size                   New size.\r
+  @param[in] FileHandle         The file handle whose size is to be changed.\r
+  @param[in] Size               The new size.\r
 \r
-  @retval EFI_SUCCESS           operation was completed sucessfully.\r
-  @retval EFI_DEVICE_ERROR      cannot access the file.\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_DEVICE_ERROR      Cannot access the file.\r
+  @retval EFI_INVALID_PARAMETER FileHandle is NULL.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -772,7 +769,9 @@ StrnCatGrowLeft (
 \r
 /**\r
   Function to get a full filename given a EFI_FILE_HANDLE somewhere lower on the\r
-  directory 'stack'.\r
+  directory 'stack'. If the file is a directory, then append the '\' char at the \r
+  end of name string. If it's not a directory, then the last '\' should not be \r
+  added.\r
 \r
   if Handle is NULL, return EFI_INVALID_PARAMETER\r
 \r
@@ -822,7 +821,7 @@ FileHandleGetFileName (
         break;\r
       } else {\r
         //\r
-        // We got info... do we have a name? if yes preceed the current path with it...\r
+        // We got info... do we have a name? if yes precede the current path with it...\r
         //\r
         if (StrLen (FileInfo->FileName) == 0) {\r
           if (*FullFileName == NULL) {\r
@@ -859,6 +858,14 @@ FileHandleGetFileName (
     *FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0);\r
   }\r
 \r
+  if (*FullFileName != NULL && \r
+      (*FullFileName)[StrLen(*FullFileName) - 1] == L'\\' && \r
+      StrLen(*FullFileName) > 1 &&\r
+      FileHandleIsDirectory(Handle) == EFI_NOT_FOUND\r
+     ) {\r
+    (*FullFileName)[StrLen(*FullFileName) - 1] = CHAR_NULL;\r
+  }\r
+\r
   if (CurrentHandle != NULL) {\r
     CurrentHandle->Close (CurrentHandle);\r
   }\r
@@ -912,25 +919,31 @@ FileHandleReturnLine(
 }\r
 \r
 /**\r
-  Function to read a single line (up to but not including the \n) from a EFI_FILE_HANDLE.\r
+  Function to read a single line (up to but not including the \n) from a file.\r
 \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
+  The function will not return the \r and \n character in buffer. When an empty line is\r
+  read a CHAR_NULL character will be returned in buffer.\r
 \r
-  @param[in]       Handle        FileHandle to read from\r
-  @param[in, out]  Buffer        pointer to buffer to read into\r
-  @param[in, out]  Size          pointer to number of bytes in buffer\r
-  @param[in]       Truncate      if TRUE then allows for truncation of the line to fit.\r
-                                 if FALSE will reset the position to the begining of the\r
-                                 line if the buffer is not large enough.\r
-  @param[in, out]  Ascii         Boolean value for indicating whether the file is Ascii (TRUE) or UCS2 (FALSE);\r
-\r
-  @retval EFI_SUCCESS           the operation was sucessful.  the line is stored in\r
+  @param[in]       Handle        FileHandle 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]       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
+                                 If the buffer is is too small and Truncate is FALSE,\r
+                                 then no read will occur.\r
+\r
+  @param[in, out]  Ascii         Boolean value for indicating whether the file is\r
+                                 Ascii (TRUE) or UCS2 (FALSE).\r
+\r
+  @retval EFI_SUCCESS           The operation was successful.  The line is stored in\r
                                 Buffer.\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 enough space to store the line.\r
-                                Size was updated to minimum space required.\r
+  @retval EFI_BUFFER_TOO_SMALL  Size was not large enough to store the line.\r
+                                Size was updated to the minimum space required.\r
   @sa FileHandleRead\r
 **/\r
 EFI_STATUS\r
@@ -945,20 +958,31 @@ FileHandleReadLine(
 {\r
   EFI_STATUS  Status;\r
   CHAR16      CharBuffer;\r
+  UINT64      FileSize;\r
   UINTN       CharSize;\r
   UINTN       CountSoFar;\r
+  UINTN       CrCount;\r
   UINT64      OriginalFilePosition;\r
 \r
-\r
   if (Handle == NULL\r
     ||Size   == NULL\r
     ||(Buffer==NULL&&*Size!=0)\r
    ){\r
     return (EFI_INVALID_PARAMETER);\r
-  }\r
-  if (Buffer != NULL) {\r
+  } \r
+  \r
+  if (Buffer != NULL && *Size != 0) {\r
     *Buffer = CHAR_NULL;\r
-  }\r
+  } \r
+  \r
+  Status = FileHandleGetSize (Handle, &FileSize);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  } else if (FileSize == 0) {\r
+    *Ascii = TRUE;\r
+    return EFI_SUCCESS;\r
+  }  \r
+  \r
   FileHandleGetPosition(Handle, &OriginalFilePosition);\r
   if (OriginalFilePosition == 0) {\r
     CharSize = sizeof(CHAR16);\r
@@ -972,6 +996,7 @@ FileHandleReadLine(
     }\r
   }\r
 \r
+  CrCount = 0;\r
   for (CountSoFar = 0;;CountSoFar++){\r
     CharBuffer = 0;\r
     if (*Ascii) {\r
@@ -986,47 +1011,61 @@ FileHandleReadLine(
        || (CharBuffer ==  '\n' && *Ascii)\r
      ){\r
       break;\r
+    } else if (\r
+        (CharBuffer == L'\r' && !(*Ascii)) ||\r
+        (CharBuffer ==  '\r' && *Ascii)\r
+      ) {\r
+      CrCount++;\r
+      continue;\r
     }\r
     //\r
     // if we have space save it...\r
     //\r
-    if ((CountSoFar+1)*sizeof(CHAR16) < *Size){\r
+    if ((CountSoFar+1-CrCount)*sizeof(CHAR16) < *Size){\r
       ASSERT(Buffer != NULL);\r
-      ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;\r
-      ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;\r
+      ((CHAR16*)Buffer)[CountSoFar-CrCount] = CharBuffer;\r
+      ((CHAR16*)Buffer)[CountSoFar+1-CrCount] = CHAR_NULL;\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 ((CountSoFar+1-CrCount)*sizeof(CHAR16) > *Size){\r
+    *Size = (CountSoFar+1-CrCount)*sizeof(CHAR16);\r
     if (!Truncate) {\r
+      if (Buffer != NULL && *Size != 0) {\r
+        ZeroMem(Buffer, *Size);\r
+      }\r
       FileHandleSetPosition(Handle, OriginalFilePosition);\r
+      return (EFI_BUFFER_TOO_SMALL);\r
     } else {\r
       DEBUG((DEBUG_WARN, "The line was truncated in FileHandleReadLine"));\r
+      return (EFI_SUCCESS);\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
 }\r
 \r
 /**\r
-  function to write a line of unicode text to a file.\r
-\r
-  if Handle is NULL, return error.\r
-  if Buffer is NULL, do nothing.  (return SUCCESS)\r
-\r
-  @param[in]     Handle         FileHandle to write to\r
-  @param[in]     Buffer         Buffer to write\r
-\r
-  @retval  EFI_SUCCESS          the data was written.\r
-  @retval  other                failure.\r
+  Function to write a line of text to a file.\r
+  \r
+  If the file is a Unicode file (with UNICODE file tag) then write the unicode \r
+  text.\r
+  If the file is an ASCII file then write the ASCII text.\r
+  If the size of file is zero (without file tag at the beginning) then write \r
+  ASCII text as default.\r
+\r
+  @param[in]     Handle         FileHandle to write to.\r
+  @param[in]     Buffer         Buffer to write, if NULL the function will\r
+                                take no action and return EFI_SUCCESS.\r
+\r
+  @retval  EFI_SUCCESS            The data was written.\r
+                                  Buffer is NULL.\r
+  @retval  EFI_INVALID_PARAMETER  Handle is NULL.\r
+  @retval  EFI_OUT_OF_RESOURCES   Unable to allocate temporary space for ASCII \r
+                                  string due to out of resources.\r
 \r
   @sa FileHandleWrite\r
 **/\r
@@ -1037,8 +1076,15 @@ FileHandleWriteLine(
   IN CHAR16          *Buffer\r
   )\r
 {\r
-  EFI_STATUS Status;\r
-  UINTN      Size;\r
+  EFI_STATUS  Status;\r
+  CHAR16      CharBuffer;\r
+  UINTN       Size;\r
+  UINTN       Index;\r
+  UINTN       CharSize;\r
+  UINT64      FileSize;\r
+  UINT64      OriginalFilePosition;\r
+  BOOLEAN     Ascii;\r
+  CHAR8       *AsciiBuffer;\r
 \r
   if (Buffer == NULL) {\r
     return (EFI_SUCCESS);\r
@@ -1047,14 +1093,85 @@ FileHandleWriteLine(
   if (Handle == NULL) {\r
     return (EFI_INVALID_PARAMETER);\r
   }\r
-\r
-  Size = StrSize(Buffer) - sizeof(Buffer[0]);\r
-  Status = FileHandleWrite(Handle, &Size, Buffer);\r
+  \r
+  Ascii = FALSE;\r
+  AsciiBuffer = NULL;\r
+  \r
+  Status = FileHandleGetPosition(Handle, &OriginalFilePosition);\r
   if (EFI_ERROR(Status)) {\r
-    return (Status);\r
+    return Status;\r
   }\r
-  Size = StrSize(L"\r\n") - sizeof(CHAR16);\r
-  return FileHandleWrite(Handle, &Size, L"\r\n");\r
+  \r
+  Status = FileHandleSetPosition(Handle, 0);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  Status = FileHandleGetSize(Handle, &FileSize);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  if (FileSize == 0) {\r
+    Ascii = TRUE;\r
+  } else {\r
+    CharSize = sizeof (CHAR16);\r
+    Status = FileHandleRead (Handle, &CharSize, &CharBuffer);\r
+    ASSERT_EFI_ERROR (Status);\r
+    if (CharBuffer == gUnicodeFileTag) {\r
+      Ascii = FALSE;\r
+    } else {\r
+      Ascii = TRUE;\r
+    }\r
+  }\r
+  \r
+  Status = FileHandleSetPosition(Handle, OriginalFilePosition);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  if (Ascii) {\r
+    Size = ( StrSize(Buffer) / sizeof(CHAR16) ) * sizeof(CHAR8);\r
+    AsciiBuffer = (CHAR8 *)AllocateZeroPool(Size);\r
+    if (AsciiBuffer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    UnicodeStrToAsciiStrS (Buffer, AsciiBuffer, Size);\r
+    for (Index = 0; Index < Size; Index++) {\r
+      if ((AsciiBuffer[Index] & BIT7) != 0) {\r
+        FreePool(AsciiBuffer);\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    }\r
+    \r
+    Size = AsciiStrSize(AsciiBuffer) - sizeof(CHAR8);\r
+    Status = FileHandleWrite(Handle, &Size, AsciiBuffer);\r
+    if (EFI_ERROR(Status)) {\r
+      FreePool (AsciiBuffer);\r
+      return (Status);\r
+    }\r
+    Size = AsciiStrSize("\r\n") - sizeof(CHAR8);\r
+    Status = FileHandleWrite(Handle, &Size, "\r\n");\r
+  } else {\r
+    if (OriginalFilePosition == 0) {\r
+      Status = FileHandleSetPosition (Handle, sizeof(CHAR16));\r
+      if (EFI_ERROR(Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+    Size = StrSize(Buffer) - sizeof(CHAR16);\r
+    Status = FileHandleWrite(Handle, &Size, Buffer);\r
+    if (EFI_ERROR(Status)) {\r
+      return (Status);\r
+    }\r
+    Size = StrSize(L"\r\n") - sizeof(CHAR16);\r
+    Status = FileHandleWrite(Handle, &Size, L"\r\n");\r
+  }\r
+  \r
+  if (AsciiBuffer != NULL) {\r
+    FreePool (AsciiBuffer);\r
+  }\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -1064,7 +1181,7 @@ FileHandleWriteLine(
   @param[in] Format   the format argument (see printlib for format specifier)\r
   @param[in] ...      the variable arguments for the format\r
 \r
-  @retval EFI_SUCCESS the operation was sucessful\r
+  @retval EFI_SUCCESS the operation was successful\r
   @return other       a return value from FileHandleWriteLine\r
 \r
   @sa FileHandleWriteLine\r