// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <fcntl.h>
#include <getopt.h>
#include <lib/fit/defer.h>
#include <lib/stdcompat/functional.h>
#include <lib/zxdump/dump.h>
#include <lib/zxdump/elf-search.h>
#include <lib/zxdump/fd-writer.h>
#include <lib/zxdump/task.h>
#include <lib/zxdump/zstd-writer.h>
#include <zircon/assert.h>

#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <variant>

#include <fbl/unique_fd.h>
#include <rapidjson/error/en.h>
#include <rapidjson/filereadstream.h>
#include <rapidjson/reader.h>
#include <rapidjson/stream.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>

#include "cli.h"

namespace {

using namespace std::literals;

constexpr std::string_view kOutputPrefix = "core."sv;
constexpr std::string_view kArchiveSuffix = ".a"sv;
constexpr std::string_view kZstdSuffix = ".zst"sv;

constexpr std::string_view kDefaultRemarksName = "remarks"sv;

struct Remarks {
  std::string name;
  std::unique_ptr<rapidjson::StringBuffer> data{new rapidjson::StringBuffer};
};

class Writer;  // Forward declaration.

// Command-line flags controlling the dump are parsed into this object, which
// is passed around to the methods affected by policy choices.
struct Flags {
  std::string OutputFile(zx_koid_t pid, bool outer = true, std::string_view suffix = {}) const {
    std::string filename{outer ? output_prefix : kOutputPrefix};
    filename += std::to_string(pid);
    filename += suffix;
    if (outer && zstd) {
      filename += kZstdSuffix;
    }
    return filename;
  }

  time_t Date(zxdump::Task& task) const { return record_date ? task.date() : 0; }

  std::vector<Remarks> remarks;
  std::string_view output_prefix = kOutputPrefix;
  std::unique_ptr<Writer> streaming;
  size_t limit = zxdump::DefaultLimit();
  bool dump_memory = true;
  bool collect_system = false;
  bool repeat_system = false;
  bool collect_kernel = false;
  bool repeat_kernel = false;
  bool collect_threads = true;
  bool collect_job_children = true;
  bool collect_job_processes = true;
  bool flatten_jobs = false;
  bool record_date = true;
  bool repeat_remarks = false;
  bool zstd = false;
  bool streaming_archive = false;
};

// This handles writing a single output file, and removing that output file if
// the dump is aborted before `Ok(true)` is called.
class Writer {
 public:
  using error_type = zxdump::FdWriter::error_type;

  Writer() = delete;

  Writer(fbl::unique_fd fd, std::string filename, bool zstd)
      : writer_{zstd ? WhichWriter{zxdump::ZstdWriter(std::move(fd))}
                     : WhichWriter{zxdump::FdWriter(std::move(fd))}},
        filename_{std::move(filename)} {}

  auto AccumulateFragmentsCallback() {
    return std::visit(
        [](auto& writer)
            -> fit::function<fit::result<error_type>(size_t offset, zxdump::ByteView data)> {
          return writer.AccumulateFragmentsCallback();
        },
        writer_);
  }

  auto WriteFragments() {
    return std::visit(
        [](auto& writer) -> fit::result<error_type, size_t> { return writer.WriteFragments(); },
        writer_);
  }

  auto WriteCallback() {
    return std::visit(
        [](auto& writer)
            -> fit::function<fit::result<error_type>(size_t offset, zxdump::ByteView data)> {
          return writer.WriteCallback();
        },
        writer_);
  }

  void ResetOffset() {
    std::visit([](auto& writer) { writer.ResetOffset(); }, writer_);
  }

  // Write errors from errno use the file name.
  void Error(zxdump::FdError error) {
    std::string_view fn = filename_;
    if (fn.empty()) {
      fn = "<stdout>"sv;
    }
    std::cerr << fn << ": "sv << error << std::endl;
  }

  // Called with true if the output file should be preserved at destruction.
  bool Ok(bool ok) {
    if (ok) {
      if (auto writer = std::get_if<zxdump::ZstdWriter>(&writer_)) {
        auto result = writer->Finish();
        if (result.is_error()) {
          Error(result.error_value());
          return false;
        }
      }
      filename_.clear();
    }
    return ok;
  }

  bool StartArchive() {
    auto result = zxdump::JobDump::DumpArchiveHeader(WriteCallback());
    if (result.is_error()) {
      Error(result.error_value());
    }
    return result.is_ok();
  }

  bool DumpMemberHeader(std::string_view name, size_t size, time_t mtime) {
    // File offset calculations start fresh with each member.
    ResetOffset();
    auto result = zxdump::JobDump::DumpMemberHeader(WriteCallback(), 0, name, size, mtime);
    if (result.is_error()) {
      Error(*result.error_value().dump_error_);
    }
    return result.is_ok();
  }

  ~Writer() {
    if (!filename_.empty()) {
      remove(filename_.c_str());
    }
  }

 private:
  using WhichWriter = std::variant<zxdump::FdWriter, zxdump::ZstdWriter>;

  WhichWriter writer_;
  std::string filename_;
};

size_t MemberHeaderSize() { return zxdump::JobDump::MemberHeaderSize(); }

// This is the base class of ProcessDumper and JobDumper; the object
// handles collecting and producing the dump for one process or one job.
// The Writer and Flags objects get passed in to control the details
// and of the dump and where it goes.
class DumperBase {
 public:
  // Read errors from syscalls use the PID (or job KOID).
  void Error(const zxdump::Error& error) const {
    std::cerr << koid_ << ": "sv << error << std::endl;
  }

  zx_koid_t koid() const { return koid_; }

  time_t ClockIn(const Flags& flags) { return 0; }

 protected:
  constexpr explicit DumperBase(zx_koid_t koid) : koid_(koid) {}

 private:
  zx_koid_t koid_ = ZX_KOID_INVALID;
};

// This does the Collect* calls that are common to ProcessDumper and JobDumper.
constexpr auto CollectCommon =  //
    [](const Flags& flags, bool top, auto& dumper,
       const zxdump::TaskHolder& holder) -> fit::result<zxdump::Error> {
  if (flags.collect_system && (top || flags.repeat_system)) {
    auto result = dumper.CollectSystem(holder);
    if (result.is_error()) {
      return result.take_error();
    }
  }

  if (flags.collect_kernel && (top || flags.repeat_kernel)) {
    auto result = dumper.CollectKernel();
    if (result.is_error()) {
      return result.take_error();
    }
  }

  if (top || flags.repeat_remarks) {
    for (const auto& [name, data] : flags.remarks) {
      std::string_view contents{data->GetString(), data->GetSize()};
      auto result = dumper.Remarks(name, contents);
      if (result.is_error()) {
        return result.take_error();
      }
    }
  }

  return fit::ok();
};

class ProcessDumper : public DumperBase {
 public:
  explicit ProcessDumper(zxdump::Process& process) : DumperBase{process.koid()}, dumper_{process} {}

  auto OutputFile(const Flags& flags, bool outer = true) const {
    return flags.OutputFile(koid(), outer);
  }

  time_t ClockIn(const Flags& flags) {
    time_t dump_date = flags.Date(dumper_.process());
    if (dump_date != 0) {
      dumper_.set_date(dump_date);
    }
    return dump_date;
  }

  // Phase 1: Collect underpants!
  std::optional<size_t> Collect(const Flags& flags, bool top, const zxdump::TaskHolder& holder) {
    if (flags.collect_threads) {
      auto result = dumper_.SuspendAndCollectThreads();
      if (result.is_error()) {
        Error(result.error_value());
        return std::nullopt;
      }
    }

    if (auto result = CollectCommon(flags, top, dumper_, holder); result.is_error()) {
      Error(result.error_value());
      return std::nullopt;
    }

    auto result = dumper_.CollectProcess(ChooseSegmentCallback(flags), flags.limit);
    if (result.is_error()) {
      Error(result.error_value());
      return std::nullopt;
    }

    return result.value();
  }

  // Phase 2: ???
  bool Dump(Writer& writer, const Flags& flags, const zxdump::TaskHolder& holder) {
    // File offset calculations start fresh in each ET_CORE file.
    writer.ResetOffset();

    // Now gather the accumulated header data first: not including the memory.
    // These iovecs will point into storage in the ProcessDump object itself.
    size_t total;
    if (auto result = dumper_.DumpHeaders(writer.AccumulateFragmentsCallback(), flags.limit);
        result.is_error()) {
      Error(result.error_value());
      return false;
    } else {
      total = result.value();
    }

    if (total > flags.limit) {
      writer.Error({.op_ = "not written"sv, .error_ = EFBIG});
      return false;
    }

    // All the fragments gathered above get written at once.
    if (auto result = writer.WriteFragments(); result.is_error()) {
      writer.Error(result.error_value());
      return false;
    }

    // Stream the memory out via a temporary buffer that's reused repeatedly
    // for each callback.
    if (auto memory = dumper_.DumpMemory(writer.WriteCallback(), flags.limit); memory.is_error()) {
      Error(memory.error_value());
      return false;
    }

    return true;
  }

 private:
  zxdump::SegmentCallback ChooseSegmentCallback(const Flags& flags) {
    if (!flags.dump_memory) {
      return PruneAll;
    }

    // TODO(mcgrathr): more filtering switches

    return cpp20::bind_front(&ProcessDumper::PruneDefault, this);
  }

  static fit::result<zxdump::Error, zxdump::SegmentDisposition> PruneAll(
      zxdump::SegmentDisposition segment, const zx_info_maps_t& mapping, const zx_info_vmo_t& vmo) {
    segment.filesz = 0;
    return fit::ok(segment);
  }

  fit::result<zxdump::Error, zxdump::SegmentDisposition> PruneDefault(
      zxdump::SegmentDisposition segment, const zx_info_maps_t& mapping, const zx_info_vmo_t& vmo) {
    if (mapping.u.mapping.committed_pages == 0 &&   // No private RAM here,
        vmo.parent_koid == ZX_KOID_INVALID &&       // and none shared,
        !(vmo.flags & ZX_INFO_VMO_PAGER_BACKED)) {  // and no backing store.
      // Since it's not pager-backed, there isn't data hidden in backing
      // store.  If we read this, it would just be zero-fill anyway.
      segment.filesz = 0;
    }

    // TODO(mcgrathr): for now, dump everything else.

    // Check for build ID.
    if (segment.filesz > 0 && zxdump::IsLikelyElfMapping(mapping)) {
      auto result = dumper_.FindBuildIdNote(mapping);
      if (result.is_error()) {
        return result.take_error();
      }
      segment.note = result.value();
      if (segment.note) {
        // TODO(mcgrathr): This could e.g. decide under some switch to truncate
        // the segment to just enough pages to include the build ID (usually
        // one).
        //
        // segment.filesz = PageAlign(note->vaddr + note->size) - mapping.base;
      }
    }

    return fit::ok(segment);
  }

  zxdump::ProcessDump dumper_;
};

// JobDumper handles dumping one job archive, either hierarchical or flattened.
class JobDumper : public DumperBase {
 public:
  explicit JobDumper(zxdump::Job& job) : DumperBase{job.koid()}, dumper_{job} {}

  auto OutputFile(const Flags& flags, bool outer = true) const {
    return flags.OutputFile(koid(), outer, kArchiveSuffix);
  }

  // The job dumper records the date of collection to use in the stub archive
  // member headers.  If the job archive is collected inside another archive,
  // this will also be the date in the member header for the nested archive.
  time_t date() const { return date_; }

  auto* operator->() { return &dumper_; }

  time_t ClockIn(const Flags& flags) {
    date_ = flags.Date(dumper_.job());
    return date_;
  }

  // Collect the job-wide data and reify the lists of children and processes.
  std::optional<size_t> Collect(const Flags& flags, bool top, const zxdump::TaskHolder& holder) {
    if (auto result = CollectCommon(flags, top, dumper_, holder); result.is_error()) {
      Error(result.error_value());
      return std::nullopt;
    }
    size_t size;
    if (auto result = dumper_.CollectJob(); result.is_error()) {
      Error(result.error_value());
      return std::nullopt;
    } else {
      size = result.value();
    }
    if (flags.collect_job_children) {
      if (auto result = dumper_.CollectChildren(); result.is_error()) {
        Error(result.error_value());
        return std::nullopt;
      } else {
        children_ = &(result.value().get());
      }
    }
    if (flags.collect_job_processes) {
      if (auto result = dumper_.CollectProcesses(); result.is_error()) {
        Error(result.error_value());
        return std::nullopt;
      } else {
        processes_ = &(result.value().get());
      }
    }
    return size;
  }

  // Dump the job archive: first dump the stub archive, and then collect and
  // dump each process and each child.
  bool Dump(Writer& writer, const Flags& flags, const zxdump::TaskHolder& holder);

 private:
  class CollectedJob;

  JobDumper(zxdump::JobDump job, zx_koid_t koid) : DumperBase{koid}, dumper_{std::move(job)} {}

  bool DumpHeaders(Writer& writer, const Flags& flags) {
    // File offset calculations start fresh in each archive.
    writer.ResetOffset();

    if (auto result = dumper_.DumpHeaders(writer.AccumulateFragmentsCallback(), date_);
        result.is_error()) {
      Error(result.error_value());
      return false;
    }

    auto result = writer.WriteFragments();
    if (result.is_error()) {
      writer.Error(result.error_value());
      return false;
    }

    return true;
  }

  static bool DumpMemberHeader(Writer& writer, std::string_view name, size_t size, time_t mtime) {
    // File offset calculations start fresh with each member.
    writer.ResetOffset();
    auto result = zxdump::JobDump::DumpMemberHeader(writer.WriteCallback(), 0, name, size, mtime);
    if (result.is_error()) {
      writer.Error(*result.error_value().dump_error_);
    }
    return result.is_ok();
  }

  zxdump::JobDump dumper_;
  zxdump::Job::JobMap* children_ = nullptr;
  zxdump::Job::ProcessMap* processes_ = nullptr;
  time_t date_ = 0;
};

// When dumping an hierarchical job archive, a CollectedJob object supports
// DeepCollect, that populates a tree of CollectedJob and CollectedProcess
// objects before the whole tree is dumped en masse.
class JobDumper::CollectedJob {
 public:
  CollectedJob(CollectedJob&&) = default;
  CollectedJob& operator=(CollectedJob&&) = default;

  explicit CollectedJob(JobDumper dumper) : dumper_(std::move(dumper)) {}

  // This is false either if the original Collect failed and this is an empty
  // object; or if any process or child collection failed so the archive is
  // still valid but just omits some processes and/or children.
  bool ok() const { return ok_; }

  // This includes the whole size of the job archive itself plus its
  // own member header as a member of its parent archive.
  size_t size_bytes() const { return MemberHeaderSize() + content_size_; }

  time_t date() const { return dumper_.date(); }

  // Returns true if the job itself was collected.
  // Later ok() indicates if any process or child collection failed.
  bool DeepCollect(const Flags& flags, const zxdump::TaskHolder& holder) {
    // Collect the job itself.
    dumper_.ClockIn(flags);
    if (auto collected_size = dumper_.Collect(flags, false, holder)) {
      content_size_ += *collected_size;

      // Collect all its processes and children.
      if (dumper_.processes_) {
        for (auto& [pid, process] : *dumper_.processes_) {
          CollectProcess(process, flags, holder);
        }
      }
      if (dumper_.children_) {
        for (auto& [koid, job] : *dumper_.children_) {
          CollectJob(job, flags, holder);
        }
      }
      return true;
    }
    ok_ = false;
    return false;
  }

  bool Dump(Writer& writer, const Flags& flags, const zxdump::TaskHolder& holder) {
    // First dump the member header for this archive as a member of its parent.
    // Then dump the "stub archive" describing the job itself.
    if (!writer.DumpMemberHeader(dumper_.OutputFile(flags, false), content_size_, date()) ||
        !dumper_.DumpHeaders(writer, flags)) {
      ok_ = false;
    } else {
      for (auto& process : processes_) {
        // Each CollectedProcess dumps its own member header and ET_CORE file.
        ok_ = process.Dump(writer, flags, holder) && ok_;
      }
      for (auto& job : children_) {
        // Recurse on each child to dump its own member header and job archive.
        ok_ = job.Dump(writer, flags, holder) && ok_;
      }
    }
    return ok_;
  }

 private:
  // At the leaves of the tree are processes still suspended after collection.
  class CollectedProcess {
   public:
    CollectedProcess(CollectedProcess&&) = default;
    CollectedProcess& operator=(CollectedProcess&&) = default;

    // Constructed with the process dumper and the result of Collect on it.
    CollectedProcess(ProcessDumper&& dumper, size_t size, time_t date)
        : dumper_(std::move(dumper)), content_size_(size), date_(date) {}

    // This includes the whole size of the ET_CORE file itself plus its
    // own member header as a member of its parent archive.
    size_t size_bytes() const { return MemberHeaderSize() + content_size_; }

    time_t date() const { return date_; }

    // Dump the member header and then the ET_CORE file contents.
    bool Dump(Writer& writer, const Flags& flags, const zxdump::TaskHolder& holder) {
      return writer.DumpMemberHeader(dumper_.OutputFile(flags, false), content_size_, date()) &&
             dumper_.Dump(writer, flags, holder);
    }

   private:
    ProcessDumper dumper_;
    size_t content_size_ = 0;
    time_t date_ = 0;
  };

  void CollectProcess(zxdump::Process& process, const Flags& flags,
                      const zxdump::TaskHolder& holder) {
    ProcessDumper dump{process};
    time_t dump_date = dump.ClockIn(flags);
    if (auto collected_size = dump.Collect(flags, false, holder)) {
      CollectedProcess core_file{std::move(dump), *collected_size, dump_date};
      content_size_ += core_file.size_bytes();
      processes_.push_back(std::move(core_file));
    } else {
      ok_ = false;
    }
  }

  void CollectJob(zxdump::Job& job, const Flags& flags, const zxdump::TaskHolder& holder) {
    CollectedJob archive{JobDumper{job}};
    if (archive.DeepCollect(flags, holder)) {
      content_size_ += archive.size_bytes();
      children_.push_back(std::move(archive));
    }
    // The job archive reports not OK if it was collected but omits some dumps.
    ok_ = archive.ok() && ok_;
  }

  JobDumper dumper_;
  std::vector<CollectedProcess> processes_;
  std::vector<CollectedJob> children_;
  size_t content_size_ = 0;
  bool ok_ = true;
};

bool JobDumper::Dump(Writer& writer, const Flags& flags, const zxdump::TaskHolder& holder) {
  if (!DumpHeaders(writer, flags)) {
    return false;
  }

  bool ok = true;
  if (processes_) {
    for (auto& [pid, process] : *processes_) {
      // Collect the process and thus discover the ET_CORE file size.
      ProcessDumper process_dump{process};
      time_t process_dump_date = process_dump.ClockIn(flags);
      if (auto collected_size = process_dump.Collect(flags, false, holder)) {
        // Dump the member header, now complete with size.
        if (!writer.DumpMemberHeader(process_dump.OutputFile(flags, false),  //
                                     *collected_size, process_dump_date)) {
          // Bail early for a write error, since later writes would fail too.
          return false;
        }
        // Now dump the member contents, the ET_CORE file for the process.
        ok = process_dump.Dump(writer, flags, holder) && ok;
      }
    }
  }

  if (children_) {
    for (auto& [koid, job] : *children_) {
      if (flags.flatten_jobs) {
        // Collect just this job first.
        JobDumper child{job};
        auto collected_job_size = child.Collect(flags, false, holder);
        ok = collected_job_size &&
             // Stream out the member header for just the stub archive alone.
             writer.DumpMemberHeader(child.OutputFile(flags, false),  //
                                     *collected_job_size, child.date()) &&
             // Now recurse to dump the stub archive followed by process and
             // child members.  Since the member header for the inner archive
             // only covers the stub archive, these become members in the outer
             // (flat) archive rather than members of the inner job archive.
             // Another inner recursion will do the same thing, so all the
             // recursions stream out a single flat archive.
             child.Dump(writer, flags, holder) && ok;
      } else {
        // Pre-collect the whole job tree and thus discover the archive size.
        // The pre-collected archive dumps its own member header first.
        CollectedJob archive{JobDumper{job}};
        ok = archive.DeepCollect(flags, holder) && archive.Dump(writer, flags, holder) && ok;
      }
    }
  }

  return ok;
}

fbl::unique_fd CreateOutputFile(const std::string& outfile) {
  fbl::unique_fd fd{open(outfile.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0666)};
  if (!fd) {
    perror(outfile.c_str());
  }
  return fd;
}

// Phase 3: Profit!
template <typename Dumper>
bool WriteDump(Dumper dumper, const Flags& flags, const zxdump::TaskHolder& holder) {
  time_t date = dumper.ClockIn(flags);

  if (flags.streaming) {
    Writer& writer = *flags.streaming;
    if (auto size = dumper.Collect(flags, true, holder)) {
      if (!flags.streaming_archive ||
          writer.DumpMemberHeader(dumper.OutputFile(flags, false), *size, date)) {
        return writer.Ok(dumper.Dump(writer, flags, holder));
      }
    }
    return false;
  }

  std::string outfile = dumper.OutputFile(flags);
  fbl::unique_fd fd = CreateOutputFile(outfile);
  if (!fd) {
    return false;
  }
  Writer writer{std::move(fd), std::move(outfile), flags.zstd};
  dumper.ClockIn(flags);
  return writer.Ok(dumper.Collect(flags, true, holder) && dumper.Dump(writer, flags, holder));
}

// "Dump" a job tree by actually just making separate dumps of each process.
// We only use the JobDumper to find the processes and/or children.
bool WriteManyCoreFiles(JobDumper dumper, const Flags& flags, const zxdump::TaskHolder& holder) {
  bool ok = true;

  if (flags.collect_job_processes) {
    if (auto result = dumper->CollectProcesses(); result.is_error()) {
      dumper.Error(result.error_value());
      ok = false;
    } else {
      for (auto& [pid, process] : result.value().get()) {
        ok = WriteDump(ProcessDumper{process}, flags, holder) && ok;
      }
    }
  }

  if (flags.collect_job_children) {
    if (auto result = dumper->CollectChildren(); result.is_error()) {
      dumper.Error(result.error_value());
      ok = false;
    } else {
      for (auto& [koid, job] : result.value().get()) {
        ok = WriteManyCoreFiles(JobDumper{job}, flags, holder) && ok;
      }
    }
  }

  return ok;
}

enum class RemarksType { kText, kJson, kBinary };

std::optional<Remarks> ParseRemarks(const char* arg, RemarksType type) {
  Remarks result;

  if (const char* eq = strchr(arg, '=')) {
    result.name = {arg, static_cast<size_t>(eq - arg)};
    arg = eq + 1;
  } else {
    if (type == RemarksType::kBinary) {
      std::cerr << "--remarks-raw requires NAME= prefix" << std::endl;
      return std::nullopt;
    }
    result.name = kDefaultRemarksName;
  }

  switch (type) {
    case RemarksType::kText:
      result.name += ".txt"sv;
      break;
    case RemarksType::kJson:
      result.name += ".json"sv;
      break;
    case RemarksType::kBinary:
      break;
  }

  constexpr auto error = [](const char* filename) -> std::ostream& {
    if (filename) {
      std::cerr << filename << ": "sv;
    }
    return std::cerr;
  };

  auto empty_remarks = [error](const char* filename = nullptr) {
    error(filename) << "empty remarks not allowed"sv << std::endl;
    return std::nullopt;
  };

  auto parse_json = [error, &result](auto&& stream, const char* filename = nullptr) {
    rapidjson::Reader reader;
    rapidjson::Writer<rapidjson::StringBuffer> writer(*result.data);
    if (!reader.Parse(stream, writer)) {
      error(filename) << "cannot parse JSON at offset " << reader.GetErrorOffset() << ": "
                      << GetParseError_En(reader.GetParseErrorCode()) << std::endl;
      return false;
    }
    return true;
  };

  if (arg[0] == '@') {
    // Read the response file.
    const char* filename = &arg[1];
    FILE* f = fopen(filename, "r");
    if (!f) {
      perror(filename);
      return std::nullopt;
    }
    auto close_f = fit::defer([f]() { fclose(f); });

    if (type == RemarksType::kJson) {
      char buffer[BUFSIZ];
      rapidjson::FileReadStream stream(f, buffer, sizeof(buffer));
      if (!parse_json(stream, filename)) {
        return std::nullopt;
      }
    } else {
      int c;
      while ((c = getc(f)) != EOF) {
        result.data->Put(static_cast<char>(c));
      }
      if (ferror(f)) {
        perror(filename);
        return std::nullopt;
      }
      if (result.data->GetSize() == 0) {
        return empty_remarks(filename);
      }
    }
  } else if (type == RemarksType::kJson) {
    if (!parse_json(rapidjson::StringStream(arg))) {
      return std::nullopt;
    }
  } else {
    std::string_view data{arg};
    if (data.empty()) {
      return empty_remarks();
    }
    data.copy(result.data->Push(data.size()), data.size());
  }

  return result;
}

constexpr const char kOptString[] = "hlo:OzamtcpJjfDUsSkKr:q:B:Rd:L";
constexpr const option kLongOpts[] = {
    {"help", no_argument, nullptr, 'h'},                 //
    {"limit", required_argument, nullptr, 'l'},          //
    {"output-prefix", required_argument, nullptr, 'o'},  //
    {"streaming", no_argument, nullptr, 'O'},            //
    {"zstd", no_argument, nullptr, 'z'},                 //
    {"exclude-memory", no_argument, nullptr, 'm'},       //
    {"no-threads", no_argument, nullptr, 't'},           //
    {"no-children", no_argument, nullptr, 'c'},          //
    {"no-processes", no_argument, nullptr, 'p'},         //
    {"jobs", no_argument, nullptr, 'J'},                 //
    {"job-archive", no_argument, nullptr, 'j'},          //
    {"flat-job-archive", no_argument, nullptr, 'f'},     //
    {"no-date", no_argument, nullptr, 'D'},              //
    {"date", no_argument, nullptr, 'U'},                 //
    {"system", no_argument, nullptr, 's'},               //
    {"system-recursive", no_argument, nullptr, 'S'},     //
    {"kernel", no_argument, nullptr, 'k'},               //
    {"kernel-recursive", no_argument, nullptr, 'K'},     //
    {"remarks", required_argument, nullptr, 'r'},        //
    {"remarks-json", required_argument, nullptr, 'q'},   //
    {"remarks-raw", required_argument, nullptr, 'B'},    //
    {"remarks-recursive", no_argument, nullptr, 'R'},    //
    {"root-job", no_argument, nullptr, 'a'},             //
    {"dump-file", required_argument, nullptr, 'd'},      //
    {"live", no_argument, nullptr, 'L'},                 //
    {nullptr, no_argument, nullptr, 0},                  //
};

}  // namespace

int main(int argc, char** argv) {
  Flags flags;
  bool streaming = false;
  const char* output_argument = nullptr;
  bool allow_jobs = false;
  constexpr auto handle_process = WriteDump<ProcessDumper>;
  auto handle_job = WriteManyCoreFiles;
  CommandLineHelper cli;

  auto usage = [&](int status = EXIT_FAILURE) {
    std::cerr << "Usage: " << argv[0] << R"""( [SWITCHES...] PID...

    --help, -h                         print this message
    --output-prefix=PREFIX, -o PREFIX  write <PREFIX><PID>, not core.<PID>
    --streaming, -O                    write streaming output
    --zstd, -z                         compress output files with zstd -11
    --limit=BYTES, -l BYTES            truncate output to BYTES per process
    --exclude-memory, -M               exclude all process memory from dumps
    --no-threads, -t                   collect only memory, threads left to run
    --jobs, -J                         allow PIDs to be job KOIDs instead
    --job-archive, -j                  write job archives, not process dumps
    --flat-job-archive, -f             write flattened job archives
    --no-children, -c                  don't recurse to child jobs
    --no-processes, -p                 don't dump processes found in jobs
    --no-date, -D                      don't record dates in dumps
    --date, -U                         record dates in dumps (default)
    --system, -s                       include system-wide information
    --system-recursive, -S             ... repeated in each child dump
    --kernel, -k                       include privileged kernel information
    --kernel-recursive, -K             ... repeated in each child dump
    --remarks=REMARKS, -r REMARKS      add dump remarks (UTF-8 text)
    --remarks-json=REMARKS, -q REMARKS add dump remarks (JSON)
    --remarks-raw=REMARKS, -B REMARKS  add dump remarks (raw binary)
    --remarks-recursive, -R            repeat dump remarks in each child dump
    --root-job, -a                     dump the root job
    --dump-file=FILE, -d FILE          read a previous dump file
    --live, -L                         use live data from the running system

By default, each PID must be the KOID of a process.

With --jobs, the KOID of a job is allowed.  Each process gets a separate dump
named for its individual PID.

With --job-archive, the KOID of a job is allowed.  Each job is dumped into a
job archive named <PREFIX><KOID>.a instead of producing per-process dump files.
If child jobs are dumped they become `core.<KOID>.a` archive members that are
themselves job archives.

With --no-children, don't recurse into child jobs of a job.
With --no-process, don't dump processes within a job, only its child jobs.
Using --no-process with --jobs rather than --job-archive means no dumps are
produced from job KOIDs at all, but valid job KOIDs are ignored rather than
causing errors.

REMARKS can be `NAME=@FILE` to read the remarks from the file, or `NAME=TEXT`
to use the literal text in the argument; just `@FILE` or just `TEXT` is like
`remarks=@FILE` or `remarks=TEXT`.  All text is expected to be in UTF-8.
Text for --remarks-json must parse as valid JSON but no particular schema is
expected; it is dumped as compact canonical UTF-8 JSON text.

With `--raw-remarks` (-B), REMARKS is still `NAME=CONTENTS` or `NAME=@FILE`,
but the contents are uninterpreted binary and `NAME` is expected to have its
own suffix rather than having `.txt` or `.json` appended.  Note that since
CONTENTS cannot have embedded NUL characters, using `@FILE` for binary data is
always recommended.

Each argument is dumped synchronously before processing the next argument.
Errors dumping each process are reported and cause a failing exit status at
the end of the run, but do not prevent additional processes from being dumped.
Without --no-threads, each process is held suspended while being dumped.
Processes within a job are dumped serially.  When dumping a child job inside a
job archive, all processes inside that whole subtree are held suspended until
the whole child job archive is dumped.

With --flat-job-archive, child job archives inside a job archive are instead
"stub" job archives that only describe the job itself.  A child job's process
and (grand)child job dumps are all included directly in the outer "flat" job
archive.  In this mode, only one process is held suspended at a time.

Jobs are always dumped while they continue to run and may omit new processes
or child jobs created after the dump collection begins.  Job dumps may report
process or child job KOIDs that were never dumped if they died during
collection.

With --root-job (-a), dump the root job.  Without --no-children, that means
dumping every job on the system; and without --no-process, it means dumping
every process on the system.  Doing this without --no-threads may deadlock
essential services.  PID arguments are not allowed with --root-job unless
--no-children is also given, since they would always be redundant.

With --streaming (-O), a single contiguous output stream is written, usually to
stdout.  If --output=FILE (-o FILE) is given along with --streaming (-O), then
it names a single output file to write in place of stdout rather than a prefix.
When there is a single PID argument or just the --root-job (-a) switch, then
the output stream is a single ELF core file or a single job archive file.  When
there are multiple PID arguments, or multiple separate single-process dumps
under --jobs (-J), or a fake root job from postportem data that doesn't form a
single job tree, the output stream is a simple archive that contains the
individual ELF core file or job archive file for each PID argument as member
files with the names used by default (core.<PID> or core.<PID>.a).  Readers
treat such an archive just like the collection of separate dump files.

By default, data for dumps is drawn from the running system.  Of course, this
only works on Fuchsia.  One or more --dump-file (-d) switches can be given to
read old postmortem data instead.  This allows, for example, extracting a
subset of the jobs or processes from the original dump set; merging multiple
dumps into one job archive; adding dump remarks; changing configuration details
to dump a subset of the original postmortem data; etc.  If no --dump-file (-d)
switches are given, then --live (-L) is the default.  Using --live (-L)
explicitly in combination with dump files is allowed, but the results may be
confusing either if the dumps are not from the current running system or if a
task found in the postmortem data is also still alive on the running system.
)""";
    return status;
  };

  while (true) {
    switch (getopt_long(argc, argv, kOptString, kLongOpts, nullptr)) {
      case -1:
        // This ends the loop.  All other cases continue (or return).
        break;

      case 'D':
        flags.record_date = false;
        continue;

      case 'U':
        flags.record_date = true;
        continue;

      case 'o':
        flags.output_prefix = optarg;
        output_argument = optarg;
        continue;

      case 'O':
        streaming = true;
        continue;

      case 'l': {
        char* p;
        flags.limit = strtoul(optarg, &p, 0);
        if (*p != '\0') {
          return usage();
        }
        continue;
      }

      case 'm':
        flags.dump_memory = false;
        continue;

      case 't':
        flags.collect_threads = false;
        continue;

      case 'f':
        flags.flatten_jobs = true;
        [[fallthrough]];

      case 'j':
        handle_job = WriteDump<JobDumper>;
        [[fallthrough]];

      case 'J':
        allow_jobs = true;
        continue;

      case 'c':
        flags.collect_job_children = false;
        continue;

      case 'p':
        flags.collect_job_processes = false;
        continue;

      case 'S':
        flags.repeat_system = true;
        [[fallthrough]];

      case 's':
        flags.collect_system = true;
        continue;

      case 'K':
        flags.repeat_kernel = true;
        [[fallthrough]];

      case 'k':
        flags.collect_kernel = true;
        continue;

      case 'r':
        if (auto note = ParseRemarks(optarg, RemarksType::kText)) {
          flags.remarks.push_back(std::move(*note));
          continue;
        }
        return usage();

      case 'R':
        flags.repeat_remarks = true;
        continue;

      case 'q':
        if (auto note = ParseRemarks(optarg, RemarksType::kJson)) {
          flags.remarks.push_back(std::move(*note));
          continue;
        }
        return usage();

      case 'B':
        if (auto note = ParseRemarks(optarg, RemarksType::kBinary)) {
          flags.remarks.push_back(std::move(*note));
          continue;
        }
        return usage();

      case 'a':
        cli.RootJobArgument();
        continue;

      case 'z':
        flags.zstd = true;
        continue;

      case 'd':
        cli.DumpFileArgument(optarg);
        continue;

      case 'L':
        cli.LiveArgument();
        continue;

      case 'h':
        return usage(EXIT_SUCCESS);

      default:
        return usage();
    }
    break;
  }

  cli.KoidArguments(argc, argv, optind, allow_jobs);

  cli.NeedInfoResource(flags.collect_kernel);
  cli.NeedSystem(flags.collect_system);

  if (cli.empty() && cli.ok()) {
    return usage();
  }

  constexpr auto is_job = [](zxdump::Task& task) { return task.type() == ZX_OBJ_TYPE_JOB; };

  auto call_dumper = [&](auto&& handle_task, auto dumper) {
    cli.Ok(handle_task(std::move(dumper), flags, cli.holder()));
  };

  auto dump_one_task = [&](zxdump::Task& task) {
    if (is_job(task)) {
      auto& job = static_cast<zxdump::Job&>(task);
      call_dumper(handle_job, JobDumper{job});
    } else {
      ZX_DEBUG_ASSERT(task.type() == ZX_OBJ_TYPE_PROCESS);
      auto& process = static_cast<zxdump::Process&>(task);
      call_dumper(handle_process, ProcessDumper{process});
    }
  };

  auto tasks = cli.take_tasks();

  if (streaming) {
    // There will be just one output stream with just one writer.
    fbl::unique_fd fd;
    std::string outname;
    if (output_argument) {
      outname = output_argument;
      fd = CreateOutputFile(outname);
      if (!fd) {
        return EXIT_FAILURE;
      }
    } else {
      fd.reset(STDOUT_FILENO);
    }

    // This gets the single writer passed down to all the dumpers.
    // When not streaming, each dumper makes its own writer.
    flags.streaming = std::make_unique<Writer>(std::move(fd), std::move(outname), flags.zstd);

    // If there will be more than one separate dump, switch to "streaming
    // archive" mode.  That is, if there are multiple separate KOID arguments
    // or the sole KOID is a job but under -J rather than -j.
    flags.streaming_archive =
        tasks.size() > 1 || (is_job(tasks.front()) && handle_job == WriteManyCoreFiles);

    if (flags.streaming_archive && !flags.streaming->StartArchive()) {
      return EXIT_FAILURE;
    }
  }

  while (!tasks.empty()) {
    zxdump::Task& task = tasks.front();
    tasks.pop();
    dump_one_task(task);
  }

  return cli.exit_status();
}
