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

#include "dev-install/dev_install.h"

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <algorithm>
#include <iostream>
#include <istream>
#include <string>
#include <vector>

#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <brillo/key_value_store.h>
#include <brillo/process/process.h>
#include <vboot/crossystem.h>

namespace dev_install {

namespace {

// The root path that we install our dev packages into.
constexpr char kUsrLocal[] = "/usr/local";

// The Portage config path as a subdir under the various roots.
constexpr char kPortageConfigSubdir[] = "etc/portage";

// Where binpkgs are saved as a subdir under the various roots.
constexpr char kBinpkgSubdir[] = "portage/packages";

// File listing of packages we need for bootstrapping.
constexpr char kBootstrapListing[] =
    "/usr/share/dev-install/bootstrap.packages";

// Directory of rootfs provided packages.
constexpr char kRootfsProvidedDir[] = "/usr/share/dev-install/rootfs.provided";

// Path to lsb-release file.
constexpr char kLsbReleasePath[] = "/etc/lsb-release";

// The devserer URL for this developer build.
constexpr char kLsbChromeOsDevserver[] = "CHROMEOS_DEVSERVER";

// The current OS version.
constexpr char kLsbChromeOsReleaseVersion[] = "CHROMEOS_RELEASE_VERSION";

// Setting for the board name.
constexpr char kLsbChromeOsReleaseBoard[] = "CHROMEOS_RELEASE_BOARD";

// The base URL of the repository holding our portage prebuilt binpkgs.
constexpr char kDefaultBinhostPrefix[] =
    "https://commondatastorage.googleapis.com/chromeos-dev-installer/board";

// Portage binpkgs append metadata to the end of the bzip2 file which makes
// bzip2 warn "trailing garbage after EOF ignored".  This is harmless, but
// can be confusing & noisy, so suppress it with -q.
constexpr char kBzip2Cmd[] = "bzip2 -q";
constexpr uint8_t kBzip2Magic[] = {0x42, 0x5a, 0x68};

// Similarly, use zstd's -f to ignore that trailing data.
constexpr char kZstdCmd[] = "zstd -f";
constexpr uint8_t kZstdMagic[] = {0x28, 0xb5, 0x2f, 0xfd};

}  // namespace

DevInstall::DevInstall()
    : reinstall_(false),
      uninstall_(false),
      yes_(false),
      only_bootstrap_(false),
      state_dir_(kUsrLocal),
      binhost_(""),
      binhost_version_(""),
      jobs_(0) {}

DevInstall::DevInstall(const std::string& binhost,
                       const std::string& binhost_version,
                       bool reinstall,
                       bool uninstall,
                       bool yes,
                       bool only_bootstrap,
                       uint32_t jobs)
    : reinstall_(reinstall),
      uninstall_(uninstall),
      yes_(yes),
      only_bootstrap_(only_bootstrap),
      state_dir_(kUsrLocal),
      binhost_(binhost),
      binhost_version_(binhost_version),
      jobs_(jobs) {}

bool DevInstall::IsDevMode() const {
  int value = ::VbGetSystemPropertyInt("cros_debug");
  return value == 1;
}

bool DevInstall::PromptUser(std::istream& input, const std::string& prompt) {
  if (yes_)
    return true;

  std::cout << prompt << "? (y/N) " << std::flush;

  std::string buffer;
  if (std::getline(input, buffer)) {
    return (buffer == "y" || buffer == "y\n");
  }
  return false;
}

// We have a custom DeletePath helper because we don't want to descend across
// mount points, and no base:: helper supports that.
bool DevInstall::DeletePath(const struct stat& base_stat,
                            const base::FilePath& dir) {
  base::FileEnumerator iter(dir, true,
                            base::FileEnumerator::FILES |
                                base::FileEnumerator::DIRECTORIES |
                                base::FileEnumerator::SHOW_SYM_LINKS);
  for (base::FilePath current = iter.Next(); !current.empty();
       current = iter.Next()) {
    const auto& info(iter.GetInfo());
    if (info.IsDirectory()) {
      // Abort if the dir is mounted.
      if (base_stat.st_dev != info.stat().st_dev) {
        LOG(ERROR) << "directory is mounted: " << current.value();
        return false;
      }

      // Clear the contents of this directory.
      if (!DeletePath(base_stat, current))
        return false;

      // Clear this directory itself.
      if (rmdir(current.value().c_str())) {
        PLOG(ERROR) << "deleting failed: " << current.value();
        return false;
      }
    } else {
      if (unlink(current.value().c_str())) {
        PLOG(ERROR) << "deleting failed: " << current.value();
        return false;
      }
    }
  }

  return true;
}

bool DevInstall::CreateMissingDirectory(const base::FilePath& dir) {
  if (!base::PathExists(dir)) {
    if (!base::CreateDirectory(dir) ||
        !base::SetPosixFilePermissions(dir, 0755)) {
      PLOG(ERROR) << "Creating " << dir.value() << " failed";
      return false;
    }
  }

  return true;
}

bool DevInstall::WriteFile(const base::FilePath& file,
                           const std::string& data) {
  if (base::WriteFile(file, data.c_str(), data.size()) != data.size()) {
    PLOG(ERROR) << "Could not write " << file.value();
    return false;
  }

  return true;
}

bool DevInstall::ClearStateDir(const base::FilePath& dir) {
  LOG(INFO) << "To clean up, we will run:\n  rm -rf /usr/local/\n"
            << "Any content you have stored in there will be deleted.";
  if (!PromptUser(std::cin, "Remove all installed packages now")) {
    LOG(INFO) << "Operation cancelled.";
    return false;
  }

  // Normally we'd use base::DeleteFile, but we don't want to traverse mounts.
  struct stat base_stat;
  if (stat(dir.value().c_str(), &base_stat)) {
    if (errno == ENOENT)
      return true;

    PLOG(ERROR) << "Could not access " << dir.value();
    return false;
  }

  bool success = DeletePath(base_stat, dir);
  if (success)
    LOG(INFO) << "Removed all installed packages.";
  else
    LOG(ERROR) << "Deleting " << dir.value() << " failed";
  return success;
}

bool DevInstall::InitializeStateDir(const base::FilePath& dir) {
  // Create this loop so uncompressed files in /usr/local/usr/ will be reachable
  // through /usr/local/.
  // Note: /usr/local is mount-binded onto the /mnt/stateful_partition/dev_mode
  // during chromeos_startup during boot for machines in dev_mode.
  const base::FilePath usr = dir.Append("usr");
  if (!base::PathExists(usr)) {
    // Create /usr/local/usr -> . symlink.
    if (!base::CreateSymbolicLink(base::FilePath("."), usr)) {
      PLOG(ERROR) << "Creating " << usr.value() << " failed";
      return false;
    }
  }

  // Setup a /tmp space for random scripts to rely on.
  const base::FilePath tmp = dir.Append("tmp");
  if (!base::PathExists(tmp)) {
    // Can't use base::SetPosixFilePermissions as that blocks +t mode.
    if (!base::CreateDirectory(tmp) || chmod(tmp.value().c_str(), 01777)) {
      PLOG(ERROR) << "Creating " << tmp.value() << " failed";
      return false;
    }
  }

  const base::FilePath local = usr.Append("local");
  if (!base::PathExists(local)) {
    // Create /usr/local/usr/local -> . symlink.
    if (!base::CreateSymbolicLink(base::FilePath("."), local)) {
      PLOG(ERROR) << "Creating " << local.value() << " failed";
      return false;
    }
  }

  // Set up symlinks for etc/{group,passwd}, so that packages can look up users
  // and groups correctly.
  const base::FilePath etc = usr.Append("etc");
  if (!CreateMissingDirectory(etc))
    return false;

  // Create /usr/local/etc/group -> /etc/group symlink.
  const base::FilePath group = etc.Append("group");
  if (!base::PathExists(group)) {
    if (!base::CreateSymbolicLink(base::FilePath("/etc/group"), group)) {
      PLOG(ERROR) << "Creating " << group.value() << " failed";
      return false;
    }
  }

  // Create /usr/local/etc/passwd -> /etc/passwd symlink.
  const base::FilePath passwd = etc.Append("passwd");
  if (!base::PathExists(passwd)) {
    if (!base::CreateSymbolicLink(base::FilePath("/etc/passwd"), passwd)) {
      PLOG(ERROR) << "Creating " << passwd.value() << " failed";
      return false;
    }
  }

  return true;
}

bool DevInstall::LoadRuntimeSettings(const base::FilePath& lsb_release) {
  brillo::KeyValueStore store;
  if (!store.Load(lsb_release)) {
    PLOG(WARNING) << "Could not read " << kLsbReleasePath;
    return true;
  }

  if (!store.GetString(kLsbChromeOsDevserver, &devserver_url_))
    devserver_url_.clear();

  if (store.GetString(kLsbChromeOsReleaseBoard, &board_)) {
    size_t pos = board_.find("-signed-");
    if (pos != std::string::npos)
      board_.erase(pos);
  } else {
    board_.clear();
  }

  // If --binhost_version wasn't specified, calculate it.
  if (binhost_version_.empty()) {
    store.GetString(kLsbChromeOsReleaseVersion, &binhost_version_);
  }

  return true;
}

void DevInstall::InitializeBinhost() {
  if (!binhost_.empty())
    return;

  if (!devserver_url_.empty()) {
    LOG(INFO) << "Devserver URL set to: " << devserver_url_;
    if (PromptUser(std::cin, "Use it as the binhost")) {
      binhost_ = devserver_url_ + "/static/pkgroot/" + board_ + "/packages";
      return;
    }
  }

  binhost_ = std::string(kDefaultBinhostPrefix) + "/" + board_ + "/" +
             binhost_version_ + "/packages";
}

std::string DevInstall::DetectCompression(const base::FilePath& pkg) {
  char bytes[4];
  if (ReadFile(pkg, bytes, sizeof(bytes)) == -1) {
    PLOG(WARNING) << "Unable to detect compression; assuming zstd";
    return kZstdCmd;
  }

  if (memcmp(bytes, kZstdMagic, sizeof(kZstdMagic)) == 0) {
    return kZstdCmd;
  } else if (memcmp(bytes, kBzip2Magic, sizeof(kBzip2Magic)) == 0) {
    return kBzip2Cmd;
  } else {
    LOG(WARNING) << "Unknown magic signature; assuming zstd";
    return kZstdCmd;
  }
}

bool DevInstall::DownloadAndInstallBootstrapPackage(
    const std::string& package) {
  const std::string url(binhost_ + "/" + package + ".tbz2");
  const base::FilePath binpkg_dir = state_dir_.Append(kBinpkgSubdir);
  const base::FilePath pkg = binpkg_dir.Append(package + ".tbz2");
  const base::FilePath pkgdir = pkg.DirName();

  if (!CreateMissingDirectory(pkgdir))
    return false;

  LOG(INFO) << "Downloading " << url;
  brillo::ProcessImpl curl;
  curl.SetSearchPath(true);
  curl.AddArg("curl");
  curl.AddArg("--fail");
  curl.AddStringOption("-o", pkg.value());
  curl.AddArg(url);
  if (curl.Run() != 0) {
    LOG(ERROR) << "Could not download package";
    return false;
  }

  LOG(INFO) << "Unpacking " << pkg.value();
  brillo::ProcessImpl tar;
  tar.SetSearchPath(true);
  tar.AddArg("tar");
  tar.AddStringOption("-C", state_dir_.value());
  tar.AddStringOption("-I", DetectCompression(pkg));
  tar.AddArg("-xkf");
  tar.AddArg(pkg.value());
  if (tar.Run() != 0) {
    LOG(ERROR) << "Could not extract package";
    return false;
  }

  return true;
}

bool DevInstall::DownloadAndInstallBootstrapPackages(
    const base::FilePath& listing) {
  std::string data;
  if (!base::ReadFileToString(listing, &data)) {
    PLOG(ERROR) << "Unable to read " << listing.value();
    return false;
  }

  std::vector<std::string> lines = base::SplitString(
      data, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  if (lines.empty()) {
    LOG(ERROR) << "Bootstrap package set is empty!";
    return false;
  }
  for (const std::string& line : lines) {
    if (!DownloadAndInstallBootstrapPackage(line))
      return false;
  }

  // The python ebuilds set up symlinks in pkg_postinst, but we don't run those
  // phases (we just run untar above).  Plus that logic depends on eselect that
  // we currently stub out.  Hand create the symlinks https://crbug.com/955147.
  const base::FilePath python = state_dir_.Append("usr/bin/python");
  if (!base::PathExists(python)) {
    if (!base::CreateSymbolicLink(base::FilePath("python-wrapper"), python)) {
      PLOG(ERROR) << "Creating " << python.value() << " failed";
      return false;
    }
  }
  const base::FilePath python2 = state_dir_.Append("usr/bin/python2");
  if (!base::PathExists(python2)) {
    if (!base::CreateSymbolicLink(base::FilePath("python2.7"), python2)) {
      PLOG(ERROR) << "Creating " << python2.value() << " failed";
      return false;
    }
  }
  const base::FilePath python3 = state_dir_.Append("usr/bin/python3");
  if (!base::PathExists(python3)) {
    if (!base::CreateSymbolicLink(base::FilePath("python3.6"), python3)) {
      PLOG(ERROR) << "Creating " << python3.value() << " failed";
      return false;
    }
  }

  return true;
}

bool DevInstall::ConfigurePortage() {
  const base::FilePath portage_dir = state_dir_.Append(kPortageConfigSubdir);
  const base::FilePath profile_dir = portage_dir.Append("make.profile");

  // Copy emerge configuration to /usr/local.
  if (!CreateMissingDirectory(profile_dir))
    return false;

  // Point our local profile to the rootfs one.  This allows us to stack.
  const base::FilePath parent_path = profile_dir.Append("parent");
  const std::string parent_data{"/etc/portage/make.profile\n"};
  if (!WriteFile(parent_path, parent_data))
    return false;

  // Install the package.provided entries for the rootfs.
  const base::FilePath provided_path = profile_dir.Append("package.provided");
  if (!CreateMissingDirectory(provided_path))
    return false;
  const base::FilePath rootfs_provided{kRootfsProvidedDir};
  base::FileEnumerator profile_iter(rootfs_provided, false,
                                    base::FileEnumerator::FILES);
  for (base::FilePath current = profile_iter.Next(); !current.empty();
       current = profile_iter.Next()) {
    const base::FilePath sym = provided_path.Append(current.BaseName());
    if (!base::CreateSymbolicLink(current, sym)) {
      PLOG(ERROR) << "Creating " << sym.value() << " failed";
      return false;
    }
  }

  // Create the directories defined in the portage config files. Permissions are
  // consistent with the other directories in /usr/local, which is a bind mount
  // for /mnt/stateful_partition/dev_image.
  //
  // We set ROOT in make.conf as portage ignores it in profile make.defaults.
  const base::FilePath make_conf_path = portage_dir.Append("make.conf");
  const std::string make_conf_data{"ROOT=\"" + state_dir_.value() +
                                   "\"\n"
                                   "PORTAGE_BINHOST=\"" +
                                   binhost_ + "\"\n"};
  if (!WriteFile(make_conf_path, make_conf_data))
    return false;

  // Hack in LD_LIBRARY_PATH within portage env.  Otherwise builds will filter
  // it out which breaks python as it can't find its libs in /usr/local.  This
  // only shows up on base images as those won't have ldconfig run since the
  // rootfs is read-only.  See https://crbug.com/1065727 for examples.
  //
  // The path we search for will be:
  // /usr/local/ (state_dir_)
  //   lib*/python*/site-packages/portage/ (internal python packages dir)
  //     package/ebuild/_config/special_env_vars.py
  //
  // We do this manually because base::FileEnumerator is unable to handle
  // symlink loops which we have in /usr/local by design.
  bool found_file = false;
  base::FileEnumerator lib_iter(state_dir_, false,
                                base::FileEnumerator::DIRECTORIES, "lib*");
  for (auto lib_current = lib_iter.Next(); !lib_current.empty();
       lib_current = lib_iter.Next()) {
    base::FileEnumerator python_iter(
        lib_current, false, base::FileEnumerator::DIRECTORIES, "python3.*");
    for (auto python_current = python_iter.Next(); !python_current.empty();
         python_current = python_iter.Next()) {
      const auto current = python_current.Append(
          "site-packages/portage/package/ebuild/_config/special_env_vars.py");
      if (!base::PathExists(current)) {
        LOG(WARNING) << "Portage file does not exist: " << current.value();
        continue;
      }

      found_file = true;
      LOG(INFO) << "Hacking portage file for dev-install " << current.value();

      // Load the file into memory.
      std::string data;
      if (!base::ReadFileToString(current, &data)) {
        PLOG(ERROR) << "Unable to read " << current.value();
        return false;
      }

      // Split it into lines.
      auto lines = base::SplitStringPiece(data, "\n", base::KEEP_WHITESPACE,
                                          base::SPLIT_WANT_ALL);
      if (lines.empty()) {
        LOG(ERROR) << "Portage internal file is empty: " << current.value();
        return false;
      }

      // Replace the one line that we need.
      const char kSearch[] = "environ_whitelist = []";
      const char kReplace[] = "environ_whitelist = ['LD_LIBRARY_PATH']";
      bool found_line = false;
      for (auto& line : lines) {
        if (line == kSearch) {
          found_line = true;
          line = kReplace;
        }
      }
      if (!found_line) {
        LOG(WARNING) << current.value() << ": Unable to find line to modify!";
      }

      // Write it back out.
      data = base::JoinString(lines, "\n");
      if (!base::WriteFile(current, data.data(), data.size())) {
        LOG(ERROR) << "Unable to write " << current.value();
        return false;
      }
    }
  }
  if (!found_file) {
    LOG(WARNING) << "Unable to locate internal portage special_env_vars.py!";
    LOG(WARNING) << "`emerge` might not work on your device; trying anyways.";
  }

  return true;
}

bool DevInstall::InstallExtraPackages() {
  if (!PromptUser(std::cin, "Install virtual/target-os-dev package now")) {
    LOG(INFO) << "You can install virtual/target-os-dev later by running:\n"
              << "emerge virtual/target-os-dev";
    return true;
  }

  brillo::ProcessImpl emerge;
  emerge.SetSearchPath(true);
  emerge.AddArg("emerge");
  int jobs = jobs_;
  if (jobs == 0)
    jobs = std::max(1L, sysconf(_SC_NPROCESSORS_ONLN) - 1);
  emerge.AddArg("--jobs=" + std::to_string(jobs));
  emerge.AddArg("virtual/target-os-dev");
  if (emerge.Run() != 0) {
    LOG(ERROR) << "Could not install virtual/target-os-dev";
    return false;
  }

  return true;
}

int DevInstall::Run() {
  // Only run if dev mode is enabled.
  if (!IsDevMode()) {
    LOG(ERROR) << "ChromeOS is not in developer mode";
    return 2;
  }

  // Handle reinstall & uninstall operations.
  if (reinstall_ || uninstall_) {
    if (!ClearStateDir(state_dir_))
      return 1;
    if (uninstall_)
      return 0;

    LOG(INFO) << "Reinstalling dev state";
  }

  // See if the system has been initialized already.
  const base::FilePath portage_dir = state_dir_.Append(kPortageConfigSubdir);
  if (base::DirectoryExists(portage_dir)) {
    LOG(ERROR) << "Directory " << portage_dir.value() << " exists.";
    LOG(ERROR) << "Did you mean dev_install --reinstall?";
    return 4;
  }

  // Initialize the base set of paths before we install any packages.
  if (!InitializeStateDir(state_dir_))
    return 5;

  // Load the settings from the active device.
  if (!LoadRuntimeSettings(base::FilePath(kLsbReleasePath)))
    return 6;

  // Parses flags to return the binhost or if none set, use the default binhost
  // set up from installation.
  InitializeBinhost();
  LOG(INFO) << "Using binhost: " << binhost_;

  // Bootstrap the setup.
  LOG(INFO) << "Starting installation of developer packages.";
  LOG(INFO) << "First, we download the necessary files.";
  if (!DownloadAndInstallBootstrapPackages(base::FilePath(kBootstrapListing)))
    return 7;

  if (only_bootstrap_) {
    LOG(INFO) << "Done installing bootstrap packages. Enjoy!";
    return 0;
  }

  LOG(INFO) << "Developer packages initialized; configuring portage.";
  if (!ConfigurePortage())
    return 8;

  LOG(INFO) << "Installing additional optional packages.";
  if (!InstallExtraPackages())
    return 9;

  LOG(INFO) << "Done! Enjoy! Or not, you choose!";
  return 0;
}

}  // namespace dev_install
