//===-- 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/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);
    }
  }

  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/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());
  }
}
