//===-- HostInfoLinux.cpp ---------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Host/Config.h"
#include "lldb/Host/linux/HostInfoLinux.h"
#include "lldb/Utility/Log.h"

#include "llvm/Support/Threading.h"

#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <sys/utsname.h>
#include <unistd.h>

#include <algorithm>
#include <mutex> // std::once

using namespace lldb_private;

namespace {
struct HostInfoLinuxFields {
  HostInfoLinuxFields() : m_os_major(0), m_os_minor(0), m_os_update(0) {}

  std::string m_distribution_id;
  uint32_t m_os_major;
  uint32_t m_os_minor;
  uint32_t m_os_update;
};

HostInfoLinuxFields *g_fields = nullptr;
}

void HostInfoLinux::Initialize() {
  HostInfoPosix::Initialize();

  g_fields = new HostInfoLinuxFields();
}

bool HostInfoLinux::GetOSVersion(uint32_t &major, uint32_t &minor,
                                 uint32_t &update) {
  static bool success = false;
  static llvm::once_flag g_once_flag;
  llvm::call_once(g_once_flag, []() {

    struct utsname un;
    if (uname(&un) == 0) {
      int status = sscanf(un.release, "%u.%u.%u", &g_fields->m_os_major,
                          &g_fields->m_os_minor, &g_fields->m_os_update);
      if (status == 3)
        success = true;
      else {
        // Some kernels omit the update version, so try looking for just "X.Y"
        // and set update to 0.
        g_fields->m_os_update = 0;
        status = sscanf(un.release, "%u.%u", &g_fields->m_os_major,
                        &g_fields->m_os_minor);
        if (status == 2)
          success = true;
      }
    }
  });

  major = g_fields->m_os_major;
  minor = g_fields->m_os_minor;
  update = g_fields->m_os_update;
  return success;
}

bool HostInfoLinux::GetOSBuildString(std::string &s) {
  struct utsname un;
  ::memset(&un, 0, sizeof(utsname));
  s.clear();

  if (uname(&un) < 0)
    return false;

  s.assign(un.release);
  return true;
}

bool HostInfoLinux::GetOSKernelDescription(std::string &s) {
  struct utsname un;

  ::memset(&un, 0, sizeof(utsname));
  s.clear();

  if (uname(&un) < 0)
    return false;

  s.assign(un.version);
  return true;
}

llvm::StringRef HostInfoLinux::GetDistributionId() {
  // Try to run 'lbs_release -i', and use that response for the distribution
  // id.
  static llvm::once_flag g_once_flag;
  llvm::call_once(g_once_flag, []() {

    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST));
    if (log)
      log->Printf("attempting to determine Linux distribution...");

    // check if the lsb_release command exists at one of the following paths
    const char *const exe_paths[] = {"/bin/lsb_release",
                                     "/usr/bin/lsb_release"};

    for (size_t exe_index = 0;
         exe_index < sizeof(exe_paths) / sizeof(exe_paths[0]); ++exe_index) {
      const char *const get_distribution_info_exe = exe_paths[exe_index];
      if (access(get_distribution_info_exe, F_OK)) {
        // this exe doesn't exist, move on to next exe
        if (log)
          log->Printf("executable doesn't exist: %s",
                      get_distribution_info_exe);
        continue;
      }

      // execute the distribution-retrieval command, read output
      std::string get_distribution_id_command(get_distribution_info_exe);
      get_distribution_id_command += " -i";

      FILE *file = popen(get_distribution_id_command.c_str(), "r");
      if (!file) {
        if (log)
          log->Printf("failed to run command: \"%s\", cannot retrieve "
                      "platform information",
                      get_distribution_id_command.c_str());
        break;
      }

      // retrieve the distribution id string.
      char distribution_id[256] = {'\0'};
      if (fgets(distribution_id, sizeof(distribution_id) - 1, file) != NULL) {
        if (log)
          log->Printf("distribution id command returned \"%s\"",
                      distribution_id);

        const char *const distributor_id_key = "Distributor ID:\t";
        if (strstr(distribution_id, distributor_id_key)) {
          // strip newlines
          std::string id_string(distribution_id + strlen(distributor_id_key));
          id_string.erase(std::remove(id_string.begin(), id_string.end(), '\n'),
                          id_string.end());

          // lower case it and convert whitespace to underscores
          std::transform(
              id_string.begin(), id_string.end(), id_string.begin(),
              [](char ch) { return tolower(isspace(ch) ? '_' : ch); });

          g_fields->m_distribution_id = id_string;
          if (log)
            log->Printf("distribution id set to \"%s\"",
                        g_fields->m_distribution_id.c_str());
        } else {
          if (log)
            log->Printf("failed to find \"%s\" field in \"%s\"",
                        distributor_id_key, distribution_id);
        }
      } else {
        if (log)
          log->Printf("failed to retrieve distribution id, \"%s\" returned no"
                      " lines",
                      get_distribution_id_command.c_str());
      }

      // clean up the file
      pclose(file);
    }
  });

  return g_fields->m_distribution_id;
}

FileSpec HostInfoLinux::GetProgramFileSpec() {
  static FileSpec g_program_filespec;

  if (!g_program_filespec) {
    char exe_path[PATH_MAX];
    ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
    if (len > 0) {
      exe_path[len] = 0;
      g_program_filespec.SetFile(exe_path, false, FileSpec::Style::native);
    }
  }

  return g_program_filespec;
}

bool HostInfoLinux::ComputeSupportExeDirectory(FileSpec &file_spec) {
  if (HostInfoPosix::ComputeSupportExeDirectory(file_spec) &&
      file_spec.IsAbsolute() && file_spec.Exists())
    return true;
  file_spec.GetDirectory() = GetProgramFileSpec().GetDirectory();
  return !file_spec.GetDirectory().IsEmpty();
}

bool HostInfoLinux::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
  FileSpec temp_file("/usr/lib" LLDB_LIBDIR_SUFFIX "/lldb/plugins", true);
  file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
  return true;
}

bool HostInfoLinux::ComputeUserPluginsDirectory(FileSpec &file_spec) {
  // XDG Base Directory Specification
  // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html If
  // XDG_DATA_HOME exists, use that, otherwise use ~/.local/share/lldb.
  const char *xdg_data_home = getenv("XDG_DATA_HOME");
  if (xdg_data_home && xdg_data_home[0]) {
    std::string user_plugin_dir(xdg_data_home);
    user_plugin_dir += "/lldb";
    file_spec.GetDirectory().SetCString(user_plugin_dir.c_str());
  } else
    file_spec.GetDirectory().SetCString("~/.local/share/lldb");
  return true;
}

void HostInfoLinux::ComputeHostArchitectureSupport(ArchSpec &arch_32,
                                                   ArchSpec &arch_64) {
  HostInfoPosix::ComputeHostArchitectureSupport(arch_32, arch_64);

  const char *distribution_id = GetDistributionId().data();

  // On Linux, "unknown" in the vendor slot isn't what we want for the default
  // triple.  It's probably an artifact of config.guess.
  if (arch_32.IsValid()) {
    arch_32.SetDistributionId(distribution_id);
    if (arch_32.GetTriple().getVendor() == llvm::Triple::UnknownVendor)
      arch_32.GetTriple().setVendorName(llvm::StringRef());
  }
  if (arch_64.IsValid()) {
    arch_64.SetDistributionId(distribution_id);
    if (arch_64.GetTriple().getVendor() == llvm::Triple::UnknownVendor)
      arch_64.GetTriple().setVendorName(llvm::StringRef());
  }
}
