// 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/zxdump/dump.h>
#include <lib/zxdump/fd-writer.h>
#include <zircon/assert.h>
#include <zircon/status.h>

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

#include <fbl/unique_fd.h>
#include <task-utils/get.h>

namespace {

using namespace std::literals;

// 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) const {
    std::string filename{output_prefix_ ? *output_prefix_ : "core."sv};
    filename += std::to_string(pid);
    return filename;
  }

  std::optional<std::string_view> output_prefix_;
  size_t limit_ = zxdump::DefaultLimit();
};

// 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 zxdump::FdWriter {
 public:
  Writer(fbl::unique_fd fd, std::string filename)
      : zxdump::FdWriter{std::move(fd)}, filename_{std::move(filename)} {}

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

  // Called with true if the output file should be preserved at destruction.
  bool Ok(bool ok) {
    if (ok) {
      filename_.clear();
    }
    return ok;
  }

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

 private:
  std::string filename_;
};

// This handles collecting and producing the dump for one process.
// The Writer and Flags objects get passed in to control the details
// and of the dump and where it goes.
class ProcessDumper {
 public:
  ProcessDumper(zx::unowned_process process, zx_koid_t pid)
      : dumper_{std::move(process)}, pid_(pid) {}

  // Read errors from syscalls use the PID.
  void Error(const zxdump::Error& error) const {
    std::cerr << pid_ << ": "sv << error << std::endl;
  }

  // Phase 1: Collect underpants!
  bool Collect(const Flags& flags) {
    auto result = dumper_.CollectProcess(flags.limit_);
    if (result.is_error()) {
      Error(result.error_value());
      return false;
    }
    return true;
  }

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

    // Now write 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()) {
      writer.Error(result.error_value());
      return false;
    } else {
      total = result.value();
    }

    if (total > flags.limit_) {
      errno = EFBIG;
      writer.Error("not written");
      return false;
    }

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

    return true;
  }

 private:
  zxdump::ProcessDump<zx::unowned_process> dumper_;
  zx_koid_t pid_;
};

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!
bool WriteProcessCoreFile(zx::process process, zx_koid_t pid, const Flags& flags) {
  std::string outfile = flags.OutputFile(pid);
  fbl::unique_fd fd = CreateOutputFile(outfile);
  if (!fd) {
    return false;
  }
  Writer writer{std::move(fd), std::move(outfile)};
  ProcessDumper dumper{zx::unowned_process{process}, pid};
  return writer.Ok(dumper.Collect(flags) && dumper.Dump(writer, flags));
}

constexpr const char kOptString[] = "hlo:";
constexpr const option kLongOpts[] = {
    {"help", no_argument, nullptr, 'h'},                 //
    {"limit", required_argument, nullptr, 'l'},          //
    {"output-prefix", required_argument, nullptr, 'o'},  //
    {nullptr, no_argument, nullptr, 0},                  //
};

}  // namespace

int main(int argc, char** argv) {
  Flags flags;

  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>
    --limit=BYTES, -l BYTES            truncate output to BYTES per process
)""";
    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 'o':
        flags.output_prefix_ = optarg;
        continue;

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

      default:
        return usage(EXIT_SUCCESS);
    }
    break;
  }

  if (optind == argc) {
    return usage();
  }

  int exit_status = EXIT_SUCCESS;
  for (int i = optind; i < argc; ++i) {
    char* p;
    zx_koid_t pid = strtoul(argv[i], &p, 0);
    if (*p != '\0') {
      std::cerr << "Not a PID (KOID): " << argv[i] << std::endl;
      return usage();
    }

    zx_obj_type_t type;
    zx_handle_t handle;
    zx_status_t status = get_task_by_koid(pid, &type, &handle);
    if (status != ZX_OK) {
      std::cerr << pid << ": " << zx_status_get_string(status) << std::endl;
      status = EXIT_FAILURE;
      continue;
    }

    switch (type) {
      default:
        std::cerr << pid << ": KOID is not a process\n";
        zx_handle_close(handle);
        exit_status = EXIT_FAILURE;
        break;

      case ZX_OBJ_TYPE_PROCESS:
        if (!WriteProcessCoreFile(zx::process{handle}, pid, flags)) {
          exit_status = EXIT_FAILURE;
        }
        break;
    }
  }

  return exit_status;
}
