From 4bd3e568094414d1135e2dcab5cdff14d84ed0d1 Mon Sep 17 00:00:00 2001 From: Aravind Anbudurai Date: Tue, 2 Aug 2016 09:55:15 -0700 Subject: [PATCH] readFile to take in fd Summary: I want to be able to read from an fd into an std::string and this diffs helps with that. Reviewed By: yfeldblum Differential Revision: D3654709 fbshipit-source-id: d48e8001a50f90c66cbe5b4a3b536c7b0074c39d --- folly/FileUtil.h | 37 +++++++++++++++++++------ folly/test/FileUtilTest.cpp | 55 ++++++++++++++++++++++++++++++------- 2 files changed, 73 insertions(+), 19 deletions(-) diff --git a/folly/FileUtil.h b/folly/FileUtil.h index 704a4969..0ab3af9a 100644 --- a/folly/FileUtil.h +++ b/folly/FileUtil.h @@ -112,21 +112,17 @@ ssize_t pwritevFull(int fd, iovec* iov, int count, off_t offset); * errno will be set appropriately by the failing system primitive. */ template -bool readFile(const char* file_name, Container& out, - size_t num_bytes = std::numeric_limits::max()) { +bool readFile( + int fd, + Container& out, + size_t num_bytes = std::numeric_limits::max()) { static_assert(sizeof(out[0]) == 1, "readFile: only containers with byte-sized elements accepted"); - assert(file_name); - - const auto fd = openNoInt(file_name, O_RDONLY); - if (fd == -1) return false; size_t soFar = 0; // amount of bytes successfully read SCOPE_EXIT { - assert(out.size() >= soFar); // resize better doesn't throw + DCHECK(out.size() >= soFar); // resize better doesn't throw out.resize(soFar); - // Ignore errors when closing the file - closeNoInt(fd); }; // Obtain file size: @@ -161,6 +157,29 @@ bool readFile(const char* file_name, Container& out, return true; } +/** + * Same as above, but takes in a file name instead of fd + */ +template +bool readFile( + const char* file_name, + Container& out, + size_t num_bytes = std::numeric_limits::max()) { + DCHECK(file_name); + + const auto fd = openNoInt(file_name, O_RDONLY); + if (fd == -1) { + return false; + } + + SCOPE_EXIT { + // Ignore errors when closing the file + closeNoInt(fd); + }; + + return readFile(fd, out, num_bytes); +} + /** * Writes container to file. The container is assumed to be * contiguous, with element size equal to 1, and offering STL-like diff --git a/folly/test/FileUtilTest.cpp b/folly/test/FileUtilTest.cpp index d79dfd24..9170ff45 100644 --- a/folly/test/FileUtilTest.cpp +++ b/folly/test/FileUtilTest.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -265,16 +266,9 @@ TEST_F(FileUtilTest, preadv) { } TEST(String, readFile) { - srand(time(nullptr)); - const string tmpPrefix = to("/tmp/folly-file-util-test-", - getpid(), "-", rand(), "-"); - const string afile = tmpPrefix + "myfile"; - const string emptyFile = tmpPrefix + "myfile2"; - - SCOPE_EXIT { - unlink(afile.c_str()); - unlink(emptyFile.c_str()); - }; + const TemporaryFile afileTemp, emptyFileTemp; + auto afile = afileTemp.path(); + auto emptyFile = emptyFileTemp.path(); EXPECT_TRUE(writeFile(string(), emptyFile.c_str())); EXPECT_TRUE(writeFile(StringPiece("bar"), afile.c_str())); @@ -303,4 +297,45 @@ TEST(String, readFile) { } } +class ReadFileFd : public ::testing::Test { + protected: + void SetUp() override { + ASSERT_TRUE(writeFile(StringPiece("bar"), aFile.path().c_str())); + } + + TemporaryFile aFile; +}; + +TEST_F(ReadFileFd, ReadZeroBytes) { + std::string contents; + EXPECT_TRUE(readFile(aFile.fd(), contents, 0)); + EXPECT_EQ("", contents); +} + +TEST_F(ReadFileFd, ReadPartial) { + std::string contents; + EXPECT_TRUE(readFile(aFile.fd(), contents, 2)); + EXPECT_EQ("ba", contents); +} + +TEST_F(ReadFileFd, ReadFull) { + std::string contents; + EXPECT_TRUE(readFile(aFile.fd(), contents)); + EXPECT_EQ("bar", contents); +} + +TEST_F(ReadFileFd, WriteOnlyFd) { + File f(aFile.path().string(), O_WRONLY); + std::string contents; + EXPECT_FALSE(readFile(f.fd(), contents)); + PLOG(INFO); +} + +TEST_F(ReadFileFd, InvalidFd) { + File f(aFile.path().string()); + f.close(); + std::string contents; + EXPECT_FALSE(readFile(f.fd(), contents)); + PLOG(INFO); +} }} // namespaces -- 2.34.1