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

#include "cmFileCopier.h"

#include "cmFSPermissions.h"
#include "cmFileCommand.h"
#include "cmFileTimes.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmsys/Directory.hxx"
#include "cmsys/Glob.hxx"

#ifdef _WIN32
#  include "cmsys/FStream.hxx"
#endif

#include <sstream>
#include <string.h>

using namespace cmFSPermissions;

cmFileCopier::cmFileCopier(cmFileCommand* command, const char* name)
  : FileCommand(command)
  , Makefile(command->GetMakefile())
  , Name(name)
  , Always(false)
  , MatchlessFiles(true)
  , FilePermissions(0)
  , DirPermissions(0)
  , CurrentMatchRule(nullptr)
  , UseGivenPermissionsFile(false)
  , UseGivenPermissionsDir(false)
  , UseSourcePermissions(true)
  , FollowSymlinkChain(false)
  , Doing(DoingNone)
{
}

cmFileCopier::~cmFileCopier() = default;

cmFileCopier::MatchProperties cmFileCopier::CollectMatchProperties(
  const std::string& file)
{
  // Match rules are case-insensitive on some platforms.
#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
  const std::string file_to_match = cmSystemTools::LowerCase(file);
#else
  const std::string& file_to_match = file;
#endif

  // Collect properties from all matching rules.
  bool matched = false;
  MatchProperties result;
  for (MatchRule& mr : this->MatchRules) {
    if (mr.Regex.find(file_to_match)) {
      matched = true;
      result.Exclude |= mr.Properties.Exclude;
      result.Permissions |= mr.Properties.Permissions;
    }
  }
  if (!matched && !this->MatchlessFiles) {
    result.Exclude = !cmSystemTools::FileIsDirectory(file);
  }
  return result;
}

bool cmFileCopier::SetPermissions(const std::string& toFile,
                                  mode_t permissions)
{
  if (permissions) {
#ifdef WIN32
    if (Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
      // Store the mode in an NTFS alternate stream.
      std::string mode_t_adt_filename = toFile + ":cmake_mode_t";

      // Writing to an NTFS alternate stream changes the modification
      // time, so we need to save and restore its original value.
      cmFileTimes file_time_orig(toFile);
      {
        cmsys::ofstream permissionStream(mode_t_adt_filename.c_str());
        if (permissionStream) {
          permissionStream << std::oct << permissions << std::endl;
        }
        permissionStream.close();
      }
      file_time_orig.Store(toFile);
    }
#endif

    if (!cmSystemTools::SetPermissions(toFile, permissions)) {
      std::ostringstream e;
      e << this->Name << " cannot set permissions on \"" << toFile << "\"";
      this->FileCommand->SetError(e.str());
      return false;
    }
  }
  return true;
}

// Translate an argument to a permissions bit.
bool cmFileCopier::CheckPermissions(std::string const& arg,
                                    mode_t& permissions)
{
  if (!cmFSPermissions::stringToModeT(arg, permissions)) {
    std::ostringstream e;
    e << this->Name << " given invalid permission \"" << arg << "\".";
    this->FileCommand->SetError(e.str());
    return false;
  }
  return true;
}

std::string const& cmFileCopier::ToName(std::string const& fromName)
{
  return fromName;
}

bool cmFileCopier::ReportMissing(const std::string& fromFile)
{
  // The input file does not exist and installation is not optional.
  std::ostringstream e;
  e << this->Name << " cannot find \"" << fromFile << "\".";
  this->FileCommand->SetError(e.str());
  return false;
}

void cmFileCopier::NotBeforeMatch(std::string const& arg)
{
  std::ostringstream e;
  e << "option " << arg << " may not appear before PATTERN or REGEX.";
  this->FileCommand->SetError(e.str());
  this->Doing = DoingError;
}

void cmFileCopier::NotAfterMatch(std::string const& arg)
{
  std::ostringstream e;
  e << "option " << arg << " may not appear after PATTERN or REGEX.";
  this->FileCommand->SetError(e.str());
  this->Doing = DoingError;
}

void cmFileCopier::DefaultFilePermissions()
{
  // Use read/write permissions.
  this->FilePermissions = 0;
  this->FilePermissions |= mode_owner_read;
  this->FilePermissions |= mode_owner_write;
  this->FilePermissions |= mode_group_read;
  this->FilePermissions |= mode_world_read;
}

void cmFileCopier::DefaultDirectoryPermissions()
{
  // Use read/write/executable permissions.
  this->DirPermissions = 0;
  this->DirPermissions |= mode_owner_read;
  this->DirPermissions |= mode_owner_write;
  this->DirPermissions |= mode_owner_execute;
  this->DirPermissions |= mode_group_read;
  this->DirPermissions |= mode_group_execute;
  this->DirPermissions |= mode_world_read;
  this->DirPermissions |= mode_world_execute;
}

bool cmFileCopier::GetDefaultDirectoryPermissions(mode_t** mode)
{
  // check if default dir creation permissions were set
  const char* default_dir_install_permissions = this->Makefile->GetDefinition(
    "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
  if (default_dir_install_permissions && *default_dir_install_permissions) {
    std::vector<std::string> items;
    cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
    for (const auto& arg : items) {
      if (!this->CheckPermissions(arg, **mode)) {
        this->FileCommand->SetError(
          " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable.");
        return false;
      }
    }
  } else {
    *mode = nullptr;
  }

  return true;
}

bool cmFileCopier::Parse(std::vector<std::string> const& args)
{
  this->Doing = DoingFiles;
  for (unsigned int i = 1; i < args.size(); ++i) {
    // Check this argument.
    if (!this->CheckKeyword(args[i]) && !this->CheckValue(args[i])) {
      std::ostringstream e;
      e << "called with unknown argument \"" << args[i] << "\".";
      this->FileCommand->SetError(e.str());
      return false;
    }

    // Quit if an argument is invalid.
    if (this->Doing == DoingError) {
      return false;
    }
  }

  // Require a destination.
  if (this->Destination.empty()) {
    std::ostringstream e;
    e << this->Name << " given no DESTINATION";
    this->FileCommand->SetError(e.str());
    return false;
  }

  // If file permissions were not specified set default permissions.
  if (!this->UseGivenPermissionsFile && !this->UseSourcePermissions) {
    this->DefaultFilePermissions();
  }

  // If directory permissions were not specified set default permissions.
  if (!this->UseGivenPermissionsDir && !this->UseSourcePermissions) {
    this->DefaultDirectoryPermissions();
  }

  return true;
}

bool cmFileCopier::CheckKeyword(std::string const& arg)
{
  if (arg == "DESTINATION") {
    if (this->CurrentMatchRule) {
      this->NotAfterMatch(arg);
    } else {
      this->Doing = DoingDestination;
    }
  } else if (arg == "FILES_FROM_DIR") {
    if (this->CurrentMatchRule) {
      this->NotAfterMatch(arg);
    } else {
      this->Doing = DoingFilesFromDir;
    }
  } else if (arg == "PATTERN") {
    this->Doing = DoingPattern;
  } else if (arg == "REGEX") {
    this->Doing = DoingRegex;
  } else if (arg == "FOLLOW_SYMLINK_CHAIN") {
    this->FollowSymlinkChain = true;
    this->Doing = DoingNone;
  } else if (arg == "EXCLUDE") {
    // Add this property to the current match rule.
    if (this->CurrentMatchRule) {
      this->CurrentMatchRule->Properties.Exclude = true;
      this->Doing = DoingNone;
    } else {
      this->NotBeforeMatch(arg);
    }
  } else if (arg == "PERMISSIONS") {
    if (this->CurrentMatchRule) {
      this->Doing = DoingPermissionsMatch;
    } else {
      this->NotBeforeMatch(arg);
    }
  } else if (arg == "FILE_PERMISSIONS") {
    if (this->CurrentMatchRule) {
      this->NotAfterMatch(arg);
    } else {
      this->Doing = DoingPermissionsFile;
      this->UseGivenPermissionsFile = true;
    }
  } else if (arg == "DIRECTORY_PERMISSIONS") {
    if (this->CurrentMatchRule) {
      this->NotAfterMatch(arg);
    } else {
      this->Doing = DoingPermissionsDir;
      this->UseGivenPermissionsDir = true;
    }
  } else if (arg == "USE_SOURCE_PERMISSIONS") {
    if (this->CurrentMatchRule) {
      this->NotAfterMatch(arg);
    } else {
      this->Doing = DoingNone;
      this->UseSourcePermissions = true;
    }
  } else if (arg == "NO_SOURCE_PERMISSIONS") {
    if (this->CurrentMatchRule) {
      this->NotAfterMatch(arg);
    } else {
      this->Doing = DoingNone;
      this->UseSourcePermissions = false;
    }
  } else if (arg == "FILES_MATCHING") {
    if (this->CurrentMatchRule) {
      this->NotAfterMatch(arg);
    } else {
      this->Doing = DoingNone;
      this->MatchlessFiles = false;
    }
  } else {
    return false;
  }
  return true;
}

bool cmFileCopier::CheckValue(std::string const& arg)
{
  switch (this->Doing) {
    case DoingFiles:
      this->Files.push_back(arg);
      break;
    case DoingDestination:
      if (arg.empty() || cmSystemTools::FileIsFullPath(arg)) {
        this->Destination = arg;
      } else {
        this->Destination = this->Makefile->GetCurrentBinaryDirectory();
        this->Destination += "/" + arg;
      }
      this->Doing = DoingNone;
      break;
    case DoingFilesFromDir:
      if (cmSystemTools::FileIsFullPath(arg)) {
        this->FilesFromDir = arg;
      } else {
        this->FilesFromDir = this->Makefile->GetCurrentSourceDirectory();
        this->FilesFromDir += "/" + arg;
      }
      cmSystemTools::ConvertToUnixSlashes(this->FilesFromDir);
      this->Doing = DoingNone;
      break;
    case DoingPattern: {
      // Convert the pattern to a regular expression.  Require a
      // leading slash and trailing end-of-string in the matched
      // string to make sure the pattern matches only whole file
      // names.
      std::string regex = "/";
      regex += cmsys::Glob::PatternToRegex(arg, false);
      regex += "$";
      this->MatchRules.emplace_back(regex);
      this->CurrentMatchRule = &*(this->MatchRules.end() - 1);
      if (this->CurrentMatchRule->Regex.is_valid()) {
        this->Doing = DoingNone;
      } else {
        std::ostringstream e;
        e << "could not compile PATTERN \"" << arg << "\".";
        this->FileCommand->SetError(e.str());
        this->Doing = DoingError;
      }
    } break;
    case DoingRegex:
      this->MatchRules.emplace_back(arg);
      this->CurrentMatchRule = &*(this->MatchRules.end() - 1);
      if (this->CurrentMatchRule->Regex.is_valid()) {
        this->Doing = DoingNone;
      } else {
        std::ostringstream e;
        e << "could not compile REGEX \"" << arg << "\".";
        this->FileCommand->SetError(e.str());
        this->Doing = DoingError;
      }
      break;
    case DoingPermissionsFile:
      if (!this->CheckPermissions(arg, this->FilePermissions)) {
        this->Doing = DoingError;
      }
      break;
    case DoingPermissionsDir:
      if (!this->CheckPermissions(arg, this->DirPermissions)) {
        this->Doing = DoingError;
      }
      break;
    case DoingPermissionsMatch:
      if (!this->CheckPermissions(
            arg, this->CurrentMatchRule->Properties.Permissions)) {
        this->Doing = DoingError;
      }
      break;
    default:
      return false;
  }
  return true;
}

bool cmFileCopier::Run(std::vector<std::string> const& args)
{
  if (!this->Parse(args)) {
    return false;
  }

  for (std::string const& f : this->Files) {
    std::string file;
    if (!f.empty() && !cmSystemTools::FileIsFullPath(f)) {
      if (!this->FilesFromDir.empty()) {
        file = this->FilesFromDir;
      } else {
        file = this->Makefile->GetCurrentSourceDirectory();
      }
      file += "/";
      file += f;
    } else if (!this->FilesFromDir.empty()) {
      this->FileCommand->SetError("option FILES_FROM_DIR requires all files "
                                  "to be specified as relative paths.");
      return false;
    } else {
      file = f;
    }

    // Split the input file into its directory and name components.
    std::vector<std::string> fromPathComponents;
    cmSystemTools::SplitPath(file, fromPathComponents);
    std::string fromName = *(fromPathComponents.end() - 1);
    std::string fromDir = cmSystemTools::JoinPath(
      fromPathComponents.begin(), fromPathComponents.end() - 1);

    // Compute the full path to the destination file.
    std::string toFile = this->Destination;
    if (!this->FilesFromDir.empty()) {
      std::string dir = cmSystemTools::GetFilenamePath(f);
      if (!dir.empty()) {
        toFile += "/";
        toFile += dir;
      }
    }
    std::string const& toName = this->ToName(fromName);
    if (!toName.empty()) {
      toFile += "/";
      toFile += toName;
    }

    // Construct the full path to the source file.  The file name may
    // have been changed above.
    std::string fromFile = fromDir;
    if (!fromName.empty()) {
      fromFile += "/";
      fromFile += fromName;
    }

    if (!this->Install(fromFile, toFile)) {
      return false;
    }
  }
  return true;
}

bool cmFileCopier::Install(const std::string& fromFile,
                           const std::string& toFile)
{
  if (fromFile.empty()) {
    std::ostringstream e;
    e << "INSTALL encountered an empty string input file name.";
    this->FileCommand->SetError(e.str());
    return false;
  }

  // Collect any properties matching this file name.
  MatchProperties match_properties = this->CollectMatchProperties(fromFile);

  // Skip the file if it is excluded.
  if (match_properties.Exclude) {
    return true;
  }

  if (cmSystemTools::SameFile(fromFile, toFile)) {
    return true;
  }

  std::string newFromFile = fromFile;
  std::string newToFile = toFile;

  if (this->FollowSymlinkChain &&
      !this->InstallSymlinkChain(newFromFile, newToFile)) {
    return false;
  }

  if (cmSystemTools::FileIsSymlink(newFromFile)) {
    return this->InstallSymlink(newFromFile, newToFile);
  }
  if (cmSystemTools::FileIsDirectory(newFromFile)) {
    return this->InstallDirectory(newFromFile, newToFile, match_properties);
  }
  if (cmSystemTools::FileExists(newFromFile)) {
    return this->InstallFile(newFromFile, newToFile, match_properties);
  }
  return this->ReportMissing(newFromFile);
}

bool cmFileCopier::InstallSymlinkChain(std::string& fromFile,
                                       std::string& toFile)
{
  std::string newFromFile;
  std::string toFilePath = cmSystemTools::GetFilenamePath(toFile);
  while (cmSystemTools::ReadSymlink(fromFile, newFromFile)) {
    if (!cmSystemTools::FileIsFullPath(newFromFile)) {
      std::string fromFilePath = cmSystemTools::GetFilenamePath(fromFile);
      newFromFile = fromFilePath + "/" + newFromFile;
    }

    std::string symlinkTarget = cmSystemTools::GetFilenameName(newFromFile);

    bool copy = true;
    if (!this->Always) {
      std::string oldSymlinkTarget;
      if (cmSystemTools::ReadSymlink(toFile, oldSymlinkTarget)) {
        if (symlinkTarget == oldSymlinkTarget) {
          copy = false;
        }
      }
    }

    this->ReportCopy(toFile, TypeLink, copy);

    if (copy) {
      cmSystemTools::RemoveFile(toFile);
      cmSystemTools::MakeDirectory(toFilePath);

      if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) {
        std::ostringstream e;
        e << this->Name << " cannot create symlink \"" << toFile << "\".";
        this->FileCommand->SetError(e.str());
        return false;
      }
    }

    fromFile = newFromFile;
    toFile = toFilePath + "/" + symlinkTarget;
  }

  return true;
}

bool cmFileCopier::InstallSymlink(const std::string& fromFile,
                                  const std::string& toFile)
{
  // Read the original symlink.
  std::string symlinkTarget;
  if (!cmSystemTools::ReadSymlink(fromFile, symlinkTarget)) {
    std::ostringstream e;
    e << this->Name << " cannot read symlink \"" << fromFile
      << "\" to duplicate at \"" << toFile << "\".";
    this->FileCommand->SetError(e.str());
    return false;
  }

  // Compare the symlink value to that at the destination if not
  // always installing.
  bool copy = true;
  if (!this->Always) {
    std::string oldSymlinkTarget;
    if (cmSystemTools::ReadSymlink(toFile, oldSymlinkTarget)) {
      if (symlinkTarget == oldSymlinkTarget) {
        copy = false;
      }
    }
  }

  // Inform the user about this file installation.
  this->ReportCopy(toFile, TypeLink, copy);

  if (copy) {
    // Remove the destination file so we can always create the symlink.
    cmSystemTools::RemoveFile(toFile);

    // Create destination directory if it doesn't exist
    cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(toFile));

    // Create the symlink.
    if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) {
      std::ostringstream e;
      e << this->Name << " cannot duplicate symlink \"" << fromFile
        << "\" at \"" << toFile << "\".";
      this->FileCommand->SetError(e.str());
      return false;
    }
  }

  return true;
}

bool cmFileCopier::InstallFile(const std::string& fromFile,
                               const std::string& toFile,
                               MatchProperties match_properties)
{
  // Determine whether we will copy the file.
  bool copy = true;
  if (!this->Always) {
    // If both files exist with the same time do not copy.
    if (!this->FileTimes.DifferS(fromFile, toFile)) {
      copy = false;
    }
  }

  // Inform the user about this file installation.
  this->ReportCopy(toFile, TypeFile, copy);

  // Copy the file.
  if (copy && !cmSystemTools::CopyAFile(fromFile, toFile, true)) {
    std::ostringstream e;
    e << this->Name << " cannot copy file \"" << fromFile << "\" to \""
      << toFile << "\".";
    this->FileCommand->SetError(e.str());
    return false;
  }

  // Set the file modification time of the destination file.
  if (copy && !this->Always) {
    // Add write permission so we can set the file time.
    // Permissions are set unconditionally below anyway.
    mode_t perm = 0;
    if (cmSystemTools::GetPermissions(toFile, perm)) {
      cmSystemTools::SetPermissions(toFile, perm | mode_owner_write);
    }
    if (!cmFileTimes::Copy(fromFile, toFile)) {
      std::ostringstream e;
      e << this->Name << " cannot set modification time on \"" << toFile
        << "\"";
      this->FileCommand->SetError(e.str());
      return false;
    }
  }

  // Set permissions of the destination file.
  mode_t permissions =
    (match_properties.Permissions ? match_properties.Permissions
                                  : this->FilePermissions);
  if (!permissions) {
    // No permissions were explicitly provided but the user requested
    // that the source file permissions be used.
    cmSystemTools::GetPermissions(fromFile, permissions);
  }
  return this->SetPermissions(toFile, permissions);
}

bool cmFileCopier::InstallDirectory(const std::string& source,
                                    const std::string& destination,
                                    MatchProperties match_properties)
{
  // Inform the user about this directory installation.
  this->ReportCopy(destination, TypeDir,
                   !cmSystemTools::FileIsDirectory(destination));

  // check if default dir creation permissions were set
  mode_t default_dir_mode_v = 0;
  mode_t* default_dir_mode = &default_dir_mode_v;
  if (!this->GetDefaultDirectoryPermissions(&default_dir_mode)) {
    return false;
  }

  // Make sure the destination directory exists.
  if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) {
    std::ostringstream e;
    e << this->Name << " cannot make directory \"" << destination
      << "\": " << cmSystemTools::GetLastSystemError();
    this->FileCommand->SetError(e.str());
    return false;
  }

  // Compute the requested permissions for the destination directory.
  mode_t permissions =
    (match_properties.Permissions ? match_properties.Permissions
                                  : this->DirPermissions);
  if (!permissions) {
    // No permissions were explicitly provided but the user requested
    // that the source directory permissions be used.
    cmSystemTools::GetPermissions(source, permissions);
  }

  // Compute the set of permissions required on this directory to
  // recursively install files and subdirectories safely.
  mode_t required_permissions =
    mode_owner_read | mode_owner_write | mode_owner_execute;

  // If the required permissions are specified it is safe to set the
  // final permissions now.  Otherwise we must add the required
  // permissions temporarily during file installation.
  mode_t permissions_before = 0;
  mode_t permissions_after = 0;
  if ((permissions & required_permissions) == required_permissions) {
    permissions_before = permissions;
  } else {
    permissions_before = permissions | required_permissions;
    permissions_after = permissions;
  }

  // Set the required permissions of the destination directory.
  if (!this->SetPermissions(destination, permissions_before)) {
    return false;
  }

  // Load the directory contents to traverse it recursively.
  cmsys::Directory dir;
  if (!source.empty()) {
    dir.Load(source);
  }
  unsigned long numFiles = static_cast<unsigned long>(dir.GetNumberOfFiles());
  for (unsigned long fileNum = 0; fileNum < numFiles; ++fileNum) {
    if (!(strcmp(dir.GetFile(fileNum), ".") == 0 ||
          strcmp(dir.GetFile(fileNum), "..") == 0)) {
      std::string fromPath = source;
      fromPath += "/";
      fromPath += dir.GetFile(fileNum);
      std::string toPath = destination;
      toPath += "/";
      toPath += dir.GetFile(fileNum);
      if (!this->Install(fromPath, toPath)) {
        return false;
      }
    }
  }

  // Set the requested permissions of the destination directory.
  return this->SetPermissions(destination, permissions_after);
}
