Added new ReadFileToString API with a max_size argument

The CL creates a new API that takes a max_size argument. When the file size exceed the max_size, the API primes the cache and returns false.

BUG=339417

Review URL: https://codereview.chromium.org/157593005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251771 0039d316-1c4b-4281-b951-d872f2087c98
parent 68d3fc19
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <stdio.h> #include <stdio.h>
#include <fstream> #include <fstream>
#include <limits>
#include "base/files/file_enumerator.h" #include "base/files/file_enumerator.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
...@@ -126,7 +127,11 @@ bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) { ...@@ -126,7 +127,11 @@ bool TextContentsEqual(const FilePath& filename1, const FilePath& filename2) {
return true; return true;
} }
bool ReadFileToString(const FilePath& path, std::string* contents) { bool ReadFileToString(const FilePath& path,
std::string* contents,
size_t max_size) {
if (contents)
contents->clear();
if (path.ReferencesParent()) if (path.ReferencesParent())
return false; return false;
FILE* file = OpenFile(path, "rb"); FILE* file = OpenFile(path, "rb");
...@@ -136,13 +141,29 @@ bool ReadFileToString(const FilePath& path, std::string* contents) { ...@@ -136,13 +141,29 @@ bool ReadFileToString(const FilePath& path, std::string* contents) {
char buf[1 << 16]; char buf[1 << 16];
size_t len; size_t len;
size_t size = 0;
bool read_status = true;
// Many files supplied in |path| have incorrect size (proc files etc).
// Hence, the file is read sequentially as opposed to a one-shot read.
while ((len = fread(buf, 1, sizeof(buf), file)) > 0) { while ((len = fread(buf, 1, sizeof(buf), file)) > 0) {
if (contents) if (contents)
contents->append(buf, len); contents->append(buf, std::min(len, max_size - size));
if ((max_size - size) < len) {
read_status = false;
break;
}
size += len;
} }
CloseFile(file); CloseFile(file);
return true; return read_status;
}
bool ReadFileToString(const FilePath& path, std::string* contents) {
return ReadFileToString(path, contents, std::numeric_limits<size_t>::max());
} }
bool IsDirectoryEmpty(const FilePath& dir_path) { bool IsDirectoryEmpty(const FilePath& dir_path) {
......
...@@ -139,10 +139,24 @@ BASE_EXPORT bool TextContentsEqual(const FilePath& filename1, ...@@ -139,10 +139,24 @@ BASE_EXPORT bool TextContentsEqual(const FilePath& filename1,
// Read the file at |path| into |contents|, returning true on success. // Read the file at |path| into |contents|, returning true on success.
// This function fails if the |path| contains path traversal components ('..'). // This function fails if the |path| contains path traversal components ('..').
// |contents| may be NULL, in which case this function is useful for its // |contents| may be NULL, in which case this function is useful for its
// side effect of priming the disk cache. // side effect of priming the disk cache, which is useful for unit tests.
// Useful for unit tests. // The function replaces rather than append to |contents|, further |contents|
// could be cleared on error.
BASE_EXPORT bool ReadFileToString(const FilePath& path, std::string* contents); BASE_EXPORT bool ReadFileToString(const FilePath& path, std::string* contents);
// Read the file at |path| into |contents|, returning true on success.
// This function has an additional check on the maximum size of the file.
// When the file size is greater than |max_size|, the function reads |max_size|
// bytes into |contents| and returns false.
// This function fails if the |path| contains path traversal components ('..').
// |contents| may be NULL, in which case this function is useful for its
// side effect of priming the disk cache, which is useful for unit tests.
// The function replaces rather than append to |contents|, further |contents|
// could be cleared on error.
BASE_EXPORT bool ReadFileToString(const FilePath& path,
std::string* contents,
size_t max_size);
#if defined(OS_POSIX) #if defined(OS_POSIX)
// Read exactly |bytes| bytes from file descriptor |fd|, storing the result // Read exactly |bytes| bytes from file descriptor |fd|, storing the result
......
...@@ -1941,6 +1941,51 @@ TEST_F(FileUtilTest, AppendToFile) { ...@@ -1941,6 +1941,51 @@ TEST_F(FileUtilTest, AppendToFile) {
EXPECT_EQ(L"hellohello", read_content); EXPECT_EQ(L"hellohello", read_content);
} }
TEST_F(FileUtilTest, ReadFileToString) {
const char kTestData[] = "0123";
std::string data;
FilePath file_path =
temp_dir_.path().Append(FILE_PATH_LITERAL("ReadFileToStringTest"));
ASSERT_EQ(4, file_util::WriteFile(file_path, kTestData, 4));
EXPECT_TRUE(ReadFileToString(file_path, &data));
EXPECT_EQ(kTestData, data);
data = "temp";
EXPECT_FALSE(ReadFileToString(file_path, &data, 0));
EXPECT_EQ(data.length(), 0u);
data = "temp";
EXPECT_FALSE(ReadFileToString(file_path, &data, 2));
EXPECT_EQ("01", data);
data.clear();
EXPECT_FALSE(ReadFileToString(file_path, &data, 3));
EXPECT_EQ("012", data);
data.clear();
EXPECT_TRUE(ReadFileToString(file_path, &data, 4));
EXPECT_EQ("0123", data);
data.clear();
EXPECT_TRUE(ReadFileToString(file_path, &data, 6));
EXPECT_EQ("0123", data);
EXPECT_TRUE(ReadFileToString(file_path, NULL, 6));
EXPECT_TRUE(ReadFileToString(file_path, NULL));
EXPECT_TRUE(base::DeleteFile(file_path, false));
EXPECT_FALSE(ReadFileToString(file_path, &data));
EXPECT_EQ(data.length(), 0u);
EXPECT_FALSE(ReadFileToString(file_path, &data, 6));
EXPECT_EQ(data.length(), 0u);
}
TEST_F(FileUtilTest, TouchFile) { TEST_F(FileUtilTest, TouchFile) {
FilePath data_dir = FilePath data_dir =
temp_dir_.path().Append(FILE_PATH_LITERAL("FilePathTest")); temp_dir_.path().Append(FILE_PATH_LITERAL("FilePathTest"));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment