//===-- SBPlatform.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/API/SBPlatform.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEnvironment.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBLaunchInfo.h"
#include "lldb/API/SBModuleSpec.h"
#include "lldb/API/SBProcessInfoList.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBUnixSignals.h"
#include "lldb/Host/File.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/Instrumentation.h"
#include "lldb/Utility/Status.h"

#include "llvm/Support/FileSystem.h"

#include <functional>

using namespace lldb;
using namespace lldb_private;

// PlatformConnectOptions
struct PlatformConnectOptions {
  PlatformConnectOptions(const char *url = nullptr) {
    if (url && url[0])
      m_url = url;
  }

  ~PlatformConnectOptions() = default;

  std::string m_url;
  std::string m_rsync_options;
  std::string m_rsync_remote_path_prefix;
  bool m_rsync_enabled = false;
  bool m_rsync_omit_hostname_from_remote_path = false;
  ConstString m_local_cache_directory;
};

// PlatformShellCommand
struct PlatformShellCommand {
  PlatformShellCommand(llvm::StringRef shell_interpreter,
                       llvm::StringRef shell_command) {
    if (!shell_interpreter.empty())
      m_shell = shell_interpreter.str();

    if (!m_shell.empty() && !shell_command.empty())
      m_command = shell_command.str();
  }

  PlatformShellCommand(llvm::StringRef shell_command = llvm::StringRef()) {
    if (!shell_command.empty())
      m_command = shell_command.str();
  }

  ~PlatformShellCommand() = default;

  std::string m_shell;
  std::string m_command;
  std::string m_working_dir;
  std::string m_output;
  int m_status = 0;
  int m_signo = 0;
  Timeout<std::ratio<1>> m_timeout = std::nullopt;
};
// SBPlatformConnectOptions
SBPlatformConnectOptions::SBPlatformConnectOptions(const char *url)
    : m_opaque_ptr(new PlatformConnectOptions(url)) {
  LLDB_INSTRUMENT_VA(this, url);
}

SBPlatformConnectOptions::SBPlatformConnectOptions(
    const SBPlatformConnectOptions &rhs)
    : m_opaque_ptr(new PlatformConnectOptions()) {
  LLDB_INSTRUMENT_VA(this, rhs);

  *m_opaque_ptr = *rhs.m_opaque_ptr;
}

SBPlatformConnectOptions::~SBPlatformConnectOptions() { delete m_opaque_ptr; }

SBPlatformConnectOptions &
SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs) {
  LLDB_INSTRUMENT_VA(this, rhs);

  *m_opaque_ptr = *rhs.m_opaque_ptr;
  return *this;
}

const char *SBPlatformConnectOptions::GetURL() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_ptr->m_url.empty())
    return nullptr;
  return ConstString(m_opaque_ptr->m_url).GetCString();
}

void SBPlatformConnectOptions::SetURL(const char *url) {
  LLDB_INSTRUMENT_VA(this, url);

  if (url && url[0])
    m_opaque_ptr->m_url = url;
  else
    m_opaque_ptr->m_url.clear();
}

bool SBPlatformConnectOptions::GetRsyncEnabled() {
  LLDB_INSTRUMENT_VA(this);

  return m_opaque_ptr->m_rsync_enabled;
}

void SBPlatformConnectOptions::EnableRsync(
    const char *options, const char *remote_path_prefix,
    bool omit_hostname_from_remote_path) {
  LLDB_INSTRUMENT_VA(this, options, remote_path_prefix,
                     omit_hostname_from_remote_path);

  m_opaque_ptr->m_rsync_enabled = true;
  m_opaque_ptr->m_rsync_omit_hostname_from_remote_path =
      omit_hostname_from_remote_path;
  if (remote_path_prefix && remote_path_prefix[0])
    m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix;
  else
    m_opaque_ptr->m_rsync_remote_path_prefix.clear();

  if (options && options[0])
    m_opaque_ptr->m_rsync_options = options;
  else
    m_opaque_ptr->m_rsync_options.clear();
}

void SBPlatformConnectOptions::DisableRsync() {
  LLDB_INSTRUMENT_VA(this);

  m_opaque_ptr->m_rsync_enabled = false;
}

const char *SBPlatformConnectOptions::GetLocalCacheDirectory() {
  LLDB_INSTRUMENT_VA(this);

  return m_opaque_ptr->m_local_cache_directory.GetCString();
}

void SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path) {
  LLDB_INSTRUMENT_VA(this, path);

  if (path && path[0])
    m_opaque_ptr->m_local_cache_directory.SetCString(path);
  else
    m_opaque_ptr->m_local_cache_directory = ConstString();
}

// SBPlatformShellCommand
SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_interpreter,
                                               const char *shell_command)
    : m_opaque_ptr(new PlatformShellCommand(shell_interpreter, shell_command)) {
  LLDB_INSTRUMENT_VA(this, shell_interpreter, shell_command);
}

SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_command)
    : m_opaque_ptr(new PlatformShellCommand(shell_command)) {
  LLDB_INSTRUMENT_VA(this, shell_command);
}

SBPlatformShellCommand::SBPlatformShellCommand(
    const SBPlatformShellCommand &rhs)
    : m_opaque_ptr(new PlatformShellCommand()) {
  LLDB_INSTRUMENT_VA(this, rhs);

  *m_opaque_ptr = *rhs.m_opaque_ptr;
}

SBPlatformShellCommand &
SBPlatformShellCommand::operator=(const SBPlatformShellCommand &rhs) {

  LLDB_INSTRUMENT_VA(this, rhs);

  *m_opaque_ptr = *rhs.m_opaque_ptr;
  return *this;
}

SBPlatformShellCommand::~SBPlatformShellCommand() { delete m_opaque_ptr; }

void SBPlatformShellCommand::Clear() {
  LLDB_INSTRUMENT_VA(this);

  m_opaque_ptr->m_output = std::string();
  m_opaque_ptr->m_status = 0;
  m_opaque_ptr->m_signo = 0;
}

const char *SBPlatformShellCommand::GetShell() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_ptr->m_shell.empty())
    return nullptr;
  return ConstString(m_opaque_ptr->m_shell).GetCString();
}

void SBPlatformShellCommand::SetShell(const char *shell_interpreter) {
  LLDB_INSTRUMENT_VA(this, shell_interpreter);

  if (shell_interpreter && shell_interpreter[0])
    m_opaque_ptr->m_shell = shell_interpreter;
  else
    m_opaque_ptr->m_shell.clear();
}

const char *SBPlatformShellCommand::GetCommand() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_ptr->m_command.empty())
    return nullptr;
  return ConstString(m_opaque_ptr->m_command).GetCString();
}

void SBPlatformShellCommand::SetCommand(const char *shell_command) {
  LLDB_INSTRUMENT_VA(this, shell_command);

  if (shell_command && shell_command[0])
    m_opaque_ptr->m_command = shell_command;
  else
    m_opaque_ptr->m_command.clear();
}

const char *SBPlatformShellCommand::GetWorkingDirectory() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_ptr->m_working_dir.empty())
    return nullptr;
  return ConstString(m_opaque_ptr->m_working_dir).GetCString();
}

void SBPlatformShellCommand::SetWorkingDirectory(const char *path) {
  LLDB_INSTRUMENT_VA(this, path);

  if (path && path[0])
    m_opaque_ptr->m_working_dir = path;
  else
    m_opaque_ptr->m_working_dir.clear();
}

uint32_t SBPlatformShellCommand::GetTimeoutSeconds() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_ptr->m_timeout)
    return m_opaque_ptr->m_timeout->count();
  return UINT32_MAX;
}

void SBPlatformShellCommand::SetTimeoutSeconds(uint32_t sec) {
  LLDB_INSTRUMENT_VA(this, sec);

  if (sec == UINT32_MAX)
    m_opaque_ptr->m_timeout = std::nullopt;
  else
    m_opaque_ptr->m_timeout = std::chrono::seconds(sec);
}

int SBPlatformShellCommand::GetSignal() {
  LLDB_INSTRUMENT_VA(this);

  return m_opaque_ptr->m_signo;
}

int SBPlatformShellCommand::GetStatus() {
  LLDB_INSTRUMENT_VA(this);

  return m_opaque_ptr->m_status;
}

const char *SBPlatformShellCommand::GetOutput() {
  LLDB_INSTRUMENT_VA(this);

  if (m_opaque_ptr->m_output.empty())
    return nullptr;
  return ConstString(m_opaque_ptr->m_output).GetCString();
}

// SBPlatform
SBPlatform::SBPlatform() { LLDB_INSTRUMENT_VA(this); }

SBPlatform::SBPlatform(const char *platform_name) {
  LLDB_INSTRUMENT_VA(this, platform_name);

  m_opaque_sp = Platform::Create(platform_name);
}

SBPlatform::SBPlatform(const SBPlatform &rhs) {
  LLDB_INSTRUMENT_VA(this, rhs);

  m_opaque_sp = rhs.m_opaque_sp;
}

SBPlatform &SBPlatform::operator=(const SBPlatform &rhs) {
  LLDB_INSTRUMENT_VA(this, rhs);

  m_opaque_sp = rhs.m_opaque_sp;
  return *this;
}

SBPlatform::~SBPlatform() = default;

SBPlatform SBPlatform::GetHostPlatform() {
  LLDB_INSTRUMENT();

  SBPlatform host_platform;
  host_platform.m_opaque_sp = Platform::GetHostPlatform();
  return host_platform;
}

bool SBPlatform::IsValid() const {
  LLDB_INSTRUMENT_VA(this);
  return this->operator bool();
}
SBPlatform::operator bool() const {
  LLDB_INSTRUMENT_VA(this);

  return m_opaque_sp.get() != nullptr;
}

bool SBPlatform::IsHost() const {
  LLDB_INSTRUMENT_VA(this);
  return m_opaque_sp.get() != nullptr && m_opaque_sp->IsHost();
}

void SBPlatform::Clear() {
  LLDB_INSTRUMENT_VA(this);

  m_opaque_sp.reset();
}

const char *SBPlatform::GetName() {
  LLDB_INSTRUMENT_VA(this);

  PlatformSP platform_sp(GetSP());
  if (platform_sp)
    return ConstString(platform_sp->GetName()).AsCString(nullptr);
  return nullptr;
}

lldb::PlatformSP SBPlatform::GetSP() const { return m_opaque_sp; }

void SBPlatform::SetSP(const lldb::PlatformSP &platform_sp) {
  m_opaque_sp = platform_sp;
}

const char *SBPlatform::GetWorkingDirectory() {
  LLDB_INSTRUMENT_VA(this);

  PlatformSP platform_sp(GetSP());
  if (platform_sp)
    return platform_sp->GetWorkingDirectory().GetPathAsConstString().AsCString(
        nullptr);
  return nullptr;
}

bool SBPlatform::SetWorkingDirectory(const char *path) {
  LLDB_INSTRUMENT_VA(this, path);

  PlatformSP platform_sp(GetSP());
  if (platform_sp) {
    if (path)
      platform_sp->SetWorkingDirectory(FileSpec(path));
    else
      platform_sp->SetWorkingDirectory(FileSpec());
    return true;
  }
  return false;
}

SBError SBPlatform::ConnectRemote(SBPlatformConnectOptions &connect_options) {
  LLDB_INSTRUMENT_VA(this, connect_options);

  SBError sb_error;
  PlatformSP platform_sp(GetSP());
  if (platform_sp && connect_options.GetURL()) {
    Args args;
    args.AppendArgument(connect_options.GetURL());
    sb_error.ref() = platform_sp->ConnectRemote(args);
  } else {
    sb_error = Status::FromErrorString("invalid platform");
  }
  return sb_error;
}

void SBPlatform::DisconnectRemote() {
  LLDB_INSTRUMENT_VA(this);

  PlatformSP platform_sp(GetSP());
  if (platform_sp)
    platform_sp->DisconnectRemote();
}

bool SBPlatform::IsConnected() {
  LLDB_INSTRUMENT_VA(this);

  PlatformSP platform_sp(GetSP());
  if (platform_sp)
    return platform_sp->IsConnected();
  return false;
}

const char *SBPlatform::GetTriple() {
  LLDB_INSTRUMENT_VA(this);

  PlatformSP platform_sp(GetSP());
  if (platform_sp) {
    ArchSpec arch(platform_sp->GetSystemArchitecture());
    if (arch.IsValid()) {
      // Const-ify the string so we don't need to worry about the lifetime of
      // the string
      return ConstString(arch.GetTriple().getTriple()).GetCString();
    }
  }
  return nullptr;
}

const char *SBPlatform::GetOSBuild() {
  LLDB_INSTRUMENT_VA(this);

  PlatformSP platform_sp(GetSP());
  if (platform_sp) {
    std::string s = platform_sp->GetOSBuildString().value_or("");
    if (!s.empty()) {
      // Const-ify the string so we don't need to worry about the lifetime of
      // the string
      return ConstString(s).GetCString();
    }
  }
  return nullptr;
}

const char *SBPlatform::GetOSDescription() {
  LLDB_INSTRUMENT_VA(this);

  PlatformSP platform_sp(GetSP());
  if (platform_sp) {
    std::string s = platform_sp->GetOSKernelDescription().value_or("");
    if (!s.empty()) {
      // Const-ify the string so we don't need to worry about the lifetime of
      // the string
      return ConstString(s).GetCString();
    }
  }
  return nullptr;
}

const char *SBPlatform::GetHostname() {
  LLDB_INSTRUMENT_VA(this);

  PlatformSP platform_sp(GetSP());
  if (platform_sp)
    return ConstString(platform_sp->GetHostname()).GetCString();
  return nullptr;
}

uint32_t SBPlatform::GetOSMajorVersion() {
  LLDB_INSTRUMENT_VA(this);

  llvm::VersionTuple version;
  if (PlatformSP platform_sp = GetSP())
    version = platform_sp->GetOSVersion();
  return version.empty() ? UINT32_MAX : version.getMajor();
}

uint32_t SBPlatform::GetOSMinorVersion() {
  LLDB_INSTRUMENT_VA(this);

  llvm::VersionTuple version;
  if (PlatformSP platform_sp = GetSP())
    version = platform_sp->GetOSVersion();
  return version.getMinor().value_or(UINT32_MAX);
}

uint32_t SBPlatform::GetOSUpdateVersion() {
  LLDB_INSTRUMENT_VA(this);

  llvm::VersionTuple version;
  if (PlatformSP platform_sp = GetSP())
    version = platform_sp->GetOSVersion();
  return version.getSubminor().value_or(UINT32_MAX);
}

void SBPlatform::SetSDKRoot(const char *sysroot) {
  LLDB_INSTRUMENT_VA(this, sysroot);
  if (PlatformSP platform_sp = GetSP())
    platform_sp->SetSDKRootDirectory(llvm::StringRef(sysroot).str());
}

SBError SBPlatform::Get(SBFileSpec &src, SBFileSpec &dst) {
  LLDB_INSTRUMENT_VA(this, src, dst);

  SBError sb_error;
  PlatformSP platform_sp(GetSP());
  if (platform_sp) {
    sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref());
  } else {
    sb_error = Status::FromErrorString("invalid platform");
  }
  return sb_error;
}

SBError SBPlatform::Put(SBFileSpec &src, SBFileSpec &dst) {
  LLDB_INSTRUMENT_VA(this, src, dst);
  return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
    if (src.Exists()) {
      uint32_t permissions = FileSystem::Instance().GetPermissions(src.ref());
      if (permissions == 0) {
        if (FileSystem::Instance().IsDirectory(src.ref()))
          permissions = eFilePermissionsDirectoryDefault;
        else
          permissions = eFilePermissionsFileDefault;
      }

      return platform_sp->PutFile(src.ref(), dst.ref(), permissions);
    }

    return Status::FromErrorStringWithFormat(
        "'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
  });
}

SBError SBPlatform::Install(SBFileSpec &src, SBFileSpec &dst) {
  LLDB_INSTRUMENT_VA(this, src, dst);
  return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
    if (src.Exists())
      return platform_sp->Install(src.ref(), dst.ref());

    Status error;
    error = Status::FromErrorStringWithFormat(
        "'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
    return error;
  });
}

SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) {
  LLDB_INSTRUMENT_VA(this, shell_command);
  return ExecuteConnected(
      [&](const lldb::PlatformSP &platform_sp) {
        const char *command = shell_command.GetCommand();
        if (!command)
          return Status::FromErrorString("invalid shell command (empty)");

        if (shell_command.GetWorkingDirectory() == nullptr) {
          std::string platform_working_dir =
              platform_sp->GetWorkingDirectory().GetPath();
          if (!platform_working_dir.empty())
            shell_command.SetWorkingDirectory(platform_working_dir.c_str());
        }
        return platform_sp->RunShellCommand(
            shell_command.m_opaque_ptr->m_shell, command,
            FileSpec(shell_command.GetWorkingDirectory()),
            &shell_command.m_opaque_ptr->m_status,
            &shell_command.m_opaque_ptr->m_signo,
            &shell_command.m_opaque_ptr->m_output, nullptr,
            shell_command.m_opaque_ptr->m_timeout);
      });
}

SBError SBPlatform::Launch(SBLaunchInfo &launch_info) {
  LLDB_INSTRUMENT_VA(this, launch_info);
  return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
    ProcessLaunchInfo info = launch_info.ref();
    Status error = platform_sp->LaunchProcess(info);
    launch_info.set_ref(info);
    return error;
  });
}

SBProcess SBPlatform::Attach(SBAttachInfo &attach_info,
                             const SBDebugger &debugger, SBTarget &target,
                             SBError &error) {
  LLDB_INSTRUMENT_VA(this, attach_info, debugger, target, error);

  if (PlatformSP platform_sp = GetSP()) {
    if (platform_sp->IsConnected()) {
      ProcessAttachInfo &info = attach_info.ref();
      Status status;
      ProcessSP process_sp = platform_sp->Attach(info, debugger.ref(),
                                                 target.GetSP().get(), status);
      error.SetError(std::move(status));
      return SBProcess(process_sp);
    }

    error = Status::FromErrorString("not connected");
    return {};
  }

  error = Status::FromErrorString("invalid platform");
  return {};
}

SBProcessInfoList SBPlatform::GetAllProcesses(SBError &error) {
  if (PlatformSP platform_sp = GetSP()) {
    if (platform_sp->IsConnected()) {
      ProcessInstanceInfoList list = platform_sp->GetAllProcesses();
      return SBProcessInfoList(list);
    }
    error = Status::FromErrorString("not connected");
    return {};
  }

  error = Status::FromErrorString("invalid platform");
  return {};
}

SBError SBPlatform::Kill(const lldb::pid_t pid) {
  LLDB_INSTRUMENT_VA(this, pid);
  return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
    return platform_sp->KillProcess(pid);
  });
}

SBError SBPlatform::ExecuteConnected(
    const std::function<Status(const lldb::PlatformSP &)> &func) {
  SBError sb_error;
  const auto platform_sp(GetSP());
  if (platform_sp) {
    if (platform_sp->IsConnected())
      sb_error.ref() = func(platform_sp);
    else
      sb_error = Status::FromErrorString("not connected");
  } else
    sb_error = Status::FromErrorString("invalid platform");

  return sb_error;
}

SBError SBPlatform::MakeDirectory(const char *path, uint32_t file_permissions) {
  LLDB_INSTRUMENT_VA(this, path, file_permissions);

  SBError sb_error;
  PlatformSP platform_sp(GetSP());
  if (platform_sp) {
    sb_error.ref() =
        platform_sp->MakeDirectory(FileSpec(path), file_permissions);
  } else {
    sb_error = Status::FromErrorString("invalid platform");
  }
  return sb_error;
}

uint32_t SBPlatform::GetFilePermissions(const char *path) {
  LLDB_INSTRUMENT_VA(this, path);

  PlatformSP platform_sp(GetSP());
  if (platform_sp) {
    uint32_t file_permissions = 0;
    platform_sp->GetFilePermissions(FileSpec(path), file_permissions);
    return file_permissions;
  }
  return 0;
}

SBError SBPlatform::SetFilePermissions(const char *path,
                                       uint32_t file_permissions) {
  LLDB_INSTRUMENT_VA(this, path, file_permissions);

  SBError sb_error;
  PlatformSP platform_sp(GetSP());
  if (platform_sp) {
    sb_error.ref() =
        platform_sp->SetFilePermissions(FileSpec(path), file_permissions);
  } else {
    sb_error = Status::FromErrorString("invalid platform");
  }
  return sb_error;
}

SBUnixSignals SBPlatform::GetUnixSignals() const {
  LLDB_INSTRUMENT_VA(this);

  if (auto platform_sp = GetSP())
    return SBUnixSignals{platform_sp};

  return SBUnixSignals();
}

SBEnvironment SBPlatform::GetEnvironment() {
  LLDB_INSTRUMENT_VA(this);
  PlatformSP platform_sp(GetSP());

  if (platform_sp) {
    return SBEnvironment(platform_sp->GetEnvironment());
  }

  return SBEnvironment();
}

SBError SBPlatform::SetLocateModuleCallback(
    lldb::SBPlatformLocateModuleCallback callback, void *callback_baton) {
  LLDB_INSTRUMENT_VA(this, callback, callback_baton);
  PlatformSP platform_sp(GetSP());
  if (!platform_sp)
    return SBError("invalid platform");

  if (!callback) {
    // Clear the callback.
    platform_sp->SetLocateModuleCallback(nullptr);
    return SBError();
  }

  // Platform.h does not accept lldb::SBPlatformLocateModuleCallback directly
  // because of the SBModuleSpec and SBFileSpec dependencies. Use a lambda to
  // convert ModuleSpec/FileSpec <--> SBModuleSpec/SBFileSpec for the callback
  // arguments.
  platform_sp->SetLocateModuleCallback(
      [callback, callback_baton](const ModuleSpec &module_spec,
                                 FileSpec &module_file_spec,
                                 FileSpec &symbol_file_spec) {
        SBModuleSpec module_spec_sb(module_spec);
        SBFileSpec module_file_spec_sb;
        SBFileSpec symbol_file_spec_sb;

        SBError error = callback(callback_baton, module_spec_sb,
                                 module_file_spec_sb, symbol_file_spec_sb);

        if (error.Success()) {
          module_file_spec = module_file_spec_sb.ref();
          symbol_file_spec = symbol_file_spec_sb.ref();
        }

        return error.ref().Clone();
      });
  return SBError();
}
