readFile to take in fd
authorAravind Anbudurai <aru7@fb.com>
Tue, 2 Aug 2016 16:55:15 +0000 (09:55 -0700)
committerFacebook Github Bot 6 <facebook-github-bot-6-bot@fb.com>
Tue, 2 Aug 2016 17:08:55 +0000 (10:08 -0700)
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
folly/test/FileUtilTest.cpp

index 704a4969fc58d1cfff8780b13bf63a85d35a663d..0ab3af9a50f6d5e6e1ece681d41fb2566ce1e081 100644 (file)
@@ -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 <class Container>
-bool readFile(const char* file_name, Container& out,
-              size_t num_bytes = std::numeric_limits<size_t>::max()) {
+bool readFile(
+    int fd,
+    Container& out,
+    size_t num_bytes = std::numeric_limits<size_t>::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 <class Container>
+bool readFile(
+    const char* file_name,
+    Container& out,
+    size_t num_bytes = std::numeric_limits<size_t>::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
index d79dfd246d8f343bc24ca98ed334e234c32e9f6b..9170ff45dee86e96978b8c285bf3cbd6d0869581 100644 (file)
@@ -23,6 +23,7 @@
 #include <glog/logging.h>
 #include <gtest/gtest.h>
 
+#include <folly/File.h>
 #include <folly/Range.h>
 #include <folly/String.h>
 
@@ -265,16 +266,9 @@ TEST_F(FileUtilTest, preadv) {
 }
 
 TEST(String, readFile) {
-  srand(time(nullptr));
-  const string tmpPrefix = to<string>("/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