// Copyright 2019 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/developer/forensics/utils/archive.h"

#include <lib/syslog/cpp/macros.h>

#include "src/lib/files/file.h"
#include "src/lib/files/scoped_temp_dir.h"
#include "src/lib/fsl/vmo/file.h"
#include "src/lib/fsl/vmo/sized_vmo.h"
#include "src/lib/fsl/vmo/vector.h"
#include "src/lib/fxl/strings/substitute.h"
#include "third_party/zlib/contrib/minizip/unzip.h"
#include "third_party/zlib/contrib/minizip/zip.h"

namespace forensics {
namespace {

using fuchsia::mem::Buffer;

bool Archive(const std::map<std::string, std::string>& files, const std::string& archive_filename,
             zipFile* zf, std::map<std::string, ArchiveFileStats>* file_to_size_stats) {
  uint64_t old_zip_size = 0;
  uint64_t new_zip_size = 0;

  for (const auto& [filename, content] : files) {
    zip_fileinfo zf_info = {};
    if (const int status =
            zipOpenNewFileInZip64(*zf, filename.c_str(), &zf_info, nullptr, 0, nullptr, 0, nullptr,
                                  Z_DEFLATED, Z_DEFAULT_COMPRESSION, /*zip64=*/1);
        status != ZIP_OK) {
      FX_LOGS(ERROR) << fxl::Substitute("cannot create $0 in output zip archive: ", filename)
                     << status;
      return false;
    }

    if (const int status = zipWriteInFileInZip(*zf, content.data(), (uint32_t)content.size());
        status != ZIP_OK) {
      FX_LOGS(ERROR) << fxl::Substitute("cannot write $0 in output zip archive: ", filename)
                     << status;
      return false;
    }

    if (const int status = zipCloseFileInZip(*zf); status != ZIP_OK) {
      FX_LOGS(WARNING) << fxl::Substitute("cannot close $0 in output zip archive: ", filename)
                       << status;
    }

    if (file_to_size_stats != nullptr) {
      files::GetFileSize(archive_filename.c_str(), &new_zip_size);
      (*file_to_size_stats)[filename] = {.raw_bytes = content.size(),
                                         .compressed_bytes = new_zip_size - old_zip_size};
    }

    old_zip_size = new_zip_size;
  }

  return true;
}

}  // namespace

bool Archive(const std::map<std::string, std::string>& files, fsl::SizedVmo* archive,
             std::map<std::string, ArchiveFileStats>* file_to_size_stats) {
  // We write the archive to a temporary file because in-memory archiving in minizip is complicated.
  files::ScopedTempDir tmp_dir;
  std::string archive_filename;
  tmp_dir.NewTempFile(&archive_filename);

  zipFile zf = zipOpen64(archive_filename.c_str(), APPEND_STATUS_CREATE);
  if (zf == nullptr) {
    FX_LOGS(ERROR) << "cannot create output zip archive";
    return false;
  }

  const bool success = Archive(files, archive_filename, &zf, file_to_size_stats);

  // We always close the archive regardless of the success status.
  if (const int status = zipClose(zf, nullptr); status != ZIP_OK) {
    FX_LOGS(WARNING) << "cannot close output zip archive: " << status;
  }

  if (!success) {
    return false;
  }

  if (!fsl::VmoFromFilename(archive_filename, archive)) {
    FX_LOGS(ERROR) << "error loading output zip archive into VMO";
    return false;
  }

  return true;
}

namespace {

bool Unpack(unzFile* uf, std::map<std::string, std::string>* files) {
  unz_global_info archive_info;
  if (const int status = unzGetGlobalInfo(*uf, &archive_info); status != UNZ_OK) {
    FX_LOGS(ERROR) << "cannot read input zip archive info: " << status;
    return false;
  }

  const auto num_files = archive_info.number_entry;
  if (num_files <= 0) {
    FX_LOGS(ERROR) << "input zip archive contains no files";
    return false;
  }

  for (uint64_t current_file_index = 1; current_file_index <= num_files; ++current_file_index) {
    unz_file_info64 file_info;
    char filename[256];
    if (const int status = unzGetCurrentFileInfo64(*uf, &file_info, filename, sizeof(filename),
                                                   nullptr, 0, nullptr, 0);
        status != UNZ_OK) {
      FX_LOGS(ERROR) << "cannot read current file info in input zip archive: " << status;
      return false;
    }

    const std::string filename_str = std::string(filename);

    if (int status = unzOpenCurrentFile(*uf); status != UNZ_OK) {
      FX_LOGS(ERROR) << fxl::Substitute("cannot open $0 in input zip archive: ", filename_str)
                     << status;
      return false;
    }

    std::vector<uint8_t> data;
    data.reserve(static_cast<size_t>(file_info.uncompressed_size));
    const size_t kBufferSize = 512;
    std::vector<uint8_t> buffer(kBufferSize);
    int num_bytes_or_status;
    do {
      num_bytes_or_status = unzReadCurrentFile(*uf, buffer.data(), kBufferSize);
      if (num_bytes_or_status < 0) {
        FX_LOGS(ERROR) << fxl::Substitute("cannot read $0 in input zip archive: ", filename_str)
                       << num_bytes_or_status;
        return false;
      } else if (num_bytes_or_status > 0) {
        data.insert(data.end(), buffer.data(), buffer.data() + num_bytes_or_status);
      }  // num_bytes_or_status == 0 means EOF
    } while (num_bytes_or_status > 0);

    if (const int status = unzCloseCurrentFile(*uf); status != UNZ_OK) {
      FX_LOGS(WARNING) << fxl::Substitute("cannot close $0 in input zip archive: ", filename_str)
                       << status;
    }

    files->insert({std::string(filename_str), std::string(data.begin(), data.end())});

    if (current_file_index == num_files) {  // last file, bail out.
      break;
    }

    if (const int status = unzGoToNextFile(*uf); status != UNZ_OK) {
      FX_LOGS(ERROR) << "cannot read next file in input zip archive: " << status;
      return false;
    }
  }

  return true;
}

}  // namespace

bool Unpack(const Buffer& archive, std::map<std::string, std::string>* files) {
  // We write the archive to a temporary file because minizip doesn't support unpacking an in-memory
  // archive.
  files::ScopedTempDir tmp_dir;
  std::string archive_filename;
  tmp_dir.NewTempFile(&archive_filename);

  auto data = std::make_unique<uint8_t[]>(archive.size);
  if (const zx_status_t status = archive.vmo.read(data.get(), 0u, archive.size); status != ZX_OK) {
    FX_PLOGS(ERROR, status) << "failed to read input zip archive VMO";
    return false;
  }

  if (!files::WriteFile(archive_filename, reinterpret_cast<const char*>(data.get()),
                        archive.size)) {
    FX_LOGS(ERROR) << "failed to write input zip archive VMO to temporary file";
    return false;
  }

  unzFile uf = unzOpen64(archive_filename.c_str());
  if (uf == nullptr) {
    FX_LOGS(ERROR) << "cannot open input zip archive at " << archive_filename;
    return false;
  }

  const bool success = Unpack(&uf, files);

  // We always close the archive regardless of the success status.
  if (const int status = unzClose(uf); status != ZIP_OK) {
    FX_LOGS(WARNING) << "cannot close input zip archive: " << status;
  }

  return success;
}

}  // namespace forensics
