// 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 "dlcservice/dlc_manager.h"

#include <cinttypes>
#include <utility>
#include <vector>

#include <base/strings/stringprintf.h>
#include <base/strings/string_util.h>
#include <brillo/message_loops/message_loop.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/dlcservice/dbus-constants.h>

#include "dlcservice/error.h"
#include "dlcservice/system_state.h"
#include "dlcservice/utils.h"

using base::Callback;
using base::FilePath;
using brillo::ErrorPtr;
using std::string;
using std::vector;

namespace dlcservice {

namespace {
// Timeout in ms for DBus method calls into imageloader.
constexpr int kImageLoaderTimeoutMs = 5000;
}  // namespace

DlcManager::DlcManager() {
  const auto system_state = SystemState::Get();
  image_loader_proxy_ = system_state->image_loader();
  manifest_dir_ = system_state->manifest_dir();
  preloaded_content_dir_ = system_state->preloaded_content_dir();
  content_dir_ = system_state->content_dir();

  string boot_disk_name;
  if (!system_state->boot_slot().GetCurrentSlot(&boot_disk_name,
                                                &current_boot_slot_))
    LOG(FATAL) << "Can not get current boot slot.";

  // Initialize supported DLC(s).
  for (const auto& id : ScanDirectory(manifest_dir_))
    supported_[id];
}

DlcManager::~DlcManager() = default;

bool DlcManager::IsSupported(const DlcId& id) {
  return supported_.find(id) != supported_.end();
}

bool DlcManager::IsInstalling() {
  for (const auto& pr : supported_)
    if (pr.second.state.state() == DlcState::INSTALLING)
      return true;
  return false;
}

DlcInfo DlcManager::GetInfo(const DlcId& id) {
  DCHECK(IsSupported(id));
  return supported_[id];
}

// Loads the preloadable DLC(s) from |preloaded_content_dir_| by scanning the
// preloaded DLC(s) and verifying the validity to be preloaded before doing
// so.
void DlcManager::PreloadDlcModuleImages() {
  // Load all preloaded DLC(s) into |content_dir_| one by one.
  for (const auto& id : ScanDirectory(preloaded_content_dir_)) {
    if (!IsSupported(id)) {
      LOG(ERROR) << "Preloading is not allowed for unsupported DLC=" << id;
      continue;
    }
    if (!IsDlcPreloadAllowed(manifest_dir_, id)) {
      LOG(ERROR) << "Preloading is not allowed for DLC=" << id;
      continue;
    }

    ErrorPtr tmp_err;
    // Deleting DLC(s) that might already be installed as preloading DLC(s)
    // take precedence in order to allow stale DLC(s) in cache to be cleared.
    // Loading should be run prior to preloading, to enforce this strict
    // precedence.
    // TODO(crbug.com/1059445): Verify before deleting that image to preload
    // has the correct hash.
    if (!DeleteInternal(id, &tmp_err)) {
      PLOG(ERROR) << "Failed to delete prior to preloading DLC=" << id << ", "
                  << Error::ToString(tmp_err);
      continue;
    }

    DlcSet dlc_set = {id};
    if (!InitInstallInternal(dlc_set, &tmp_err)) {
      LOG(ERROR) << "Failed to create preloaded DLC=" << id << ", "
                 << Error::ToString(tmp_err);
      continue;
    }

    if (!PreloadedCopier(id)) {
      LOG(ERROR) << "Something went wrong during preloading DLC (" << id
                 << "), please check for previous errors.";
      if (!CancelInstall(&tmp_err))
        LOG(WARNING) << Error::ToString(tmp_err);
      continue;
    }

    // When the copying is successful, go ahead and finish installation.
    if (!FinishInstall(&tmp_err)) {
      LOG(ERROR) << "Failed to finish installation for preloaded DLC=" << id
                 << ", " << Error::ToString(tmp_err);
      continue;
    }

    // Delete the preloaded DLC only after both copies into A and B succeed as
    // well as mounting.
    auto image_preloaded_path = JoinPaths(preloaded_content_dir_, id,
                                          GetDlcPackage(id), kDlcImageFileName);
    if (!base::DeleteFile(image_preloaded_path.DirName().DirName(), true)) {
      LOG(ERROR) << "Failed to delete image after preloading DLC=" << id;
      continue;
    }
  }
}

bool DlcManager::InitInstallInternal(const DlcSet& requested_install,
                                     ErrorPtr* err) {
  DCHECK(!IsInstalling());

  ErrorPtr tmp_err;
  for (const auto& id : requested_install) {
    if (!IsSupported(id)) {
      *err = Error::Create(
          kErrorInvalidDlc,
          base::StringPrintf("Trying to install unsupported DLC=%s",
                             id.c_str()));
      if (!CancelInstall(&tmp_err))
        LOG(ERROR) << "Failed during install initialization: "
                   << Error::ToString(tmp_err);
      return false;
    }
    switch (GetInfo(id).state.state()) {
      case DlcState::NOT_INSTALLED:
        if (IsActiveImagePresent(id)) {
          if (ValidateInactiveImage(id) && TryMount(id))
            break;
          if (!DeleteInternal(id, err)) {
            if (!CancelInstall(&tmp_err))
              LOG(ERROR) << "Failed during install initialization: "
                         << Error::ToString(tmp_err);
            return false;
          }
        }
        if (!Create(id, err)) {
          if (!CancelInstall(&tmp_err))
            LOG(ERROR) << "Failed during install initialization: "
                       << Error::ToString(tmp_err);
          return false;
        }
        break;
      case DlcState::INSTALLED:
        if (!ValidateInactiveImage(id))
          LOG(ERROR) << "Bad inactive image for DLC=" << id;
        if (!TryMount(id))
          LOG(ERROR) << "Failed to mount installed DLC=" << id;
        break;
      case DlcState::INSTALLING:
      default:
        NOTREACHED();
        return false;
    }
    // Failure to set the metadata flags should not fail the install.
    if (!SystemState::Get()->update_engine()->SetDlcActiveValue(true, id,
                                                                &tmp_err)) {
      LOG(WARNING) << "Update Engine failed to set DLC to active:" << id
                   << (tmp_err ? Error::ToString(tmp_err)
                               : "Missing error from update engine proxy.");
    }
  }
  return true;
}

bool DlcManager::FinishInstall(ErrorPtr* err) {
  bool ret = true;
  for (const auto& pr : supported_) {
    const auto& id = pr.first;
    const auto& info = pr.second;
    if (info.state.state() != DlcState::INSTALLING)
      continue;
    string mount_point;
    ErrorPtr tmp_err;
    if (!Mount(id, &mount_point, &tmp_err)) {
      LOG(ERROR) << "Failed during install finalization: "
                 << Error::ToString(tmp_err);
      if (!DeleteInternal(id, &tmp_err))
        LOG(ERROR) << "Failed during install finalization: "
                   << Error::ToString(tmp_err);
      ret = false;
      continue;
    }
    SetInstalled(id, GetDlcRoot(FilePath(mount_point)).value());
  }
  if (!ret)
    *err =
        Error::Create(kErrorInternal, "Not all DLC(s) successfully mounted.");
  return ret;
}

bool DlcManager::CancelInstall(ErrorPtr* err) {
  bool ret = true;
  if (!IsInstalling()) {
    LOG(WARNING) << "No install started to being with, nothing to cancel.";
    return ret;
  }
  for (const auto& pr : supported_) {
    const auto& id = pr.first;
    const auto& info = pr.second;
    if (info.state.state() != DlcState::INSTALLING)
      continue;
    // Consider as not installed even if delete fails below, correct errors
    // will be propagated later and should not block on further installs.
    SetNotInstalled(id);
    ErrorPtr tmp_err;
    if (!DeleteInternal(id, &tmp_err)) {
      PLOG(ERROR) << "Failed during install cancellation: "
                  << Error::ToString(tmp_err);
      ret = false;
    }
  }
  if (!ret)
    *err = Error::Create(kErrorInternal,
                         "Not all installing DLC(s) successfully cancelled.");
  return ret;
}

// Deletes all directories related to the given DLC |id|.
bool DlcManager::DeleteInternal(const string& id, ErrorPtr* err) {
  vector<string> undeleted_paths;
  for (const auto& path : {JoinPaths(content_dir_, id)}) {
    if (!base::DeleteFile(path, true)) {
      PLOG(ERROR) << "Failed to delete path=" << path;
      undeleted_paths.push_back(path.value());
    }
    // Failure to set DLC to inactive should not fail uninstall.
    ErrorPtr tmp_err;
    if (!SystemState::Get()->update_engine()->SetDlcActiveValue(false, id,
                                                                &tmp_err))
      LOG(WARNING) << "Failed to set DLC(" << id << ") to inactive."
                   << (tmp_err ? Error::ToString(tmp_err)
                               : "Missing error from update engine proxy.");
  }
  bool ret = undeleted_paths.empty();
  if (!ret) {
    *err = Error::Create(
        kErrorInternal,
        base::StringPrintf("DLC directories (%s) could not be deleted.",
                           base::JoinString(undeleted_paths, ",").c_str()));
  }
  SetNotInstalled(id);
  return ret;
}

bool DlcManager::Mount(const string& id, string* mount_point, ErrorPtr* err) {
  if (!image_loader_proxy_->LoadDlcImage(
          id, GetDlcPackage(id),
          current_boot_slot_ == BootSlot::Slot::A ? imageloader::kSlotNameA
                                                  : imageloader::kSlotNameB,
          mount_point, nullptr, kImageLoaderTimeoutMs)) {
    *err = Error::Create(kErrorInternal,
                         "Imageloader is unavailable for LoadDlcImage().");
    return false;
  }
  if (mount_point->empty()) {
    *err = Error::Create(kErrorInternal,
                         "Imageloader LoadDlcImage() call failed.");
    return false;
  }
  return true;
}

bool DlcManager::Unmount(const string& id, ErrorPtr* err) {
  bool success = false;
  if (!image_loader_proxy_->UnloadDlcImage(id, GetDlcPackage(id), &success,
                                           nullptr, kImageLoaderTimeoutMs)) {
    *err = Error::Create(kErrorInternal,
                         "Imageloader is unavailable for UnloadDlcImage().");
    return false;
  }
  if (!success) {
    *err = Error::Create(kErrorInternal,
                         "Imageloader UnloadDlcImage() call failed.");
    return false;
  }
  return true;
}

string DlcManager::GetDlcPackage(const DlcId& id) {
  return *(ScanDirectory(JoinPaths(manifest_dir_, id)).begin());
}

void DlcManager::SetNotInstalled(const DlcId& id) {
  DCHECK(IsSupported(id));
  supported_[id] = DlcInfo(DlcState::NOT_INSTALLED);
}

void DlcManager::SetInstalling(const DlcId& id) {
  DCHECK(IsSupported(id));
  supported_[id] = DlcInfo(DlcState::INSTALLING);
}

void DlcManager::SetInstalled(const DlcId& id, const DlcRoot& root) {
  DCHECK(IsSupported(id));
  supported_[id] = DlcInfo(DlcState::INSTALLED, root);
}

// Returns true if the DLC module has a boolean true for 'preload-allowed'
// attribute in the manifest for the given |id| and |package|.
bool DlcManager::IsDlcPreloadAllowed(const base::FilePath& dlc_manifest_path,
                                     const std::string& id) {
  imageloader::Manifest manifest;
  if (!GetDlcManifest(dlc_manifest_path, id, GetDlcPackage(id), &manifest)) {
    // Failing to read the manifest will be considered a preloading blocker.
    return false;
  }
  return manifest.preload_allowed();
}

// Create the DLC |id| and |package| directories if they don't exist.
bool DlcManager::CreateDlcPackagePath(const string& id,
                                      const string& package,
                                      ErrorPtr* err) {
  FilePath content_path_local = JoinPaths(content_dir_, id);
  FilePath content_package_path = JoinPaths(content_dir_, id, package);

  // Create the DLC ID directory with correct permissions.
  if (!CreateDir(content_path_local)) {
    *err =
        Error::Create(kErrorInternal,
                      base::StringPrintf(
                          "Failed to create directory for DLC=%s", id.c_str()));
    return false;
  }
  // Create the DLC package directory with correct permissions.
  if (!CreateDir(content_package_path)) {
    *err = Error::Create(
        kErrorInternal,
        base::StringPrintf("Failed to create package directory for DLC=%s",
                           id.c_str()));
    return false;
  }
  return true;
}

bool DlcManager::Create(const string& id, ErrorPtr* err) {
  // Create content directories.
  const auto& package = GetDlcPackage(id);
  const auto& content_id_path = JoinPaths(content_dir_, id);
  for (const auto& path :
       {content_id_path, JoinPaths(content_id_path, package)}) {
    if (!CreateDir(path)) {
      *err = Error::Create(
          kErrorInternal,
          base::StringPrintf("Failed to create directory %s for DLC=%s",
                             path.value().c_str(), id.c_str()));
      return false;
    }
  }

  imageloader::Manifest manifest;
  if (!dlcservice::GetDlcManifest(manifest_dir_, id, package, &manifest)) {
    *err = Error::Create(
        kErrorInternal,
        base::StringPrintf("Cannot read the manifest for DLC=%s", id.c_str()));
    return false;
  }

  const int64_t image_size = manifest.preallocated_size();
  if (image_size <= 0) {
    *err = Error::Create(
        kErrorInternal, base::StringPrintf("Preallocated size=%" PRId64
                                           " in manifest is illegal for DLC=%s",
                                           image_size, id.c_str()));
    return false;
  }

  // Creates image A.
  FilePath image_a_path =
      GetDlcImagePath(content_dir_, id, package, BootSlot::Slot::A);
  if (!CreateFile(image_a_path, image_size)) {
    *err = Error::Create(
        kErrorAllocation,
        base::StringPrintf("Failed to create slot A image file for DLC=%s",
                           id.c_str()));
    return false;
  }

  // Creates image B.
  FilePath image_b_path =
      GetDlcImagePath(content_dir_, id, package, BootSlot::Slot::B);
  if (!CreateFile(image_b_path, image_size)) {
    *err = Error::Create(
        kErrorAllocation,
        base::StringPrintf("Failed to create slot B image file for DLC=%s",
                           id.c_str()));
    return false;
  }

  SetInstalling(id);
  return true;
}

// Validate that:
//  - If inactive image for DLC is missing, try creating it.
//  - If inactive image size is less than size in manifest, increase it.
bool DlcManager::ValidateInactiveImage(const string& id) {
  string mount_point;
  const auto& package = GetDlcPackage(id);
  FilePath inactive_image_path = GetDlcImagePath(
      content_dir_, id, package,
      current_boot_slot_ == BootSlot::Slot::A ? BootSlot::Slot::B
                                              : BootSlot::Slot::A);

  imageloader::Manifest manifest;
  if (!GetDlcManifest(manifest_dir_, id, package, &manifest)) {
    LOG(ERROR) << "Failed to get manifest for DLC=" << id;
    return false;
  }
  int64_t max_image_size = manifest.preallocated_size();

  if (!base::PathExists(inactive_image_path)) {
    LOG(WARNING) << "The DLC image " << inactive_image_path.value()
                 << " does not exist.";
    if (!CreateFile(inactive_image_path, max_image_size)) {
      LOG(ERROR) << "Failed to create inactive image "
                 << inactive_image_path.value()
                 << " during validation for DLC=" << id;
      return false;
    }
  }

  // Different scenarios possible to hit this flow:
  //  - Inactive and manifest size are the same -> Do nothing.
  //
  // TODO(crbug.com/943780): This requires further design updates to both
  //  dlcservice and upate_engine in order to fully handle. Solution pending.
  //  - Update applied and not rebooted -> Do nothing. A lot more corner cases
  //    than just always keeping active and inactive image sizes the same.
  //
  //  - Update applied and rebooted -> Try fixing up inactive image.
  int64_t inactive_image_size;
  if (!base::GetFileSize(inactive_image_path, &inactive_image_size)) {
    LOG(ERROR) << "Failed to get inactive image size DLC=" << id;
  } else {
    // When |inactive_image_size| is less than the size permitted in the
    // manifest, this means that we rebooted into an update.
    if (inactive_image_size < max_image_size) {
      // Only increasing size, the inactive DLC is still usable in case of
      // reverts.
      if (!ResizeFile(inactive_image_path, max_image_size)) {
        LOG(ERROR) << "Failed to increase inactive image, update_engine may "
                      "face problems in updating when stateful is full later.";
        return false;
      }
    }
  }
  return true;
}

// Helper used to load in (copy + cleanup) preloadable files for the |id|.
bool DlcManager::PreloadedCopier(const string& id) {
  const auto& package = GetDlcPackage(id);
  FilePath image_preloaded_path =
      JoinPaths(preloaded_content_dir_, id, package, kDlcImageFileName);
  FilePath image_a_path =
      GetDlcImagePath(content_dir_, id, package, BootSlot::Slot::A);
  FilePath image_b_path =
      GetDlcImagePath(content_dir_, id, package, BootSlot::Slot::B);

  // Check the size of file to copy is valid.
  imageloader::Manifest manifest;
  if (!dlcservice::GetDlcManifest(manifest_dir_, id, package, &manifest)) {
    LOG(ERROR) << "Failed to get manifest for DLC=" << id;
    return false;
  }
  int64_t max_image_size = manifest.preallocated_size();
  // Scope the |image_preloaded| file so it always closes before deleting.
  {
    int64_t image_preloaded_size;
    if (!base::GetFileSize(image_preloaded_path, &image_preloaded_size)) {
      LOG(ERROR) << "Failed to get preloaded DLC (" << id << ") size.";
      return false;
    }
    if (image_preloaded_size > max_image_size) {
      LOG(ERROR) << "Preloaded DLC (" << id << ") is (" << image_preloaded_size
                 << ") larger than the preallocated size (" << max_image_size
                 << ") in manifest.";
      return false;
    }
  }

  // Based on |current_boot_slot_|, copy the preloadable image.
  FilePath image_boot_path, image_non_boot_path;
  switch (current_boot_slot_) {
    case BootSlot::Slot::A:
      image_boot_path = image_a_path;
      image_non_boot_path = image_b_path;
      break;
    case BootSlot::Slot::B:
      image_boot_path = image_b_path;
      image_non_boot_path = image_a_path;
      break;
    default:
      NOTREACHED();
      return false;
  }
  // TODO(kimjae): when preloaded images are place into unencrypted, this
  // operation can be a move.
  if (!CopyAndResizeFile(image_preloaded_path, image_boot_path,
                         max_image_size)) {
    LOG(ERROR) << "Failed to preload DLC (" << id << ") into boot slot.";
    return false;
  }
  return true;
}

bool DlcManager::TryMount(const DlcId& id) {
  const auto info = GetInfo(id);
  if (base::PathExists(FilePath(info.root))) {
    LOG(INFO) << "Skipping mount as already mounted at " << info.root;
    return true;
  }

  string mount_point;
  ErrorPtr tmp_err;
  if (!Mount(id, &mount_point, &tmp_err)) {
    LOG(ERROR) << "DLC thought to have been installed, but maybe is in a "
               << "bad state. DLC=" << id << ", " << Error::ToString(tmp_err);
    return false;
  }
  SetInstalled(id, GetDlcRoot(FilePath(mount_point)).value());
  return true;
}

bool DlcManager::IsActiveImagePresent(const DlcId& id) {
  return base::PathExists(
      GetDlcImagePath(content_dir_, id, GetDlcPackage(id), current_boot_slot_));
}

DlcModuleList DlcManager::GetInstalled() {
  return ToDlcModuleList(supported_, [](const DlcId&, const DlcInfo& info) {
    return info.state.state() == DlcState::INSTALLED;
  });
}

DlcModuleList DlcManager::GetSupported() {
  return ToDlcModuleList(supported_, [](const DlcId&, const DlcInfo&) {
    return true;
  });
}

bool DlcManager::GetState(const DlcId& id, DlcState* state, ErrorPtr* err) {
  DCHECK(state);
  DCHECK(err);
  if (!IsSupported(id)) {
    *err = Error::Create(
        kErrorInvalidDlc,
        base::StringPrintf("Cannot get state for unsupported DLC=%s",
                           id.c_str()));
    return false;
  }

  *state = GetInfo(id).state;
  return true;
}

void DlcManager::LoadDlcModuleImages() {
  PreloadDlcModuleImages();
}

bool DlcManager::InitInstall(const DlcModuleList& dlc_module_list,
                             ErrorPtr* err) {
  DCHECK(err);
  const auto dlc_set =
      ToDlcSet(dlc_module_list, [](const DlcModuleInfo&) { return true; });

  if (dlc_set.empty()) {
    *err = Error::Create(kErrorInvalidDlc,
                         "Must provide at least one DLC to install.");
    return false;
  }

  return InitInstallInternal(dlc_set, err);
}

DlcModuleList DlcManager::GetMissingInstalls() {
  // Only return the DLC(s) that aren't already installed.
  return ToDlcModuleList(supported_, [](const DlcId&, const DlcInfo& info) {
    return info.state.state() == DlcState::INSTALLING;
  });
}

bool DlcManager::Delete(const string& id, ErrorPtr* err) {
  DCHECK(err);
  if (!IsSupported(id)) {
    *err = Error::Create(
        kErrorInvalidDlc,
        base::StringPrintf("Trying to delete unsupported DLC=%s", id.c_str()));
    return false;
  }
  switch (GetInfo(id).state.state()) {
    case DlcState::NOT_INSTALLED:
      LOG(WARNING) << "Trying to uninstall not installed DLC=" << id;
      return DeleteInternal(id, err);
    case DlcState::INSTALLING:
      *err = Error::Create(
          kErrorBusy,
          base::StringPrintf("Trying to delete a currently installing DLC=%s",
                             id.c_str()));
      return false;
    case DlcState::INSTALLED:
      return Unmount(id, err) && DeleteInternal(id, err);
    default:
      NOTREACHED();
      return false;
  }
}

}  // namespace dlcservice
