Adds dumpstate log file to bugreport zip.

BUG: 29276583

Change-Id: I1e1346cbeb117f9945fbb0aa138986d9e791ae4f
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 5bfa919..2842bb9 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1000,7 +1000,7 @@
    temporary file.
  */
 static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
-        time_t now) {
+        const std::string& log_path, time_t now) {
     if (!add_zip_entry(bugreport_name, bugreport_path)) {
         MYLOGE("Failed to add text entry to .zip file\n");
         return false;
@@ -1010,6 +1010,16 @@
         return false;
     }
 
+    // Add log file (which contains stderr output) to zip...
+    fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
+    if (!add_zip_entry("dumpstate_log.txt", log_path.c_str())) {
+        MYLOGE("Failed to add dumpstate log to .zip file\n");
+        return false;
+    }
+    // ... and re-opens it for further logging.
+    redirect_to_existing_file(stderr, const_cast<char*>(log_path.c_str()));
+    fprintf(stderr, "\n");
+
     int32_t err = zip_writer->Finish();
     if (err) {
         MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
@@ -1171,7 +1181,7 @@
     /* full path of the temporary file containing the bugreport */
     std::string tmp_path;
 
-    /* full path of the file containing the dumpstate logs*/
+    /* full path of the file containing the dumpstate logs */
     std::string log_path;
 
     /* full path of the systrace file, when enabled */
@@ -1380,7 +1390,7 @@
         if (do_zip_file) {
             std::string entry_name = base_name + "-" + suffix + ".txt";
             MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
-            if (!finish_zip_file(entry_name, tmp_path, now)) {
+            if (!finish_zip_file(entry_name, tmp_path, log_path, now)) {
                 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
                 do_text_file = true;
             } else {
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 4769974..6093cd1 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -151,9 +151,12 @@
 /* redirect output to a service control socket */
 void redirect_to_socket(FILE *redirect, const char *service);
 
-/* redirect output to a file */
+/* redirect output to a new file */
 void redirect_to_file(FILE *redirect, char *path);
 
+/* redirect output to an existing file */
+void redirect_to_existing_file(FILE *redirect, char *path);
+
 /* create leading directories, if necessary */
 void create_parent_dirs(const char *path);
 
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 992f0a9..908179a 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -975,11 +975,11 @@
     }
 }
 
-/* redirect output to a file */
-void redirect_to_file(FILE *redirect, char *path) {
+void _redirect_to_file(FILE *redirect, char *path, int truncate_flag) {
     create_parent_dirs(path);
 
-    int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+    int fd = TEMP_FAILURE_RETRY(open(path,
+                                     O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
                                      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
     if (fd < 0) {
         MYLOGE("%s: %s\n", path, strerror(errno));
@@ -990,6 +990,14 @@
     close(fd);
 }
 
+void redirect_to_file(FILE *redirect, char *path) {
+    _redirect_to_file(redirect, path, O_TRUNC);
+}
+
+void redirect_to_existing_file(FILE *redirect, char *path) {
+    _redirect_to_file(redirect, path, O_APPEND);
+}
+
 static bool should_dump_native_traces(const char* path) {
     for (const char** p = native_processes_to_dump; *p; p++) {
         if (!strcmp(*p, path)) {