// 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 "src/sys/pkg/lib/far/cpp/archive_writer.h"

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <algorithm>
#include <limits>
#include <string>
#include <vector>

#include <fbl/unique_fd.h>

#include "src/lib/files/file_descriptor.h"
#include "src/sys/pkg/lib/far/cpp/alignment.h"
#include "src/sys/pkg/lib/far/cpp/file_operations.h"
#include "src/sys/pkg/lib/far/cpp/format.h"

namespace archive {

ArchiveWriter::ArchiveWriter() = default;

ArchiveWriter::~ArchiveWriter() = default;

bool ArchiveWriter::Add(ArchiveEntry entry) {
  size_t size = entry.dst_path.size();
  if (size > std::numeric_limits<uint16_t>::max())
    return false;
  if (size > std::numeric_limits<uint32_t>::max() - total_path_length_)
    return false;
  // TODO(abarth): Add more entry.dst_path validation.
  dirty_ = true;
  entries_.push_back(std::move(entry));
  total_path_length_ += size;
  return true;
}

bool ArchiveWriter::Write(int fd) {
  if (dirty_) {
    std::sort(entries_.begin(), entries_.end());
    dirty_ = false;
  }

  if (HasDuplicateEntries())
    return false;

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

  uint64_t index_count = entries_.empty() ? 0 : 2;
  uint64_t next_chunk = 0;

  IndexChunk index;
  index.length = index_count * sizeof(IndexEntry);
  next_chunk += sizeof(IndexChunk) + index.length;
  if (!WriteObject(fd, index)) {
    fprintf(stderr, "error: Failed to write index chunk.\n");
    return false;
  }

  if (entries_.empty())
    return true;  // No files to store in the archive.

  IndexEntry dir_entry;
  dir_entry.type = kDirType;
  dir_entry.offset = next_chunk;
  dir_entry.length = entries_.size() * sizeof(DirectoryTableEntry);
  next_chunk += dir_entry.length;
  if (!WriteObject(fd, dir_entry)) {
    fprintf(stderr, "error: Failed to write directory index chunk.\n");
    return false;
  }

  IndexEntry dirnames_entry;
  dirnames_entry.type = kDirnamesType;
  dirnames_entry.offset = next_chunk;
  dirnames_entry.length = AlignTo8ByteBoundary(total_path_length_);
  next_chunk += dirnames_entry.length;
  if (!WriteObject(fd, dirnames_entry)) {
    fprintf(stderr, "error: Failed to write directory names index chunk\n");
    return false;
  }

  uint32_t name_offset = 0;
  uint64_t data_offset = AlignToPage(next_chunk);
  std::vector<DirectoryTableEntry> directory_table(entries_.size());
  for (size_t i = 0; i < entries_.size(); ++i) {
    const ArchiveEntry& entry = entries_[i];
    DirectoryTableEntry& directory_entry = directory_table[i];

    struct stat info;
    if (stat(entry.src_path.c_str(), &info) != 0) {
      fprintf(stderr, "error: Failed to read length of file: %s\n", entry.src_path.c_str());
      return false;
    }
    uint64_t data_length = info.st_size;

    if (data_length > std::numeric_limits<uint64_t>::max() - data_offset) {
      fprintf(stderr, "error: File overflowed total archive size: %s\n", entry.src_path.c_str());
      return false;
    }

    directory_entry.name_offset = name_offset;
    directory_entry.name_length = entry.dst_path.size();
    directory_entry.data_offset = data_offset;
    directory_entry.data_length = data_length;

    name_offset += directory_entry.name_length;
    data_offset = AlignToPage(data_offset + data_length);
  }

  if (!WriteVector(fd, directory_table)) {
    fprintf(stderr, "error: Failed to write directory table.\n");
    return false;
  }

  std::vector<char> path_data(total_path_length_);
  char* pos = path_data.data();
  for (const auto& entry : entries_) {
    memcpy(pos, entry.dst_path.data(), entry.dst_path.size());
    pos += entry.dst_path.size();
  }

  if (!WriteVector(fd, path_data)) {
    fprintf(stderr, "error: Failed to write path data.\n");
    return false;
  }

  for (size_t i = 0; i < entries_.size(); ++i) {
    const ArchiveEntry& entry = entries_[i];
    const DirectoryTableEntry& directory_entry = directory_table[i];

    if (lseek(fd, directory_entry.data_offset, SEEK_SET) < 0) {
      fprintf(stderr, "error: Failed to seek to data offset.\n");
      return false;
    }
    if (!CopyPathToFile(entry.src_path.c_str(), fd, directory_entry.data_length)) {
      fprintf(stderr, "error: Failed to write file data: %s\n", entry.src_path.c_str());
      return false;
    }
  }

  if (!entries_.empty()) {
    const DirectoryTableEntry& directory_entry = directory_table.back();
    uint64_t end = directory_entry.data_offset + directory_entry.data_length;
    if (ftruncate(fd, AlignToPage(end)) < 0) {
      fprintf(stderr, "error: Failed to truncate archive to proper length.\n");
      return false;
    }
  }

  return true;
}

bool ArchiveWriter::HasDuplicateEntries() {
  for (size_t i = 0; i + 1 < entries_.size(); ++i) {
    if (entries_[i].dst_path == entries_[i + 1].dst_path) {
      fprintf(stderr, "error: Archive has duplicate path: '%s'\n", entries_[i].dst_path.c_str());
      return true;
    }
  }
  return false;
}

}  // namespace archive
