Merge "Add ReadFully and WriteFully to libbase."
diff --git a/base/file.cpp b/base/file.cpp
index a51c5ff..6b19818 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -120,5 +120,29 @@
   return result || CleanUpAfterFailedWrite(path);
 }
 
+bool ReadFully(int fd, void* data, size_t byte_count) {
+  uint8_t* p = reinterpret_cast<uint8_t*>(data);
+  size_t remaining = byte_count;
+  while (remaining > 0) {
+    ssize_t n = TEMP_FAILURE_RETRY(read(fd, p, remaining));
+    if (n <= 0) return false;
+    p += n;
+    remaining -= n;
+  }
+  return true;
+}
+
+bool WriteFully(int fd, const void* data, size_t byte_count) {
+  const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
+  size_t remaining = byte_count;
+  while (remaining > 0) {
+    ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, remaining));
+    if (n == -1) return false;
+    p += n;
+    remaining -= n;
+  }
+  return true;
+}
+
 }  // namespace base
 }  // namespace android
diff --git a/base/file_test.cpp b/base/file_test.cpp
index fc48b32..e5cf696 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -79,3 +79,28 @@
   ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << errno;
   EXPECT_EQ("abc", s);
 }
+
+TEST(file, ReadFully) {
+  int fd = open("/proc/version", O_RDONLY);
+  ASSERT_NE(-1, fd) << strerror(errno);
+
+  char buf[1024];
+  memset(buf, 0, sizeof(buf));
+  ASSERT_TRUE(android::base::ReadFully(fd, buf, 5));
+  ASSERT_STREQ("Linux", buf);
+
+  ASSERT_EQ(0, lseek(fd, 0, SEEK_SET)) << strerror(errno);
+
+  ASSERT_FALSE(android::base::ReadFully(fd, buf, sizeof(buf)));
+
+  close(fd);
+}
+
+TEST(file, WriteFully) {
+  TemporaryFile tf;
+  ASSERT_TRUE(tf.fd != -1);
+  ASSERT_TRUE(android::base::WriteFully(tf.fd, "abc", 3));
+  std::string s;
+  ASSERT_TRUE(android::base::ReadFileToString(tf.filename, &s)) << errno;
+  EXPECT_EQ("abc", s);
+}
diff --git a/base/include/base/file.h b/base/include/base/file.h
index ef97742..acd29b3 100644
--- a/base/include/base/file.h
+++ b/base/include/base/file.h
@@ -34,6 +34,9 @@
                        mode_t mode, uid_t owner, gid_t group);
 #endif
 
+bool ReadFully(int fd, void* data, size_t byte_count);
+bool WriteFully(int fd, const void* data, size_t byte_count);
+
 }  // namespace base
 }  // namespace android