Add PReadAll/PWriteAll for filedescriptor ptr

the newly added functions will read/write to a specified offset without
modifying file offset.

Test: treehugger
Change-Id: If0e7e3f2b9d2371838c3a7f27fe4250400ba3133
diff --git a/common/utils.cc b/common/utils.cc
index 66fd12d..1ac42dc 100644
--- a/common/utils.cc
+++ b/common/utils.cc
@@ -239,6 +239,31 @@
   return true;
 }
 
+bool PReadAll(const FileDescriptorPtr& fd,
+              void* buf,
+              size_t count,
+              off_t offset,
+              ssize_t* out_bytes_read) {
+  auto old_off = fd->Seek(0, SEEK_CUR);
+  TEST_AND_RETURN_FALSE_ERRNO(old_off >= 0);
+
+  auto success = ReadAll(fd, buf, count, offset, out_bytes_read);
+  TEST_AND_RETURN_FALSE_ERRNO(fd->Seek(old_off, SEEK_SET) == old_off);
+  return success;
+}
+
+bool PWriteAll(const FileDescriptorPtr& fd,
+               const void* buf,
+               size_t count,
+               off_t offset) {
+  auto old_off = fd->Seek(0, SEEK_CUR);
+  TEST_AND_RETURN_FALSE_ERRNO(old_off >= 0);
+
+  auto success = WriteAll(fd, buf, count, offset);
+  TEST_AND_RETURN_FALSE_ERRNO(fd->Seek(old_off, SEEK_SET) == old_off);
+  return success;
+}
+
 // Append |nbytes| of content from |buf| to the vector pointed to by either
 // |vec_p| or |str_p|.
 static void AppendBytes(const uint8_t* buf,
diff --git a/common/utils.h b/common/utils.h
index 0762796..616de06 100644
--- a/common/utils.h
+++ b/common/utils.h
@@ -70,6 +70,14 @@
               size_t count,
               off_t off);
 
+// https://man7.org/linux/man-pages/man2/pread.2.html
+// PWriteAll writes data at specified offset, but it DOES NOT modify file
+// position. Behaves similar to linux' pwrite syscall.
+bool PWriteAll(const FileDescriptorPtr& fd,
+               const void* buf,
+               size_t count,
+               off_t offset);
+
 // Calls read() repeatedly until |count| bytes are read or EOF or EWOULDBLOCK
 // is reached. Returns whether all read() calls succeeded (including EWOULDBLOCK
 // as a success case), sets |eof| to whether the eof was reached and sets
@@ -90,6 +98,15 @@
              off_t offset,
              ssize_t* out_bytes_read);
 
+// https://man7.org/linux/man-pages/man2/pread.2.html
+// Reads data at specified offset, this function DOES NOT change file position.
+// Behavior is similar to linux's pread syscall.
+bool PReadAll(const FileDescriptorPtr& fd,
+              void* buf,
+              size_t count,
+              off_t offset,
+              ssize_t* out_bytes_read);
+
 // Opens |path| for reading and appends its entire content to the container
 // pointed to by |out_p|. Returns true upon successfully reading all of the
 // file's content, false otherwise, in which case the state of the output