[lib/fuzzer] Fix logging for Fuchsia

This change fixes two aspects of logging on Fuchsia:

1. When logging to stdout, the output file descriptor should not be
closed in ExecuteCommand, as it prevent fdio_spawn_etc from succeeding
in subsequent calls.
2. When logging to a file in anything other than standalone Zircon, the
log file needs to be created in mutable storage. The best indicator
where this is relative to the Fuchsia component will be given by
'-artifact_prefix=...', so save the log file relative to that path.

Patch by: aarongreen
Differential Revision: https://reviews.llvm.org/D52562

llvm-svn: 343607
GitOrigin-RevId: a70ece45ebb2f9ecc8ecb349c03ed628b3c26d59
diff --git a/FuzzerCommand.h b/FuzzerCommand.h
index 255f571..9d258a2 100644
--- a/FuzzerCommand.h
+++ b/FuzzerCommand.h
@@ -81,7 +81,7 @@
   }
 
   // Like hasArgument, but checks for "-[Flag]=...".
-  bool hasFlag(const std::string &Flag) {
+  bool hasFlag(const std::string &Flag) const {
     std::string Arg("-" + Flag + "=");
     auto IsMatch = [&](const std::string &Other) {
       return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;
@@ -92,7 +92,7 @@
   // Returns the value of the first instance of a given flag, or an empty string
   // if the flag isn't present.  Ignores any occurrences after
   // "-ignore_remaining_args=1", if present.
-  std::string getFlagValue(const std::string &Flag) {
+  std::string getFlagValue(const std::string &Flag) const {
     std::string Arg("-" + Flag + "=");
     auto IsMatch = [&](const std::string &Other) {
       return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0;
diff --git a/FuzzerUtilFuchsia.cpp b/FuzzerUtilFuchsia.cpp
index b9c70e4..cd48fef 100644
--- a/FuzzerUtilFuchsia.cpp
+++ b/FuzzerUtilFuchsia.cpp
@@ -375,19 +375,28 @@
     Argv[i] = Args[i].c_str();
   Argv[Argc] = nullptr;
 
-  // Determine stdout
+  // Determine output.  On Fuchsia, the fuzzer is typically run as a component
+  // that lacks a mutable working directory. Fortunately, when this is the case
+  // a mutable output directory must be specified using "-artifact_prefix=...",
+  // so write the log file(s) there.
   int FdOut = STDOUT_FILENO;
-
   if (Cmd.hasOutputFile()) {
-    auto Filename = Cmd.getOutputFile();
-    FdOut = open(Filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0);
+    std::string Path;
+    if (Cmd.hasFlag("artifact_prefix"))
+      Path = Cmd.getFlagValue("artifact_prefix") + "/" + Cmd.getOutputFile();
+    else
+      Path = Cmd.getOutputFile();
+    FdOut = open(Path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0);
     if (FdOut == -1) {
-      Printf("libFuzzer: failed to open %s: %s\n", Filename.c_str(),
+      Printf("libFuzzer: failed to open %s: %s\n", Path.c_str(),
              strerror(errno));
       return ZX_ERR_IO;
     }
   }
-  auto CloseFdOut = at_scope_exit([&]() { close(FdOut); } );
+  auto CloseFdOut = at_scope_exit([FdOut]() {
+    if (FdOut != STDOUT_FILENO)
+      close(FdOut);
+  });
 
   // Determine stderr
   int FdErr = STDERR_FILENO;