// 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 <fcntl.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
