//===-- source/Host/aix/Host.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/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/posix/Support.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/ProcessInfo.h"
#include "lldb/Utility/Status.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/Object/XCOFFObjectFile.h"
#include "llvm/Support/MemoryBuffer.h"
#include <dirent.h>
#include <sys/proc.h>
#include <sys/procfs.h>

using namespace lldb;
using namespace lldb_private;

namespace {
enum class ProcessState {
  Unknown,
  Dead,
  DiskSleep,
  Idle,
  Paging,
  Parked,
  Running,
  Sleeping,
  TracedOrStopped,
  Zombie,
};
}

static ProcessInstanceInfo::timespec convert(pr_timestruc64_t t) {
  ProcessInstanceInfo::timespec ts;
  ts.tv_sec = t.tv_sec;
  ts.tv_usec = t.tv_nsec / 1000; // nanos to micros
  return ts;
}

static bool GetStatusInfo(::pid_t pid, ProcessInstanceInfo &processInfo,
                          ProcessState &State) {
  struct pstatus pstatusData;
  auto BufferOrError = getProcFile(pid, "status");
  if (!BufferOrError)
    return false;

  std::unique_ptr<llvm::MemoryBuffer> StatusBuffer = std::move(*BufferOrError);
  // Ensure there's enough data for psinfoData
  if (StatusBuffer->getBufferSize() < sizeof(pstatusData))
    return false;

  std::memcpy(&pstatusData, StatusBuffer->getBufferStart(),
              sizeof(pstatusData));
  switch (pstatusData.pr_stat) {
  case SIDL:
    State = ProcessState::Idle;
    break;
  case SACTIVE:
    State = ProcessState::Running;
    break;
  case SSTOP:
    State = ProcessState::TracedOrStopped;
    break;
  case SZOMB:
    State = ProcessState::Zombie;
    break;
  default:
    State = ProcessState::Unknown;
    break;
  }
  processInfo.SetIsZombie(State == ProcessState::Zombie);
  processInfo.SetUserTime(convert(pstatusData.pr_utime));
  processInfo.SetSystemTime(convert(pstatusData.pr_stime));
  processInfo.SetCumulativeUserTime(convert(pstatusData.pr_cutime));
  processInfo.SetCumulativeSystemTime(convert(pstatusData.pr_cstime));
  return true;
}

static ArchSpec GetXCOFFProcessCPUType(llvm::StringRef exe_path) {
  Log *log = GetLog(LLDBLog::Host);

  auto file_buffer = llvm::MemoryBuffer::getFile(exe_path);
  if (!file_buffer)
    return ArchSpec();

  llvm::Expected<std::unique_ptr<llvm::object::ObjectFile>> obj_or_err =
      llvm::object::ObjectFile::createObjectFile(
          (*file_buffer)->getMemBufferRef());

  if (!obj_or_err) {
    LLDB_LOG(log, "failed to create ObjectFile from buffer");
    return ArchSpec();
  }

  llvm::object::ObjectFile *obj = obj_or_err->get();

  const llvm::object::XCOFFObjectFile *xcoff_obj =
      llvm::dyn_cast<llvm::object::XCOFFObjectFile>(obj);
  if (!xcoff_obj) {
    LLDB_LOG(log, "Not an valid XCOFF object file: {0}", exe_path);
    return ArchSpec();
  }

  if (xcoff_obj->is64Bit())
    return HostInfo::GetArchitecture(HostInfo::eArchKind64);

  return HostInfo::GetArchitecture(HostInfo::eArchKind32);
}

static bool GetExePathAndIds(::pid_t pid, ProcessInstanceInfo &process_info) {
  struct psinfo psinfoData;
  auto BufferOrError = getProcFile(pid, "psinfo");
  if (!BufferOrError)
    return false;

  std::unique_ptr<llvm::MemoryBuffer> PsinfoBuffer = std::move(*BufferOrError);
  // Ensure there's enough data for psinfoData
  if (PsinfoBuffer->getBufferSize() < sizeof(psinfoData))
    return false;

  std::memcpy(&psinfoData, PsinfoBuffer->getBufferStart(), sizeof(psinfoData));
  llvm::StringRef PathRef(
      psinfoData.pr_psargs,
      strnlen(psinfoData.pr_psargs, sizeof(psinfoData.pr_psargs)));
  if (PathRef.empty())
    return false;

  process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native);
  ArchSpec arch_spec = GetXCOFFProcessCPUType(PathRef);
  if (!arch_spec)
    return false;
  process_info.SetArchitecture(arch_spec);
  process_info.SetParentProcessID(psinfoData.pr_ppid);
  process_info.SetGroupID(psinfoData.pr_gid);
  process_info.SetEffectiveGroupID(psinfoData.pr_egid);
  process_info.SetUserID(psinfoData.pr_uid);
  process_info.SetEffectiveUserID(psinfoData.pr_euid);
  process_info.SetProcessGroupID(psinfoData.pr_pgid);
  process_info.SetProcessSessionID(psinfoData.pr_sid);
  return true;
}

static bool GetProcessAndStatInfo(::pid_t pid,
                                  ProcessInstanceInfo &process_info,
                                  ProcessState &State) {
  process_info.Clear();
  process_info.SetProcessID(pid);

  if (pid == LLDB_INVALID_PROCESS_ID)
    return false;
  // Get Executable path/Arch and Get User and Group IDs.
  if (!GetExePathAndIds(pid, process_info))
    return false;
  // Get process status and timing info.
  if (!GetStatusInfo(pid, process_info, State))
    return false;

  return true;
}

uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,
                                 ProcessInstanceInfoList &process_infos) {
  static const char procdir[] = "/proc/";

  DIR *dirproc = opendir(procdir);
  if (dirproc) {
    struct dirent *direntry = nullptr;
    const uid_t our_uid = getuid();
    const lldb::pid_t our_pid = getpid();
    bool all_users = match_info.GetMatchAllUsers();

    while ((direntry = readdir(dirproc)) != nullptr) {
      lldb::pid_t pid;
      // Skip non-numeric name directories
      if (!llvm::to_integer(direntry->d_name, pid))
        continue;
      // Skip this process.
      if (pid == our_pid)
        continue;

      ProcessState State;
      ProcessInstanceInfo process_info;
      if (!GetProcessAndStatInfo(pid, process_info, State))
        continue;

      if (State == ProcessState::Zombie ||
          State == ProcessState::TracedOrStopped)
        continue;

      // Check for user match if we're not matching all users and not running
      // as root.
      if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid))
        continue;

      if (match_info.Matches(process_info))
        process_infos.push_back(process_info);
    }
    closedir(dirproc);
  }
  return process_infos.size();
}

bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
  ProcessState State;
  return GetProcessAndStatInfo(pid, process_info, State);
}

Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
  return Status("unimplemented");
}
