// Copyright 2017 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 "garnet/lib/far/archive_reader.h"

#include <inttypes.h>
#include <unistd.h>

#include <limits>
#include <utility>

#include "garnet/lib/far/file_operations.h"
#include "garnet/lib/far/format.h"
#include "src/lib/files/directory.h"
#include "src/lib/files/path.h"
#include "src/lib/fxl/strings/concatenate.h"

namespace archive {
namespace {

struct PathComparator {
  const ArchiveReader* reader = nullptr;

  bool operator()(const DirectoryTableEntry& lhs, const fxl::StringView& rhs) {
    return reader->GetPathView(lhs) < rhs;
  }
};

}  // namespace

ArchiveReader::ArchiveReader(fxl::UniqueFD fd) : fd_(std::move(fd)) {}

ArchiveReader::~ArchiveReader() = default;

bool ArchiveReader::Read() { return ReadIndex() && ReadDirectory(); }

bool ArchiveReader::Extract(fxl::StringView output_dir) const {
  for (const auto& entry : directory_table_) {
    std::string path = fxl::Concatenate({output_dir, "/", GetPathView(entry)});
    std::string dir = files::GetDirectoryName(path);
    if (!dir.empty() && !files::IsDirectory(dir) &&
        !files::CreateDirectory(dir)) {
      fprintf(stderr, "error: Failed to create directory '%s'.\n", dir.c_str());
      return false;
    }
    if (lseek(fd_.get(), entry.data_offset, SEEK_SET) < 0) {
      fprintf(stderr, "error: Failed to seek to offset of file.\n");
      return false;
    }
    if (!CopyFileToPath(fd_.get(), path.c_str(), entry.data_length)) {
      fprintf(stderr, "error: Failed write contents to '%s'.\n", path.c_str());
      return false;
    }
  }
  return true;
}

bool ArchiveReader::ExtractFile(fxl::StringView archive_path,
                                const char* output_path) const {
  DirectoryTableEntry entry;
  if (!GetDirectoryEntryByPath(archive_path, &entry))
    return false;
  if (lseek(fd_.get(), entry.data_offset, SEEK_SET) < 0) {
    fprintf(stderr, "error: Failed to seek to offset of file.\n");
    return false;
  }
  if (!CopyFileToPath(fd_.get(), output_path, entry.data_length)) {
    fprintf(stderr, "error: Failed write contents to '%s'.\n", output_path);
    return false;
  }
  return true;
}

bool ArchiveReader::CopyFile(fxl::StringView archive_path, int dst_fd) const {
  DirectoryTableEntry entry;
  if (!GetDirectoryEntryByPath(archive_path, &entry))
    return false;
  if (lseek(fd_.get(), entry.data_offset, SEEK_SET) < 0) {
    fprintf(stderr, "error: Failed to seek to offset of file.\n");
    return false;
  }
  if (!CopyFileToFile(fd_.get(), dst_fd, entry.data_length)) {
    fprintf(stderr, "error: Failed write contents.\n");
    return false;
  }
  return true;
}

bool ArchiveReader::GetDirectoryEntryByIndex(uint64_t index,
                                             DirectoryTableEntry* entry) const {
  if (index >= directory_table_.size())
    return false;
  *entry = directory_table_[index];
  return true;
}

bool ArchiveReader::GetDirectoryEntryByPath(fxl::StringView archive_path,
                                            DirectoryTableEntry* entry) const {
  uint64_t index = 0;
  return GetDirectoryIndexByPath(archive_path, &index) &&
         GetDirectoryEntryByIndex(index, entry);
}

bool ArchiveReader::GetDirectoryIndexByPath(fxl::StringView archive_path,
                                            uint64_t* index) const {
  PathComparator comparator;
  comparator.reader = this;

  auto it = std::lower_bound(directory_table_.begin(), directory_table_.end(),
                             archive_path, comparator);
  if (it == directory_table_.end() || GetPathView(*it) != archive_path)
    return false;
  *index = it - directory_table_.begin();
  return true;
}

fxl::UniqueFD ArchiveReader::TakeFileDescriptor() { return std::move(fd_); }

fxl::StringView ArchiveReader::GetPathView(
    const DirectoryTableEntry& entry) const {
  return fxl::StringView(path_data_.data() + entry.name_offset,
                         entry.name_length);
}

bool ArchiveReader::ReadIndex() {
  if (lseek(fd_.get(), 0, SEEK_SET) < 0) {
    fprintf(stderr, "error: Failed to seek to beginning of archive.\n");
    return false;
  }

  IndexChunk index_chunk;
  if (!ReadObject(fd_.get(), &index_chunk)) {
    fprintf(stderr,
            "error: Failed read index chunk. Is this file an archive?\n");
    return false;
  }

  if (index_chunk.magic != kMagic) {
    fprintf(stderr,
            "error: Index chunk missing magic. Is this file an archive?\n");
    return false;
  }

  if (index_chunk.length % sizeof(IndexEntry) != 0 ||
      index_chunk.length >
          std::numeric_limits<uint64_t>::max() - sizeof(IndexChunk)) {
    fprintf(stderr, "error: Invalid index chunk length.\n");
    return false;
  }

  index_.resize(index_chunk.length / sizeof(IndexEntry));
  if (!ReadVector(fd_.get(), &index_)) {
    fprintf(stderr, "error: Failed to read contents of index chunk.\n");
    return false;
  }

  uint64_t next_offset = sizeof(IndexChunk) + index_chunk.length;
  for (const auto& entry : index_) {
    if (entry.offset != next_offset) {
      fprintf(stderr,
              "error: Chunk at offset %" PRIu64 " not tightly packed.\n",
              entry.offset);
      return false;
    }
    if (entry.length % 8 != 0) {
      fprintf(stderr,
              "error: Chunk length %" PRIu64
              " not aligned to 8 byte boundary.\n",
              entry.length);
      return false;
    }
    if (entry.length > std::numeric_limits<uint64_t>::max() - entry.offset) {
      fprintf(stderr,
              "error: Chunk length %" PRIu64
              " overflowed total archive size.\n",
              entry.length);
      return false;
    }
    next_offset = entry.offset + entry.length;
  }

  return true;
}

bool ArchiveReader::ReadDirectory() {
  const IndexEntry* dir_entry = GetIndexEntry(kDirType);
  if (!dir_entry) {
    fprintf(stderr, "error: Cannot find directory chunk.\n");
    return false;
  }
  if (dir_entry->length % sizeof(DirectoryTableEntry) != 0) {
    fprintf(stderr, "error: Invalid directory chunk length: %" PRIu64 ".\n",
            dir_entry->length);
    return false;
  }
  uint64_t file_count = dir_entry->length / sizeof(DirectoryTableEntry);
  directory_table_.resize(file_count);

  if (lseek(fd_.get(), dir_entry->offset, SEEK_SET) < 0) {
    fprintf(stderr, "error: Failed to seek to directory chunk.\n");
    return false;
  }
  if (!ReadVector(fd_.get(), &directory_table_)) {
    fprintf(stderr, "error: Failed to read directory table.\n");
    return false;
  }

  const IndexEntry* dirnames_entry = GetIndexEntry(kDirnamesType);
  if (!dirnames_entry) {
    fprintf(stderr, "error: Cannot find directory names chunk.\n");
    return false;
  }
  path_data_.resize(dirnames_entry->length);

  if (lseek(fd_.get(), dirnames_entry->offset, SEEK_SET) < 0) {
    fprintf(stderr, "error: Failed to seek to directory names chunk.\n");
    return false;
  }
  if (!ReadVector(fd_.get(), &path_data_)) {
    fprintf(stderr, "error: Failed to read directory names.\n");
    return false;
  }

  return true;
}

const IndexEntry* ArchiveReader::GetIndexEntry(uint64_t type) const {
  for (auto& entry : index_) {
    if (entry.type == type)
      return &entry;
  }
  return nullptr;
}

}  // namespace archive
