Parse postinstall program progress updates.

In Android postinstall is expected to take a long time in common cases.
This patch allows the postinstall program to report back to the updater
a progress indication, which will then be forwarded to all the clients
listening. These progress updates are part of the FINALIZING status.

Bug: 27880754
TEST=Added unittests. Deployed an update to an edison-eng and post-install reported progress back with the postinstall_example.

Change-Id: I35f96b92f090219c54cca48d8ab07c54cf8b4ab1
diff --git a/common/subprocess.cc b/common/subprocess.cc
index 1bfb911..9738b1d 100644
--- a/common/subprocess.cc
+++ b/common/subprocess.cc
@@ -33,6 +33,8 @@
 #include <brillo/process.h>
 #include <brillo/secure_blob.h>
 
+#include "update_engine/common/utils.h"
+
 using brillo::MessageLoop;
 using std::string;
 using std::unique_ptr;
@@ -114,26 +116,21 @@
 
 void Subprocess::OnStdoutReady(SubprocessRecord* record) {
   char buf[1024];
-  ssize_t rc = 0;
+  size_t bytes_read;
   do {
-    rc = HANDLE_EINTR(read(record->stdout_fd, buf, arraysize(buf)));
-    if (rc < 0) {
-      // EAGAIN and EWOULDBLOCK are normal return values when there's no more
-      // input as we are in non-blocking mode.
-      if (errno != EWOULDBLOCK && errno != EAGAIN) {
-        PLOG(ERROR) << "Error reading fd " << record->stdout_fd;
-        MessageLoop::current()->CancelTask(record->stdout_task_id);
-        record->stdout_task_id = MessageLoop::kTaskIdNull;
-      }
-    } else if (rc == 0) {
-      // A value of 0 means that the child closed its end of the pipe and there
-      // is nothing else to read from stdout.
+    bytes_read = 0;
+    bool eof;
+    bool ok = utils::ReadAll(
+        record->stdout_fd, buf, arraysize(buf), &bytes_read, &eof);
+    record->stdout.append(buf, bytes_read);
+    if (!ok || eof) {
+      // There was either an error or an EOF condition, so we are done watching
+      // the file descriptor.
       MessageLoop::current()->CancelTask(record->stdout_task_id);
       record->stdout_task_id = MessageLoop::kTaskIdNull;
-    } else {
-      record->stdout.append(buf, rc);
+      return;
     }
-  } while (rc > 0);
+  } while (bytes_read);
 }
 
 void Subprocess::ChildExitedCallback(const siginfo_t& info) {