/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmArchiveWrite.h"

#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <limits>
#include <sstream>
#include <string>
#include <thread>

#include <cm/algorithm>

#include <cm3p/archive.h>
#include <cm3p/archive_entry.h>

#include "cmsys/Directory.hxx"
#include "cmsys/Encoding.hxx"
#include "cmsys/FStream.hxx"

#include "cm_get_date.h"

#include "cmLocale.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

#ifndef __LA_SSIZE_T
#  define __LA_SSIZE_T la_ssize_t
#endif

static std::string cm_archive_error_string(struct archive* a)
{
  const char* e = archive_error_string(a);
  return e ? e : "unknown error";
}

static void cm_archive_entry_copy_pathname(struct archive_entry* e,
                                           const std::string& dest)
{
#if cmsys_STL_HAS_WSTRING
  archive_entry_copy_pathname_w(e, cmsys::Encoding::ToWide(dest).c_str());
#else
  archive_entry_copy_pathname(e, dest.c_str());
#endif
}

static void cm_archive_entry_copy_sourcepath(struct archive_entry* e,
                                             const std::string& file)
{
#if cmsys_STL_HAS_WSTRING
  archive_entry_copy_sourcepath_w(e, cmsys::Encoding::ToWide(file).c_str());
#else
  archive_entry_copy_sourcepath(e, file.c_str());
#endif
}

class cmArchiveWrite::Entry
{
  struct archive_entry* Object;

public:
  Entry()
    : Object(archive_entry_new())
  {
  }
  ~Entry() { archive_entry_free(this->Object); }
  Entry(const Entry&) = delete;
  Entry& operator=(const Entry&) = delete;
  operator struct archive_entry*() { return this->Object; }
};

struct cmArchiveWrite::Callback
{
  // archive_write_callback
  static __LA_SSIZE_T Write(struct archive* /*unused*/, void* cd,
                            const void* b, size_t n)
  {
    cmArchiveWrite* self = static_cast<cmArchiveWrite*>(cd);
    if (self->Stream.write(static_cast<const char*>(b),
                           static_cast<std::streamsize>(n))) {
      return static_cast<__LA_SSIZE_T>(n);
    }
    return static_cast<__LA_SSIZE_T>(-1);
  }
};

cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
                               std::string const& format, int compressionLevel,
                               int numThreads)
  : Stream(os)
  , Archive(archive_write_new())
  , Disk(archive_read_disk_new())
  , Verbose(false)
  , Format(format)
{
  switch (c) {
    case CompressNone:
      if (archive_write_add_filter_none(this->Archive) != ARCHIVE_OK) {
        this->Error = cmStrCat("archive_write_add_filter_none: ",
                               cm_archive_error_string(this->Archive));
        return;
      }
      break;
    case CompressCompress:
      if (archive_write_add_filter_compress(this->Archive) != ARCHIVE_OK) {
        this->Error = cmStrCat("archive_write_add_filter_compress: ",
                               cm_archive_error_string(this->Archive));
        return;
      }
      break;
    case CompressGZip: {
      if (archive_write_add_filter_gzip(this->Archive) != ARCHIVE_OK) {
        this->Error = cmStrCat("archive_write_add_filter_gzip: ",
                               cm_archive_error_string(this->Archive));
        return;
      }
      std::string source_date_epoch;
      cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch);
      if (!source_date_epoch.empty()) {
        // We're not able to specify an arbitrary timestamp for gzip.
        // The next best thing is to omit the timestamp entirely.
        if (archive_write_set_filter_option(this->Archive, "gzip", "timestamp",
                                            nullptr) != ARCHIVE_OK) {
          this->Error = cmStrCat("archive_write_set_filter_option: ",
                                 cm_archive_error_string(this->Archive));
          return;
        }
      }
    } break;
    case CompressBZip2:
      if (archive_write_add_filter_bzip2(this->Archive) != ARCHIVE_OK) {
        this->Error = cmStrCat("archive_write_add_filter_bzip2: ",
                               cm_archive_error_string(this->Archive));
        return;
      }
      break;
    case CompressLZMA:
      if (archive_write_add_filter_lzma(this->Archive) != ARCHIVE_OK) {
        this->Error = cmStrCat("archive_write_add_filter_lzma: ",
                               cm_archive_error_string(this->Archive));
        return;
      }
      break;
    case CompressXZ:
      if (archive_write_add_filter_xz(this->Archive) != ARCHIVE_OK) {
        this->Error = cmStrCat("archive_write_add_filter_xz: ",
                               cm_archive_error_string(this->Archive));
        return;
      }

      {
#if ARCHIVE_VERSION_NUMBER >= 3004000
        // Upstream fixed an issue with their integer parsing in 3.4.0
        // which would cause spurious errors to be raised from `strtoull`.

        if (numThreads < 1) {
          int upperLimit = (numThreads == 0) ? std::numeric_limits<int>::max()
                                             : std::abs(numThreads);

          numThreads =
            cm::clamp<int>(std::thread::hardware_concurrency(), 1, upperLimit);
        }

#  ifdef _AIX
        // FIXME: Using more than 2 threads creates an empty archive.
        // Enforce this limit pending further investigation.
        numThreads = std::min(numThreads, 2);
#  endif

        std::string sNumThreads = std::to_string(numThreads);

        if (archive_write_set_filter_option(this->Archive, "xz", "threads",
                                            sNumThreads.c_str()) !=
            ARCHIVE_OK) {
          this->Error = cmStrCat("archive_compressor_xz_options: ",
                                 cm_archive_error_string(this->Archive));
          return;
        }
#endif
      }

      break;
    case CompressZstd:
      if (archive_write_add_filter_zstd(this->Archive) != ARCHIVE_OK) {
        this->Error = cmStrCat("archive_write_add_filter_zstd: ",
                               cm_archive_error_string(this->Archive));
        return;
      }
      break;
  }

  if (compressionLevel != 0) {
    std::string compressionLevelStr = std::to_string(compressionLevel);
    std::string archiveFilterName;
    switch (c) {
      case CompressNone:
      case CompressCompress:
        break;
      case CompressGZip:
        archiveFilterName = "gzip";
        break;
      case CompressBZip2:
        archiveFilterName = "bzip2";
        break;
      case CompressLZMA:
        archiveFilterName = "lzma";
        break;
      case CompressXZ:
        archiveFilterName = "xz";
        break;
      case CompressZstd:
        archiveFilterName = "zstd";
        break;
    }
    if (!archiveFilterName.empty()) {
      if (archive_write_set_filter_option(
            this->Archive, archiveFilterName.c_str(), "compression-level",
            compressionLevelStr.c_str()) != ARCHIVE_OK) {
        this->Error = cmStrCat("archive_write_set_filter_option: ",
                               cm_archive_error_string(this->Archive));
        return;
      }
    }
  }

#if !defined(_WIN32) || defined(__CYGWIN__)
  if (archive_read_disk_set_standard_lookup(this->Disk) != ARCHIVE_OK) {
    this->Error = cmStrCat("archive_read_disk_set_standard_lookup: ",
                           cm_archive_error_string(this->Archive));
    return;
  }
#endif

  if (archive_write_set_format_by_name(this->Archive, format.c_str()) !=
      ARCHIVE_OK) {
    this->Error = cmStrCat("archive_write_set_format_by_name: ",
                           cm_archive_error_string(this->Archive));
    return;
  }

  // do not pad the last block!!
  if (archive_write_set_bytes_in_last_block(this->Archive, 1)) {
    this->Error = cmStrCat("archive_write_set_bytes_in_last_block: ",
                           cm_archive_error_string(this->Archive));
    return;
  }
}

bool cmArchiveWrite::Open()
{
  if (!this->Error.empty()) {
    return false;
  }
  if (archive_write_open(
        this->Archive, this, nullptr,
        reinterpret_cast<archive_write_callback*>(&Callback::Write),
        nullptr) != ARCHIVE_OK) {
    this->Error =
      cmStrCat("archive_write_open: ", cm_archive_error_string(this->Archive));
    return false;
  }
  return true;
}

cmArchiveWrite::~cmArchiveWrite()
{
  archive_read_free(this->Disk);
  archive_write_free(this->Archive);
}

bool cmArchiveWrite::Add(std::string path, size_t skip, const char* prefix,
                         bool recursive)
{
  if (!path.empty() && path.back() == '/') {
    path.erase(path.size() - 1);
  }
  this->AddPath(path.c_str(), skip, prefix, recursive);
  return this->Okay();
}

bool cmArchiveWrite::AddPath(const char* path, size_t skip, const char* prefix,
                             bool recursive)
{
  if (strcmp(path, ".") != 0 ||
      (this->Format != "zip" && this->Format != "7zip")) {
    if (!this->AddFile(path, skip, prefix)) {
      return false;
    }
  }
  if ((!cmSystemTools::FileIsDirectory(path) || !recursive) ||
      cmSystemTools::FileIsSymlink(path)) {
    return true;
  }
  cmsys::Directory d;
  if (d.Load(path)) {
    std::string next = cmStrCat(path, '/');
    if (next == "./" && (this->Format == "zip" || this->Format == "7zip")) {
      next.clear();
    }
    std::string::size_type end = next.size();
    unsigned long n = d.GetNumberOfFiles();
    for (unsigned long i = 0; i < n; ++i) {
      const char* file = d.GetFile(i);
      if (strcmp(file, ".") != 0 && strcmp(file, "..") != 0) {
        next.erase(end);
        next += file;
        if (!this->AddPath(next.c_str(), skip, prefix)) {
          return false;
        }
      }
    }
  }
  return true;
}

bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
{
  this->Error = "";
  // Skip the file if we have no name for it.  This may happen on a
  // top-level directory, which does not need to be included anyway.
  if (skip >= strlen(file)) {
    return true;
  }
  const char* out = file + skip;

  cmLocaleRAII localeRAII;
  static_cast<void>(localeRAII);

  // Meta-data.
  std::string dest = cmStrCat(prefix ? prefix : "", out);
  if (this->Verbose) {
    std::cout << dest << "\n";
  }
  Entry e;
  cm_archive_entry_copy_sourcepath(e, file);
  cm_archive_entry_copy_pathname(e, dest);
  if (archive_read_disk_entry_from_file(this->Disk, e, -1, nullptr) !=
      ARCHIVE_OK) {
    this->Error = cmStrCat("Unable to read from file '", file,
                           "': ", cm_archive_error_string(this->Disk));
    return false;
  }
  if (!this->MTime.empty()) {
    time_t now;
    time(&now);
    time_t t = cm_get_date(now, this->MTime.c_str());
    if (t == -1) {
      this->Error = cmStrCat("unable to parse mtime '", this->MTime, '\'');
      return false;
    }
    archive_entry_set_mtime(e, t, 0);
  } else {
    std::string source_date_epoch;
    cmSystemTools::GetEnv("SOURCE_DATE_EPOCH", source_date_epoch);
    if (!source_date_epoch.empty()) {
      std::istringstream iss(source_date_epoch);
      time_t epochTime;
      iss >> epochTime;
      if (iss.eof() && !iss.fail()) {
        // Set all of the file times to the epoch time to handle archive
        // formats that include creation/access time.
        archive_entry_set_mtime(e, epochTime, 0);
        archive_entry_set_atime(e, epochTime, 0);
        archive_entry_set_ctime(e, epochTime, 0);
        archive_entry_set_birthtime(e, epochTime, 0);
      }
    }
  }

  // manages the uid/guid of the entry (if any)
  if (this->Uid.IsSet() && this->Gid.IsSet()) {
    archive_entry_set_uid(e, this->Uid.Get());
    archive_entry_set_gid(e, this->Gid.Get());
  }

  if (!this->Uname.empty() && !this->Gname.empty()) {
    archive_entry_set_uname(e, this->Uname.c_str());
    archive_entry_set_gname(e, this->Gname.c_str());
  }

  // manages the permissions
  if (this->Permissions.IsSet()) {
    archive_entry_set_perm(e, this->Permissions.Get());
  }

  if (this->PermissionsMask.IsSet()) {
    int perm = archive_entry_perm(e);
    archive_entry_set_perm(e, perm & this->PermissionsMask.Get());
  }

  // Clear acl and xattr fields not useful for distribution.
  archive_entry_acl_clear(e);
  archive_entry_xattr_clear(e);
  archive_entry_set_fflags(e, 0, 0);

  if (this->Format == "pax" || this->Format == "paxr") {
    // Sparse files are a GNU tar extension.
    // Do not use them in standard tar files.
    archive_entry_sparse_clear(e);
  }

  if (archive_write_header(this->Archive, e) != ARCHIVE_OK) {
    this->Error = cmStrCat("archive_write_header: ",
                           cm_archive_error_string(this->Archive));
    return false;
  }

  // do not copy content of symlink
  if (!archive_entry_symlink(e)) {
    // Content.
    if (size_t size = static_cast<size_t>(archive_entry_size(e))) {
      return this->AddData(file, size);
    }
  }
  return true;
}

bool cmArchiveWrite::AddData(const char* file, size_t size)
{
  cmsys::ifstream fin(file, std::ios::in | std::ios::binary);
  if (!fin) {
    this->Error = cmStrCat("Error opening \"", file,
                           "\": ", cmSystemTools::GetLastSystemError());
    return false;
  }

  char buffer[16384];
  size_t nleft = size;
  while (nleft > 0) {
    using ssize_type = std::streamsize;
    size_t const nnext = nleft > sizeof(buffer) ? sizeof(buffer) : nleft;
    ssize_type const nnext_s = static_cast<ssize_type>(nnext);
    fin.read(buffer, nnext_s);
    // Some stream libraries (older HPUX) return failure at end of
    // file on the last read even if some data were read.  Check
    // gcount instead of trusting the stream error status.
    if (static_cast<size_t>(fin.gcount()) != nnext) {
      break;
    }
    if (archive_write_data(this->Archive, buffer, nnext) != nnext_s) {
      this->Error = cmStrCat("archive_write_data: ",
                             cm_archive_error_string(this->Archive));
      return false;
    }
    nleft -= nnext;
  }
  if (nleft > 0) {
    this->Error = cmStrCat("Error reading \"", file,
                           "\": ", cmSystemTools::GetLastSystemError());
    return false;
  }
  return true;
}
