// Copyright 2018 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 "report_attachments.h"

#include <memory>
#include <string>

#include <fuchsia/mem/cpp/fidl.h>
#include <lib/fxl/files/file.h>
#include <lib/fxl/files/path.h>
#include <lib/fxl/strings/concatenate.h>
#include <lib/fxl/strings/trim.h>
#include <lib/syslog/cpp/logger.h>
#include <third_party/crashpad/minidump/minidump_file_writer.h>
#include <third_party/crashpad/util/file/file_writer.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/syscalls/log.h>
#include <zircon/types.h>

namespace fuchsia {
namespace crash {

const char kAttachmentKernelLog[] = "kernel_log";
const char kAttachmentBuildInfoSnapshot[] = "build.snapshot";

std::string WriteKernelLogToFile(const std::string& dir) {
  std::string filename =
      files::SimplifyPath(fxl::Concatenate({dir, "/kernel_log.XXXXXX"}));
  base::ScopedFD fd(mkstemp(filename.data()));
  if (fd.get() < 0) {
    FX_LOGS(ERROR) << "could not create temp file";
    return std::string();
  }

  zx::log log;
  zx_status_t status = zx::log::create(ZX_LOG_FLAG_READABLE, &log);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "zx::log::create failed " << status;
    return std::string();
  }

  char buf[ZX_LOG_RECORD_MAX + 1];
  zx_log_record_t* rec = (zx_log_record_t*)buf;
  while (log.read(ZX_LOG_RECORD_MAX, rec, 0) > 0) {
    if (rec->datalen && (rec->data[rec->datalen - 1] == '\n')) {
      rec->datalen--;
    }
    rec->data[rec->datalen] = 0;

    dprintf(fd.get(), "[%05d.%03d] %05" PRIu64 ".%05" PRIu64 "> %s\n",
            (int)(rec->timestamp / 1000000000ULL),
            (int)((rec->timestamp / 1000000ULL) % 1000ULL), rec->pid, rec->tid,
            rec->data);
  }
  return filename;
}

namespace {

zx_status_t WriteVMO(crashpad::FileWriter* writer,
                     const fuchsia::mem::Buffer vmo) {
  // TODO(frousseau): make crashpad::FileWriter VMO-aware.
  std::unique_ptr<void, decltype(&free)> buffer(malloc(vmo.size), &free);
  zx_status_t status = vmo.vmo.read(buffer.get(), 0u, vmo.size);
  if (status != ZX_OK) {
    return ZX_ERR_INTERNAL;
  }
  writer->Write(buffer.get(), vmo.size);
  return ZX_OK;
}

zx_status_t AddAttachment(crashpad::CrashReportDatabase::NewReport* report,
                          const std::string& attachment_filename,
                          fuchsia::mem::Buffer content_buffer,
                          const std::string& debug_name) {
  crashpad::FileWriter* writer = report->AddAttachment(attachment_filename);
  if (!writer) {
    return ZX_ERR_INTERNAL;
  }
  if (zx_status_t status = WriteVMO(writer, std::move(content_buffer));
      status != ZX_OK) {
    FX_LOGS(ERROR) << "error writing " << debug_name
                   << " to file: " << zx_status_get_string(status);
    return ZX_ERR_INTERNAL;
  }
  return ZX_OK;
}

zx_status_t AddAttachment(crashpad::CrashReportDatabase::NewReport* report,
                          const std::string& attachment_filename,
                          const std::string& content_filepath) {
  crashpad::FileWriter* writer = report->AddAttachment(attachment_filename);
  if (!writer) {
    return ZX_ERR_INTERNAL;
  }
  std::string content;
  if (!files::ReadFileToString(content_filepath, &content)) {
    FX_LOGS(ERROR) << "Failed to read content from '" << content_filepath
                   << "'.";
    return ZX_ERR_INTERNAL;
  }
  content = fxl::TrimString(content, "\r\n").ToString();
  writer->Write(content.data(), content.size());
  return ZX_OK;
}

}  // namespace

zx_status_t AddManagedRuntimeExceptionAttachments(
    crashpad::CrashReportDatabase::NewReport* report,
    ManagedRuntimeLanguage language, fuchsia::mem::Buffer stack_trace) {
  const std::string& stack_trace_filename =
      (language == ManagedRuntimeLanguage::DART)
          ? "DartError"  // the crash server expects a specific name for Dart.
          : "stack_trace";
  AddAttachment(report, stack_trace_filename, std::move(stack_trace),
                "stack trace");
  AddAttachment(report, kAttachmentBuildInfoSnapshot,
                "/config/build-info/snapshot");
  // TODO(DX-581): attach syslog as well.
  // TODO(DX-748): attach kernel log as well.
  return ZX_OK;
}

zx_status_t AddKernelPanicAttachments(
    crashpad::CrashReportDatabase::NewReport* report,
    fuchsia::mem::Buffer crashlog) {
  AddAttachment(report, "log", std::move(crashlog), "kernel panic crashlog");
  AddAttachment(report, kAttachmentBuildInfoSnapshot,
                "/config/build-info/snapshot");
  return ZX_OK;
}

}  // namespace crash
}  // namespace fuchsia
