//===-- ModuleCache.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/ModuleCache.h"

#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/File.h"
#include "lldb/Host/LockFile.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"

#include <cassert>

#include <cstdio>

using namespace lldb;
using namespace lldb_private;

namespace {

const char *kModulesSubdir = ".cache";
const char *kLockDirName = ".lock";
const char *kTempFileName = ".temp";
const char *kTempSymFileName = ".symtemp";
const char *kSymFileExtension = ".sym";
const char *kFSIllegalChars = "\\/:*?\"<>|";

std::string GetEscapedHostname(const char *hostname) {
  if (hostname == nullptr)
    hostname = "unknown";
  std::string result(hostname);
  size_t size = result.size();
  for (size_t i = 0; i < size; ++i) {
    if ((result[i] >= 1 && result[i] <= 31) ||
        strchr(kFSIllegalChars, result[i]) != nullptr)
      result[i] = '_';
  }
  return result;
}

class ModuleLock {
private:
  FileUP m_file_up;
  std::unique_ptr<lldb_private::LockFile> m_lock;
  FileSpec m_file_spec;

public:
  ModuleLock(const FileSpec &root_dir_spec, const UUID &uuid, Status &error);
  void Delete();
};

static FileSpec JoinPath(const FileSpec &path1, llvm::StringRef path2) {
  FileSpec result_spec(path1);
  result_spec.AppendPathComponent(path2);
  return result_spec;
}

static Status MakeDirectory(const FileSpec &dir_path) {
  namespace fs = llvm::sys::fs;

  return fs::create_directories(dir_path.GetPath(), true, fs::perms::owner_all);
}

FileSpec GetModuleDirectory(const FileSpec &root_dir_spec, const UUID &uuid) {
  const auto modules_dir_spec = JoinPath(root_dir_spec, kModulesSubdir);
  return JoinPath(modules_dir_spec, uuid.GetAsString().c_str());
}

FileSpec GetSymbolFileSpec(const FileSpec &module_file_spec) {
  return FileSpec(module_file_spec.GetPath() + kSymFileExtension);
}

void DeleteExistingModule(const FileSpec &root_dir_spec,
                          const FileSpec &sysroot_module_path_spec) {
  Log *log = GetLog(LLDBLog::Modules);
  UUID module_uuid;
  {
    auto module_sp =
        std::make_shared<Module>(ModuleSpec(sysroot_module_path_spec));
    module_uuid = module_sp->GetUUID();
  }

  if (!module_uuid.IsValid())
    return;

  Status error;
  ModuleLock lock(root_dir_spec, module_uuid, error);
  if (error.Fail()) {
    LLDB_LOGF(log, "Failed to lock module %s: %s",
              module_uuid.GetAsString().c_str(), error.AsCString());
  }

  namespace fs = llvm::sys::fs;
  fs::file_status st;
  if (status(sysroot_module_path_spec.GetPath(), st))
    return;

  if (st.getLinkCount() > 2) // module is referred by other hosts.
    return;

  const auto module_spec_dir = GetModuleDirectory(root_dir_spec, module_uuid);
  llvm::sys::fs::remove_directories(module_spec_dir.GetPath());
  lock.Delete();
}

void DecrementRefExistingModule(const FileSpec &root_dir_spec,
                                const FileSpec &sysroot_module_path_spec) {
  // Remove $platform/.cache/$uuid folder if nobody else references it.
  DeleteExistingModule(root_dir_spec, sysroot_module_path_spec);

  // Remove sysroot link.
  llvm::sys::fs::remove(sysroot_module_path_spec.GetPath());

  FileSpec symfile_spec = GetSymbolFileSpec(sysroot_module_path_spec);
  llvm::sys::fs::remove(symfile_spec.GetPath());
}

Status CreateHostSysRootModuleLink(const FileSpec &root_dir_spec,
                                   const char *hostname,
                                   const FileSpec &platform_module_spec,
                                   const FileSpec &local_module_spec,
                                   bool delete_existing) {
  const auto sysroot_module_path_spec =
      JoinPath(JoinPath(root_dir_spec, hostname),
               platform_module_spec.GetPath().c_str());
  if (FileSystem::Instance().Exists(sysroot_module_path_spec)) {
    if (!delete_existing)
      return Status();

    DecrementRefExistingModule(root_dir_spec, sysroot_module_path_spec);
  }

  Status error =
      MakeDirectory(FileSpec(sysroot_module_path_spec.GetDirectory()));
  if (error.Fail())
    return error;

  return llvm::sys::fs::create_hard_link(local_module_spec.GetPath(),
                                         sysroot_module_path_spec.GetPath());
}

} // namespace

ModuleLock::ModuleLock(const FileSpec &root_dir_spec, const UUID &uuid,
                       Status &error) {
  const auto lock_dir_spec = JoinPath(root_dir_spec, kLockDirName);
  error = MakeDirectory(lock_dir_spec);
  if (error.Fail())
    return;

  m_file_spec = JoinPath(lock_dir_spec, uuid.GetAsString().c_str());

  auto file = FileSystem::Instance().Open(
      m_file_spec, File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate |
                       File::eOpenOptionCloseOnExec);
  if (file)
    m_file_up = std::move(file.get());
  else {
    m_file_up.reset();
    error = Status::FromError(file.takeError());
    return;
  }

  m_lock = std::make_unique<lldb_private::LockFile>(m_file_up->GetDescriptor());
  error = m_lock->WriteLock(0, 1);
  if (error.Fail())
    error =
        Status::FromErrorStringWithFormatv("Failed to lock file: {0}", error);
}

void ModuleLock::Delete() {
  if (!m_file_up)
    return;

  m_file_up->Close();
  m_file_up.reset();
  llvm::sys::fs::remove(m_file_spec.GetPath());
}

/////////////////////////////////////////////////////////////////////////

Status ModuleCache::Put(const FileSpec &root_dir_spec, const char *hostname,
                        const ModuleSpec &module_spec, const FileSpec &tmp_file,
                        const FileSpec &target_file) {
  const auto module_spec_dir =
      GetModuleDirectory(root_dir_spec, module_spec.GetUUID());
  const auto module_file_path =
      JoinPath(module_spec_dir, target_file.GetFilename());

  const auto tmp_file_path = tmp_file.GetPath();
  const auto err_code =
      llvm::sys::fs::rename(tmp_file_path, module_file_path.GetPath());
  if (err_code)
    return Status::FromErrorStringWithFormat(
        "Failed to rename file %s to %s: %s", tmp_file_path.c_str(),
        module_file_path.GetPath().c_str(), err_code.message().c_str());

  const auto error = CreateHostSysRootModuleLink(
      root_dir_spec, hostname, target_file, module_file_path, true);
  if (error.Fail())
    return Status::FromErrorStringWithFormat("Failed to create link to %s: %s",
                                             module_file_path.GetPath().c_str(),
                                             error.AsCString());
  return Status();
}

Status ModuleCache::Get(const FileSpec &root_dir_spec, const char *hostname,
                        const ModuleSpec &module_spec,
                        ModuleSP &cached_module_sp, bool *did_create_ptr) {
  const auto find_it =
      m_loaded_modules.find(module_spec.GetUUID().GetAsString());
  if (find_it != m_loaded_modules.end()) {
    cached_module_sp = (*find_it).second.lock();
    if (cached_module_sp)
      return Status();
    m_loaded_modules.erase(find_it);
  }

  const auto module_spec_dir =
      GetModuleDirectory(root_dir_spec, module_spec.GetUUID());
  const auto module_file_path =
      JoinPath(module_spec_dir, module_spec.GetFileSpec().GetFilename());

  if (!FileSystem::Instance().Exists(module_file_path))
    return Status::FromErrorStringWithFormat(
        "Module %s not found", module_file_path.GetPath().c_str());
  if (FileSystem::Instance().GetByteSize(module_file_path) !=
      module_spec.GetObjectSize())
    return Status::FromErrorStringWithFormat(
        "Module %s has invalid file size", module_file_path.GetPath().c_str());

  // We may have already cached module but downloaded from an another host - in
  // this case let's create a link to it.
  auto error = CreateHostSysRootModuleLink(root_dir_spec, hostname,
                                           module_spec.GetFileSpec(),
                                           module_file_path, false);
  if (error.Fail())
    return Status::FromErrorStringWithFormat("Failed to create link to %s: %s",
                                             module_file_path.GetPath().c_str(),
                                             error.AsCString());

  auto cached_module_spec(module_spec);
  cached_module_spec.GetUUID().Clear(); // Clear UUID since it may contain md5
                                        // content hash instead of real UUID.
  cached_module_spec.GetFileSpec() = module_file_path;
  cached_module_spec.GetPlatformFileSpec() = module_spec.GetFileSpec();

  error = ModuleList::GetSharedModule(cached_module_spec, cached_module_sp,
                                      nullptr, did_create_ptr,
                                      /*invoke_locate_callback=*/false);
  if (error.Fail())
    return error;

  FileSpec symfile_spec = GetSymbolFileSpec(cached_module_sp->GetFileSpec());
  if (FileSystem::Instance().Exists(symfile_spec))
    cached_module_sp->SetSymbolFileFileSpec(symfile_spec);

  m_loaded_modules.insert(
      std::make_pair(module_spec.GetUUID().GetAsString(), cached_module_sp));

  return Status();
}

Status ModuleCache::GetAndPut(const FileSpec &root_dir_spec,
                              const char *hostname,
                              const ModuleSpec &module_spec,
                              const ModuleDownloader &module_downloader,
                              const SymfileDownloader &symfile_downloader,
                              lldb::ModuleSP &cached_module_sp,
                              bool *did_create_ptr) {
  const auto module_spec_dir =
      GetModuleDirectory(root_dir_spec, module_spec.GetUUID());
  auto error = MakeDirectory(module_spec_dir);
  if (error.Fail())
    return error;

  ModuleLock lock(root_dir_spec, module_spec.GetUUID(), error);
  if (error.Fail())
    return Status::FromErrorStringWithFormat(
        "Failed to lock module %s: %s",
        module_spec.GetUUID().GetAsString().c_str(), error.AsCString());

  const auto escaped_hostname(GetEscapedHostname(hostname));
  // Check local cache for a module.
  error = Get(root_dir_spec, escaped_hostname.c_str(), module_spec,
              cached_module_sp, did_create_ptr);
  if (error.Success())
    return error;

  const auto tmp_download_file_spec = JoinPath(module_spec_dir, kTempFileName);
  error = module_downloader(module_spec, tmp_download_file_spec);
  llvm::FileRemover tmp_file_remover(tmp_download_file_spec.GetPath());
  if (error.Fail())
    return Status::FromErrorStringWithFormat("Failed to download module: %s",
                                             error.AsCString());

  // Put downloaded file into local module cache.
  error = Put(root_dir_spec, escaped_hostname.c_str(), module_spec,
              tmp_download_file_spec, module_spec.GetFileSpec());
  if (error.Fail())
    return Status::FromErrorStringWithFormat(
        "Failed to put module into cache: %s", error.AsCString());

  tmp_file_remover.releaseFile();
  error = Get(root_dir_spec, escaped_hostname.c_str(), module_spec,
              cached_module_sp, did_create_ptr);
  if (error.Fail())
    return error;

  // Fetching a symbol file for the module
  const auto tmp_download_sym_file_spec =
      JoinPath(module_spec_dir, kTempSymFileName);
  error = symfile_downloader(cached_module_sp, tmp_download_sym_file_spec);
  llvm::FileRemover tmp_symfile_remover(tmp_download_sym_file_spec.GetPath());
  if (error.Fail())
    // Failed to download a symfile but fetching the module was successful. The
    // module might contain the necessary symbols and the debugging is also
    // possible without a symfile.
    return Status();

  error = Put(root_dir_spec, escaped_hostname.c_str(), module_spec,
              tmp_download_sym_file_spec,
              GetSymbolFileSpec(module_spec.GetFileSpec()));
  if (error.Fail())
    return Status::FromErrorStringWithFormat(
        "Failed to put symbol file into cache: %s", error.AsCString());

  tmp_symfile_remover.releaseFile();

  FileSpec symfile_spec = GetSymbolFileSpec(cached_module_sp->GetFileSpec());
  cached_module_sp->SetSymbolFileFileSpec(symfile_spec);
  return Status();
}
