// Copyright 2015 The Crashpad Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "client/crash_report_database.h"

#include <windows.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <wchar.h>

#include <mutex>
#include <tuple>
#include <utility>

#include "base/check_op.h"
#include "base/logging.h"
#include "base/numerics/safe_math.h"
#include "base/strings/utf_string_conversions.h"
#include "client/settings.h"
#include "util/file/directory_reader.h"
#include "util/file/filesystem.h"
#include "util/misc/implicit_cast.h"
#include "util/misc/initialization_state_dcheck.h"
#include "util/misc/metrics.h"

namespace crashpad {

namespace {

constexpr wchar_t kReportsDirectory[] = L"reports";
constexpr wchar_t kMetadataFileName[] = L"metadata";

constexpr wchar_t kSettings[] = L"settings.dat";

constexpr wchar_t kCrashReportFileExtension[] = L"dmp";

constexpr uint32_t kMetadataFileHeaderMagic = 'CPAD';
constexpr uint32_t kMetadataFileVersion = 1;

using OperationStatus = CrashReportDatabase::OperationStatus;

// Helpers ---------------------------------------------------------------------

// Adds a string to the string table and returns the byte index where it was
// added.
uint32_t AddStringToTable(std::string* string_table, const std::string& str) {
  uint32_t offset = base::checked_cast<uint32_t>(string_table->size());
  *string_table += str;
  *string_table += '\0';
  return offset;
}

// Converts |str| to UTF8, adds the result to the string table and returns the
// byte index where it was added.
uint32_t AddStringToTable(std::string* string_table, const std::wstring& str) {
  return AddStringToTable(string_table, base::WideToUTF8(str));
}

// Reads from the current file position to EOF and returns as a string of bytes.
std::string ReadRestOfFileAsString(FileHandle file) {
  FileOffset read_from = LoggingSeekFile(file, 0, SEEK_CUR);
  FileOffset end = LoggingSeekFile(file, 0, SEEK_END);
  FileOffset original = LoggingSeekFile(file, read_from, SEEK_SET);
  if (read_from == -1 || end == -1 || original == -1 || read_from == end)
    return std::string();
  DCHECK_EQ(read_from, original);
  DCHECK_GT(end, read_from);
  size_t data_length = static_cast<size_t>(end - read_from);
  std::string buffer(data_length, '\0');
  return LoggingReadFileExactly(file, &buffer[0], data_length) ? buffer
                                                               : std::string();
}

bool UUIDFromReportPath(const base::FilePath& path, UUID* uuid) {
  return uuid->InitializeFromString(
      path.RemoveFinalExtension().BaseName().value());
}

// Helper structures, and conversions ------------------------------------------

// The format of the on disk metadata file is a MetadataFileHeader, followed by
// a number of fixed size records of MetadataFileReportRecord, followed by a
// string table in UTF8 format, where each string is \0 terminated.
struct MetadataFileHeader {
  uint32_t magic;
  uint32_t version;
  uint32_t num_records;
  uint32_t padding;
};

struct ReportDisk;

enum class ReportState {
  //! \brief Created and filled out by caller, owned by database.
  kPending,
  //! \brief In the process of uploading, owned by caller.
  kUploading,
  //! \brief Upload completed or skipped, owned by database.
  kCompleted,
};

enum {
  //! \brief Corresponds to uploaded bit of the report state.
  kAttributeUploaded = 1 << 0,

  //! \brief Corresponds to upload_explicity_requested bit of the report state.
  kAttributeUploadExplicitlyRequested = 1 << 1,
};

struct MetadataFileReportRecord {
  // Note that this default constructor does no initialization. It is used only
  // to create an array of records that are immediately initialized by reading
  // from disk in Metadata::Read().
  MetadataFileReportRecord() {}

  // Constructs from a ReportDisk, adding to |string_table| and storing indices
  // as strings into that table.
  MetadataFileReportRecord(const ReportDisk& report, std::string* string_table);

  UUID uuid;  // UUID is a 16 byte, standard layout structure.
  uint32_t file_path_index;  // Index into string table. File name is relative
                             // to the reports directory when on disk.
  uint32_t id_index;  // Index into string table.
  int64_t creation_time;  // Holds a time_t.
  int64_t last_upload_attempt_time;  // Holds a time_t.
  int32_t upload_attempts;
  int32_t state;  // A ReportState.
  uint8_t attributes;  // Bitfield of kAttribute*.
  uint8_t padding[7];
};

//! \brief A private extension of the Report class that includes additional data
//!     that's stored on disk in the metadata file.
struct ReportDisk : public CrashReportDatabase::Report {
  ReportDisk(const MetadataFileReportRecord& record,
             const base::FilePath& report_dir,
             const std::string& string_table);

  ReportDisk(const UUID& uuid,
             const base::FilePath& path,
             time_t creation_tim,
             ReportState state);

  //! \brief The current state of the report.
  ReportState state;
};

MetadataFileReportRecord::MetadataFileReportRecord(const ReportDisk& report,
                                                   std::string* string_table)
    : uuid(report.uuid),
      file_path_index(
          AddStringToTable(string_table, report.file_path.BaseName().value())),
      id_index(AddStringToTable(string_table, report.id)),
      creation_time(report.creation_time),
      last_upload_attempt_time(report.last_upload_attempt_time),
      upload_attempts(report.upload_attempts),
      state(static_cast<uint32_t>(report.state)),
      attributes((report.uploaded ? kAttributeUploaded : 0) |
                 (report.upload_explicitly_requested
                      ? kAttributeUploadExplicitlyRequested
                      : 0)) {
  memset(&padding, 0, sizeof(padding));
}

ReportDisk::ReportDisk(const MetadataFileReportRecord& record,
                       const base::FilePath& report_dir,
                       const std::string& string_table)
    : Report() {
  uuid = record.uuid;
  file_path = report_dir.Append(
      base::UTF8ToWide(&string_table[record.file_path_index]));
  id = &string_table[record.id_index];
  creation_time = record.creation_time;
  last_upload_attempt_time = record.last_upload_attempt_time;
  upload_attempts = record.upload_attempts;
  state = static_cast<ReportState>(record.state);
  uploaded = (record.attributes & kAttributeUploaded) != 0;
  upload_explicitly_requested =
      (record.attributes & kAttributeUploadExplicitlyRequested) != 0;
}

ReportDisk::ReportDisk(const UUID& uuid,
                       const base::FilePath& path,
                       time_t creation_time,
                       ReportState state)
    : Report() {
  this->uuid = uuid;
  this->file_path = path;
  this->creation_time = creation_time;
  this->state = state;
}

// Metadata --------------------------------------------------------------------

//! \brief Manages the metadata for the set of reports, handling serialization
//!     to disk, and queries.
class Metadata {
 public:
  Metadata(const Metadata&) = delete;
  Metadata& operator=(const Metadata&) = delete;

  //! \brief Writes any changes if necessary, unlocks and closes the file
  //!     handle.
  ~Metadata();

  static std::unique_ptr<Metadata> Create(
      const base::FilePath& metadata_file,
      const base::FilePath& report_dir,
      const base::FilePath& attachments_dir);

  //! \brief Adds a new report to the set.
  //!
  //! \param[in] new_report_disk The record to add. The #state field must be set
  //!     to kPending.
  void AddNewRecord(const ReportDisk& new_report_disk);

  //! \brief Finds all reports in a given state. The \a reports vector is only
  //!     valid when CrashReportDatabase::kNoError is returned.
  //!
  //! \param[in] desired_state The state to match.
  //! \param[out] reports Matching reports, must be empty on entry.
  OperationStatus FindReports(
      ReportState desired_state,
      std::vector<CrashReportDatabase::Report>* reports) const;

  //! \brief Finds the report matching the given UUID.
  //!
  //! The returned report is only valid if CrashReportDatabase::kNoError is
  //! returned.
  //!
  //! \param[in] uuid The report identifier.
  //! \param[out] report_disk The found report, valid only if
  //!     CrashReportDatabase::kNoError is returned. Ownership is not
  //!     transferred to the caller, and the report may not be modified.
  OperationStatus FindSingleReport(const UUID& uuid,
                                   const ReportDisk** report_disk) const;

  //! \brief Finds a single report matching the given UUID and in the desired
  //!     state, and returns a mutable ReportDisk* if found.
  //!
  //! This marks the metadata as dirty, and on destruction, changes will be
  //! written to disk via Write().
  //!
  //! \return #kNoError on success. #kReportNotFound if there was no report with
  //!     the specified UUID, or if the report was not in the specified state
  //!     and was not uploading. #kBusyError if the report was not in the
  //!     specified state and was uploading.
  OperationStatus FindSingleReportAndMarkDirty(const UUID& uuid,
                                               ReportState desired_state,
                                               ReportDisk** report_disk);

  //! \brief Removes a report from the metadata database, without touching the
  //!     on-disk file.
  //!
  //! The returned report is only valid if CrashReportDatabase::kNoError is
  //! returned. This will mark the database as dirty. Future metadata
  //! operations for this report will not succeed.
  //!
  //! \param[in] uuid The report identifier to remove.
  //! \param[out] report_path The found report's file_path, valid only if
  //!     CrashReportDatabase::kNoError is returned.
  OperationStatus DeleteReport(const UUID& uuid,
                               base::FilePath* report_path);

  //! \brief Removes reports from the metadata database, that don't have
  //!     corresponding report files.
  //!
  //! \return number of metadata entries removed
  int CleanDatabase();

 private:
  Metadata(FileHandle handle,
           const base::FilePath& report_dir,
           const base::FilePath& attachments_dir);

  bool Rewind();

  void Read();
  void Write();

  //! \brief Confirms that the corresponding report actually exists on disk
  //!     (that is, the dump file has not been removed), and that the report is
  //!     in the given state.
  static OperationStatus VerifyReport(const ReportDisk& report_disk,
                                      ReportState desired_state);
  //! \brief Confirms that the corresponding report actually exists on disk
  //!     (that is, the dump file has not been removed).
  static OperationStatus VerifyReportAnyState(const ReportDisk& report_disk);

  ScopedFileHandle handle_;
  const base::FilePath report_dir_;
  const base::FilePath attachments_dir_;
  bool dirty_;  //! \brief `true` when a Write() is required on destruction.
  std::vector<ReportDisk> reports_;
};

Metadata::~Metadata() {
  if (dirty_)
    Write();
  // Not actually async, UnlockFileEx requires the Offset fields.
  OVERLAPPED overlapped = {0};
  if (!UnlockFileEx(handle_.get(), 0, MAXDWORD, MAXDWORD, &overlapped))
    PLOG(ERROR) << "UnlockFileEx";
}

// static
std::unique_ptr<Metadata> Metadata::Create(
    const base::FilePath& metadata_file,
    const base::FilePath& report_dir,
    const base::FilePath& attachments_dir) {
  // It is important that dwShareMode be non-zero so that concurrent access to
  // this file results in a successful open. This allows us to get to LockFileEx
  // which then blocks to guard access.
  FileHandle handle = CreateFile(metadata_file.value().c_str(),
                                 GENERIC_READ | GENERIC_WRITE,
                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
                                 nullptr,
                                 OPEN_ALWAYS,
                                 FILE_ATTRIBUTE_NORMAL,
                                 nullptr);
  if (handle == kInvalidFileHandle)
    return std::unique_ptr<Metadata>();
  // Not actually async, LockFileEx requires the Offset fields.
  OVERLAPPED overlapped = {0};
  if (!LockFileEx(handle,
                  LOCKFILE_EXCLUSIVE_LOCK,
                  0,
                  MAXDWORD,
                  MAXDWORD,
                  &overlapped)) {
    PLOG(ERROR) << "LockFileEx";
    return std::unique_ptr<Metadata>();
  }

  std::unique_ptr<Metadata> metadata(
      new Metadata(handle, report_dir, attachments_dir));
  // If Read() fails, for whatever reason (corruption, etc.) metadata will not
  // have been modified and will be in a clean empty state. We continue on and
  // return an empty database to hopefully recover. This means that existing
  // crash reports have been orphaned.
  metadata->Read();
  return metadata;
}

void Metadata::AddNewRecord(const ReportDisk& new_report_disk) {
  DCHECK(new_report_disk.state == ReportState::kPending);
  reports_.push_back(new_report_disk);
  dirty_ = true;
}

OperationStatus Metadata::FindReports(
    ReportState desired_state,
    std::vector<CrashReportDatabase::Report>* reports) const {
  DCHECK(reports->empty());
  for (const auto& report : reports_) {
    if (report.state == desired_state &&
        VerifyReport(report, desired_state) == CrashReportDatabase::kNoError) {
      reports->push_back(report);
    }
  }
  return CrashReportDatabase::kNoError;
}

OperationStatus Metadata::FindSingleReport(
    const UUID& uuid,
    const ReportDisk** out_report) const {
  auto report_iter = std::find_if(
      reports_.begin(), reports_.end(), [uuid](const ReportDisk& report) {
        return report.uuid == uuid;
      });
  if (report_iter == reports_.end())
    return CrashReportDatabase::kReportNotFound;
  OperationStatus os = VerifyReportAnyState(*report_iter);
  if (os == CrashReportDatabase::kNoError)
    *out_report = &*report_iter;
  return os;
}

OperationStatus Metadata::FindSingleReportAndMarkDirty(
    const UUID& uuid,
    ReportState desired_state,
    ReportDisk** report_disk) {
  auto report_iter = std::find_if(
      reports_.begin(), reports_.end(), [uuid](const ReportDisk& report) {
        return report.uuid == uuid;
      });
  if (report_iter == reports_.end())
    return CrashReportDatabase::kReportNotFound;
  OperationStatus os = VerifyReport(*report_iter, desired_state);
  if (os == CrashReportDatabase::kNoError) {
    dirty_ = true;
    *report_disk = &*report_iter;
  }
  return os;
}

OperationStatus Metadata::DeleteReport(const UUID& uuid,
                                       base::FilePath* report_path) {
  auto report_iter = std::find_if(
      reports_.begin(), reports_.end(), [uuid](const ReportDisk& report) {
        return report.uuid == uuid;
      });
  if (report_iter == reports_.end())
    return CrashReportDatabase::kReportNotFound;
  *report_path = report_iter->file_path;
  reports_.erase(report_iter);
  dirty_ = true;
  return CrashReportDatabase::kNoError;
}

int Metadata::CleanDatabase() {
  int removed = 0;
  for (auto report_iter = reports_.begin(); report_iter != reports_.end();) {
    if (!IsRegularFile(report_iter->file_path)) {
      report_iter = reports_.erase(report_iter);
      ++removed;
      dirty_ = true;
    } else {
      ++report_iter;
    }
  }
  return removed;
}

Metadata::Metadata(FileHandle handle,
                   const base::FilePath& report_dir,
                   const base::FilePath& attachments_dir)
    : handle_(handle),
      report_dir_(report_dir),
      attachments_dir_(attachments_dir),
      dirty_(false),
      reports_() {}

bool Metadata::Rewind() {
  FileOffset result = LoggingSeekFile(handle_.get(), 0, SEEK_SET);
  DCHECK_EQ(result, 0);
  return result == 0;
}

void Metadata::Read() {
  FileOffset length = LoggingSeekFile(handle_.get(), 0, SEEK_END);
  if (length <= 0)  // Failed, or empty: Abort.
    return;
  if (!Rewind()) {
    LOG(ERROR) << "failed to rewind to read";
    return;
  }

  MetadataFileHeader header;
  if (!LoggingReadFileExactly(handle_.get(), &header, sizeof(header))) {
    LOG(ERROR) << "failed to read header";
    return;
  }
  if (header.magic != kMetadataFileHeaderMagic ||
      header.version != kMetadataFileVersion) {
    LOG(ERROR) << "unexpected header";
    return;
  }

  base::CheckedNumeric<uint32_t> records_size =
      base::CheckedNumeric<uint32_t>(header.num_records) *
      static_cast<uint32_t>(sizeof(MetadataFileReportRecord));
  if (!records_size.IsValid()) {
    LOG(ERROR) << "record size out of range";
    return;
  }

  std::vector<ReportDisk> reports;
  if (header.num_records > 0) {
    std::vector<MetadataFileReportRecord> records(header.num_records);
    if (!LoggingReadFileExactly(
            handle_.get(), &records[0], records_size.ValueOrDie())) {
      LOG(ERROR) << "failed to read records";
      return;
    }

    std::string string_table = ReadRestOfFileAsString(handle_.get());
    if (string_table.empty() || string_table.back() != '\0') {
      LOG(ERROR) << "bad string table";
      return;
    }

    for (const auto& record : records) {
      if (record.file_path_index >= string_table.size() ||
          record.id_index >= string_table.size()) {
        LOG(ERROR) << "invalid string table index";
        return;
      }
      ReportDisk report_disk(record, report_dir_, string_table);

      report_disk.total_size = GetFileSize(report_disk.file_path);
      base::FilePath report_attachment_dir =
          attachments_dir_.Append(report_disk.uuid.ToWString());
      report_disk.total_size += GetDirectorySize(report_attachment_dir);
      reports.push_back(report_disk);
    }
  }
  reports_.swap(reports);
}

void Metadata::Write() {
  if (!Rewind()) {
    LOG(ERROR) << "failed to rewind to write";
    return;
  }

  // Truncate to ensure that a partial write doesn't cause a mix of old and new
  // data causing an incorrect interpretation on read.
  if (!SetEndOfFile(handle_.get())) {
    PLOG(ERROR) << "failed to truncate";
    return;
  }

  size_t num_records = reports_.size();

  // Fill and write out the header.
  MetadataFileHeader header = {0};
  header.magic = kMetadataFileHeaderMagic;
  header.version = kMetadataFileVersion;
  header.num_records = base::checked_cast<uint32_t>(num_records);
  if (!LoggingWriteFile(handle_.get(), &header, sizeof(header))) {
    LOG(ERROR) << "failed to write header";
    return;
  }

  if (num_records == 0)
    return;

  // Build the records and string table we're going to write.
  std::string string_table;
  std::vector<MetadataFileReportRecord> records;
  records.reserve(num_records);
  for (const auto& report : reports_) {
    const base::FilePath& path = report.file_path;
    if (path.DirName() != report_dir_) {
      LOG(ERROR) << path << " expected to start with " << report_dir_;
      return;
    }
    records.push_back(MetadataFileReportRecord(report, &string_table));
  }

  if (!LoggingWriteFile(handle_.get(),
                        &records[0],
                        records.size() * sizeof(MetadataFileReportRecord))) {
    LOG(ERROR) << "failed to write records";
    return;
  }
  if (!LoggingWriteFile(
          handle_.get(), string_table.c_str(), string_table.size())) {
    LOG(ERROR) << "failed to write string table";
    return;
  }
}

// static
OperationStatus Metadata::VerifyReportAnyState(const ReportDisk& report_disk) {
  DWORD fileattr = GetFileAttributes(report_disk.file_path.value().c_str());
  if (fileattr == INVALID_FILE_ATTRIBUTES)
    return CrashReportDatabase::kReportNotFound;
  return (fileattr & FILE_ATTRIBUTE_DIRECTORY)
             ? CrashReportDatabase::kFileSystemError
             : CrashReportDatabase::kNoError;
}

// static
OperationStatus Metadata::VerifyReport(const ReportDisk& report_disk,
                                       ReportState desired_state) {
  if (report_disk.state == desired_state) {
    return VerifyReportAnyState(report_disk);
  }

  return report_disk.state == ReportState::kUploading
             ? CrashReportDatabase::kBusyError
             : CrashReportDatabase::kReportNotFound;
}

bool EnsureDirectory(const base::FilePath& path) {
  DWORD fileattr = GetFileAttributes(path.value().c_str());
  if (fileattr == INVALID_FILE_ATTRIBUTES) {
    PLOG(ERROR) << "GetFileAttributes " << path;
    return false;
  }
  if ((fileattr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
    LOG(ERROR) << "GetFileAttributes " << path << ": not a directory";
    return false;
  }
  return true;
}

//! \brief Ensures that the node at path is a directory, and creates it if it
//!     does not exist.
//!
//! \return If the path points to a file, rather than a directory, or the
//!     directory could not be created, returns `false`. Otherwise, returns
//!     `true`, indicating that path already was or now is a directory.
bool CreateDirectoryIfNecessary(const base::FilePath& path) {
  if (CreateDirectory(path.value().c_str(), nullptr))
    return true;
  if (GetLastError() != ERROR_ALREADY_EXISTS) {
    PLOG(ERROR) << "CreateDirectory " << base::WideToUTF8(path.value());
    return false;
  }
  return EnsureDirectory(path);
}

}  // namespace

// CrashReportDatabaseWin ------------------------------------------------------

class CrashReportDatabaseWin : public CrashReportDatabase {
 public:
  explicit CrashReportDatabaseWin(const base::FilePath& path);

  CrashReportDatabaseWin(const CrashReportDatabaseWin&) = delete;
  CrashReportDatabaseWin& operator=(const CrashReportDatabaseWin&) = delete;

  ~CrashReportDatabaseWin() override;

  bool Initialize(bool may_create);

  // CrashReportDatabase:
  Settings* GetSettings() override;
  OperationStatus PrepareNewCrashReport(
      std::unique_ptr<NewReport>* report) override;
  OperationStatus FinishedWritingCrashReport(std::unique_ptr<NewReport> report,
                                             UUID* uuid) override;
  OperationStatus LookUpCrashReport(const UUID& uuid, Report* report) override;
  OperationStatus GetPendingReports(std::vector<Report>* reports) override;
  OperationStatus GetCompletedReports(std::vector<Report>* reports) override;
  OperationStatus GetReportForUploading(
      const UUID& uuid,
      std::unique_ptr<const UploadReport>* report,
      bool report_metrics) override;
  OperationStatus SkipReportUpload(const UUID& uuid,
                                   Metrics::CrashSkippedReason reason) override;
  OperationStatus DeleteReport(const UUID& uuid) override;
  OperationStatus RequestUpload(const UUID& uuid) override;
  int CleanDatabase(time_t lockfile_ttl) override;
  base::FilePath DatabasePath() override;

 private:
  // CrashReportDatabase:
  OperationStatus RecordUploadAttempt(UploadReport* report,
                                      bool successful,
                                      const std::string& id) override;

  // Cleans any attachments that have no associated report.
  void CleanOrphanedAttachments();

  std::unique_ptr<Metadata> AcquireMetadata();

  Settings& SettingsInternal() {
    std::call_once(settings_init_, [this]() {
      settings_.Initialize(base_dir_.Append(kSettings));
    });
    return settings_;
  }

  base::FilePath base_dir_;
  Settings settings_;
  std::once_flag settings_init_;
  InitializationStateDcheck initialized_;
};

CrashReportDatabaseWin::CrashReportDatabaseWin(const base::FilePath& path)
    : CrashReportDatabase(),
      base_dir_(path),
      settings_(),
      settings_init_(),
      initialized_() {}

CrashReportDatabaseWin::~CrashReportDatabaseWin() {
}

bool CrashReportDatabaseWin::Initialize(bool may_create) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);

  // Ensure the database directory exists.
  if (may_create) {
    if (!CreateDirectoryIfNecessary(base_dir_))
      return false;
  } else if (!EnsureDirectory(base_dir_)) {
    return false;
  }

  // Ensure that the report subdirectory exists.
  if (!CreateDirectoryIfNecessary(base_dir_.Append(kReportsDirectory)))
    return false;

  if (!CreateDirectoryIfNecessary(AttachmentsRootPath()))
    return false;

  INITIALIZATION_STATE_SET_VALID(initialized_);
  return true;
}

base::FilePath CrashReportDatabaseWin::DatabasePath() {
  return base_dir_;
}

Settings* CrashReportDatabaseWin::GetSettings() {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  return &SettingsInternal();
}

OperationStatus CrashReportDatabaseWin::PrepareNewCrashReport(
    std::unique_ptr<NewReport>* report) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<NewReport> new_report(new NewReport());
  if (!new_report->Initialize(this,
                              base_dir_.Append(kReportsDirectory),
                              std::wstring(L".") + kCrashReportFileExtension)) {
    return kFileSystemError;
  }

  report->reset(new_report.release());
  return kNoError;
}

OperationStatus CrashReportDatabaseWin::FinishedWritingCrashReport(
    std::unique_ptr<NewReport> report,
    UUID* uuid) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;
  metadata->AddNewRecord(ReportDisk(report->ReportID(),
                                    report->file_remover_.get(),
                                    time(nullptr),
                                    ReportState::kPending));

  std::ignore = report->file_remover_.release();

  // Close all the attachments and disarm their removers too.
  for (auto& writer : report->attachment_writers_) {
    writer->Close();
  }
  for (auto& remover : report->attachment_removers_) {
    std::ignore = remover.release();
  }

  *uuid = report->ReportID();

  Metrics::CrashReportPending(Metrics::PendingReportReason::kNewlyCreated);
  Metrics::CrashReportSize(report->Writer()->Seek(0, SEEK_END));

  return kNoError;
}

OperationStatus CrashReportDatabaseWin::LookUpCrashReport(const UUID& uuid,
                                                          Report* report) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;
  // Find and return a copy of the matching report.
  const ReportDisk* report_disk;
  OperationStatus os = metadata->FindSingleReport(uuid, &report_disk);
  if (os == kNoError)
    *report = *report_disk;
  return os;
}

OperationStatus CrashReportDatabaseWin::GetPendingReports(
    std::vector<Report>* reports) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  return metadata ? metadata->FindReports(ReportState::kPending, reports)
                  : kDatabaseError;
}

OperationStatus CrashReportDatabaseWin::GetCompletedReports(
    std::vector<Report>* reports) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  return metadata ? metadata->FindReports(ReportState::kCompleted, reports)
                  : kDatabaseError;
}

OperationStatus CrashReportDatabaseWin::GetReportForUploading(
    const UUID& uuid,
    std::unique_ptr<const UploadReport>* report,
    bool report_metrics) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;

  ReportDisk* report_disk;
  OperationStatus os = metadata->FindSingleReportAndMarkDirty(
      uuid, ReportState::kPending, &report_disk);
  if (os == kNoError) {
    report_disk->state = ReportState::kUploading;
    auto upload_report = std::make_unique<UploadReport>();
    *implicit_cast<Report*>(upload_report.get()) = *report_disk;

    if (!upload_report->Initialize(upload_report->file_path, this)) {
      return kFileSystemError;
    }
    upload_report->report_metrics_ = report_metrics;

    report->reset(upload_report.release());
  }
  return os;
}

OperationStatus CrashReportDatabaseWin::RecordUploadAttempt(
    UploadReport* report,
    bool successful,
    const std::string& id) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  if (report->report_metrics_) {
    Metrics::CrashUploadAttempted(successful);
  }

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;
  ReportDisk* report_disk;
  OperationStatus os = metadata->FindSingleReportAndMarkDirty(
      report->uuid, ReportState::kUploading, &report_disk);
  if (os != kNoError)
    return os;

  time_t now = time(nullptr);

  report_disk->uploaded = successful;
  report_disk->id = id;
  report_disk->last_upload_attempt_time = now;
  report_disk->upload_attempts++;
  if (successful) {
    report_disk->state = ReportState::kCompleted;
    report_disk->upload_explicitly_requested = false;
  } else {
    report_disk->state = ReportState::kPending;
    report_disk->upload_explicitly_requested =
        report->upload_explicitly_requested;
  }

  if (!SettingsInternal().SetLastUploadAttemptTime(now))
    return kDatabaseError;

  return kNoError;
}

OperationStatus CrashReportDatabaseWin::DeleteReport(const UUID& uuid) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;

  base::FilePath report_path;
  OperationStatus os = metadata->DeleteReport(uuid, &report_path);
  if (os != kNoError)
    return os;

  if (!DeleteFile(report_path.value().c_str())) {
    PLOG(ERROR) << "DeleteFile " << report_path;
    return kFileSystemError;
  }

  RemoveAttachmentsByUUID(uuid);

  return kNoError;
}

OperationStatus CrashReportDatabaseWin::SkipReportUpload(
    const UUID& uuid,
    Metrics::CrashSkippedReason reason) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  Metrics::CrashUploadSkipped(reason);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;
  ReportDisk* report_disk;
  OperationStatus os = metadata->FindSingleReportAndMarkDirty(
      uuid, ReportState::kPending, &report_disk);
  if (os == kNoError) {
    report_disk->state = ReportState::kCompleted;
    report_disk->upload_explicitly_requested = false;
  }
  return os;
}

std::unique_ptr<Metadata> CrashReportDatabaseWin::AcquireMetadata() {
  base::FilePath metadata_file = base_dir_.Append(kMetadataFileName);
  return Metadata::Create(metadata_file,
                          base_dir_.Append(kReportsDirectory),
                          AttachmentsRootPath());
}

std::unique_ptr<CrashReportDatabase> InitializeInternal(
    const base::FilePath& path,
    bool may_create) {
  std::unique_ptr<CrashReportDatabaseWin> database_win(
      new CrashReportDatabaseWin(path));
  return database_win->Initialize(may_create)
             ? std::move(database_win)
             : std::unique_ptr<CrashReportDatabaseWin>();
}

OperationStatus CrashReportDatabaseWin::RequestUpload(const UUID& uuid) {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());
  if (!metadata)
    return kDatabaseError;

  ReportDisk* report_disk;
  // TODO(gayane): Search for the report only once regardless of its state.
  OperationStatus os = metadata->FindSingleReportAndMarkDirty(
      uuid, ReportState::kCompleted, &report_disk);
  if (os == kReportNotFound) {
    os = metadata->FindSingleReportAndMarkDirty(
        uuid, ReportState::kPending, &report_disk);
  }

  if (os != kNoError)
    return os;

  // If the crash report has already been uploaded, don't request new upload.
  if (report_disk->uploaded)
    return kCannotRequestUpload;

  // Mark the crash report as having upload explicitly requested by the user,
  // and move it to the pending state.
  report_disk->upload_explicitly_requested = true;
  report_disk->state = ReportState::kPending;

  Metrics::CrashReportPending(Metrics::PendingReportReason::kUserInitiated);

  return kNoError;
}

int CrashReportDatabaseWin::CleanDatabase(time_t lockfile_ttl) {
  int removed = 0;
  const base::FilePath dir_path(base_dir_.Append(kReportsDirectory));
  DirectoryReader reader;
  if (!reader.Open(dir_path)) {
    return removed;
  }

  base::FilePath filename;
  DirectoryReader::Result result;
  time_t now = time(nullptr);

  std::unique_ptr<Metadata> metadata(AcquireMetadata());

  // Remove old reports without metadata.
  while ((result = reader.NextFile(&filename)) ==
         DirectoryReader::Result::kSuccess) {
    timespec filetime;
    const base::FilePath report_path(dir_path.Append(filename));
    if (!FileModificationTime(report_path, &filetime) ||
        filetime.tv_sec > now - lockfile_ttl) {
      continue;
    }

    const ReportDisk* report_disk;
    UUID uuid;
    bool is_uuid = UUIDFromReportPath(report_path, &uuid);
    // ignore files whose base name is not uuid
    if (!is_uuid) {
      continue;
    }
    OperationStatus os = metadata->FindSingleReport(uuid, &report_disk);

    if (os == OperationStatus::kReportNotFound) {
      if (LoggingRemoveFile(report_path)) {
        ++removed;
        RemoveAttachmentsByUUID(uuid);
      }
      continue;
    }
  }

  // Remove any metadata records without report files.
  removed += metadata->CleanDatabase();

  CleanOrphanedAttachments();
  return removed;
}

void CrashReportDatabaseWin::CleanOrphanedAttachments() {
  base::FilePath root_attachments_dir = AttachmentsRootPath();
  DirectoryReader reader;
  if (!reader.Open(root_attachments_dir)) {
    return;
  }

  base::FilePath filename;
  DirectoryReader::Result result;
  base::FilePath reports_dir = base_dir_.Append(kReportsDirectory);
  while ((result = reader.NextFile(&filename)) ==
         DirectoryReader::Result::kSuccess) {
    const base::FilePath path(root_attachments_dir.Append(filename));
    if (IsDirectory(path, false)) {
      UUID uuid;
      if (!uuid.InitializeFromString(filename.value())) {
        LOG(ERROR) << "unexpected attachment dir name " << filename;
        continue;
      }

      // Remove attachments if corresponding report doen't exist.
      base::FilePath report_path =
          reports_dir.Append(uuid.ToWString() + kCrashReportFileExtension);
      if (!IsRegularFile(report_path)) {
        RemoveAttachmentsByUUID(uuid);
      }
    }
  }
}

// static
std::unique_ptr<CrashReportDatabase> CrashReportDatabase::Initialize(
    const base::FilePath& path) {
  return InitializeInternal(path, true);
}

// static
std::unique_ptr<CrashReportDatabase>
CrashReportDatabase::InitializeWithoutCreating(const base::FilePath& path) {
  return InitializeInternal(path, false);
}

}  // namespace crashpad
