// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <grp.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

#include <memory>

#include <vector>

#include <base/check.h>
#include <base/files/file.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/process/launch.h>
#include <base/strings/stringprintf.h>

#include "mems_setup/delegate_impl.h"

namespace mems_setup {

namespace {
const char kVpdDataPath[] =
    "/mnt/stateful_partition/unencrypted/cache/vpd/full-v2.txt";
const char kSysModulePath[] = "/sys/module";
}  // namespace

bool LoadVpdFromString(const std::string& vpd_data,
                       std::map<std::string, std::string>* cache) {
  CHECK(cache);

  size_t nl_pos = 0;
  const size_t vpd_len = vpd_data.size();
  while (nl_pos < vpd_len) {
    const auto i_eq = vpd_data.find('=', nl_pos);
    if (i_eq == std::string::npos)
      break;

    auto i_nl = vpd_data.find('\n', i_eq + 1);
    if (i_nl == std::string::npos)
      i_nl = vpd_len;

    // VPD entries come in "key"="value" form, including the quotes;
    // the purpose of the substring operations here is to remove those
    // quotes, as they are inconvenient to deal with from C++ code.
    const auto key = vpd_data.substr(nl_pos + 1, i_eq - nl_pos - 2);
    const auto value = vpd_data.substr(i_eq + 2, i_nl - i_eq - 3);
    cache->emplace(key, value);

    nl_pos = i_nl + 1;
  }

  return true;
}

void DelegateImpl::LoadVpdIfNeeded() {
  if (vpd_loaded_)
    return;

  std::string vpd_data;
  base::FilePath vpd_path(kVpdDataPath);
  if (!base::ReadFileToString(vpd_path, &vpd_data)) {
    LOG(ERROR) << "failed to read VPD data";
    return;
  }

  vpd_loaded_ = LoadVpdFromString(vpd_data, &vpd_cache_);
}

base::Optional<std::string> DelegateImpl::ReadVpdValue(const std::string& key) {
  LoadVpdIfNeeded();

  auto k = vpd_cache_.find(key);
  if (k != vpd_cache_.end())
    return k->second;
  else
    return base::nullopt;
}

bool DelegateImpl::ProbeKernelModule(const std::string& module) {
  base::FilePath init_path(kSysModulePath);
  init_path = init_path.Append(module).Append("initstate");

  std::string init_data;

  // If we can tell that a module has been loaded, then just return along
  // the happy path instead of forking a new process.
  if (base::ReadFileToString(init_path, &init_data)) {
    if (init_data == "live\n")
      return true;
  }

  std::vector<std::string> argv;
  argv.emplace_back("/sbin/modprobe");
  argv.emplace_back("-q");
  argv.emplace_back(module);

  base::Process process(base::LaunchProcess(argv, base::LaunchOptions()));
  if (!process.IsValid()) {
    LOG(ERROR) << "failed to launch modprobe";
    return false;
  }
  int exit_code = -1;
  if (!process.WaitForExit(&exit_code)) {
    LOG(ERROR) << "modprobe exit could not be detected";
    return false;
  }
  return exit_code == 0;
}

bool DelegateImpl::CreateDirectory(const base::FilePath& fp) {
  return base::CreateDirectory(fp);
}

bool DelegateImpl::Exists(const base::FilePath& fp) {
  return base::PathExists(fp);
}

std::vector<base::FilePath> DelegateImpl::EnumerateAllFiles(
    base::FilePath file_path) {
  std::vector<base::FilePath> files;

  base::FileEnumerator file_enumerator(file_path, false,
                                       base::FileEnumerator::FILES);

  for (base::FilePath file = file_enumerator.Next(); !file.empty();
       file = file_enumerator.Next())
    files.push_back(file);

  return files;
}

base::Optional<gid_t> DelegateImpl::FindGroupId(const char* group) {
  size_t len = 1024;
  const auto max_len = sysconf(_SC_GETGR_R_SIZE_MAX);
  if (max_len != -1)
    len = max_len;

  std::vector<char> buf(len);
  struct group result;
  struct group* resultp = nullptr;

  getgrnam_r(group, &result, buf.data(), len, &resultp);
  if (!resultp)
    return base::nullopt;

  return resultp->gr_gid;
}

int DelegateImpl::GetPermissions(const base::FilePath& path) {
  int mode = 0;
  bool ok = base::GetPosixFilePermissions(path, &mode);
  if (ok)
    return mode;
  return 0;
}

bool DelegateImpl::SetPermissions(const base::FilePath& path, int mode) {
  return base::SetPosixFilePermissions(path, mode);
}

bool DelegateImpl::SetOwnership(const base::FilePath& path,
                                uid_t user,
                                gid_t group) {
  return lchown(path.value().c_str(), user, group) == 0;
}

}  // namespace mems_setup
