// Copyright 2016 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 "imageloader/imageloader_impl.h"

#include <linux/magic.h>
#include <sys/statvfs.h>
#include <sys/vfs.h>

#include <memory>
#include <string>

#include <base/containers/adapters.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/important_file_writer.h>
#include <base/json/json_string_value_serializer.h>
#include <base/logging.h>
#include <base/values.h>
#include <base/version.h>
#include <chromeos/dbus/service_constants.h>

#include "imageloader/component.h"
#include "imageloader/dlc.h"

namespace imageloader {

namespace {

using imageloader::kBadResult;

// The name of the file containing the latest component version.
constexpr char kLatestVersionFile[] = "latest-version";
// The maximum size of the latest-version file.
constexpr int kMaximumLatestVersionSize = 4096;
// Maximum ID length.
constexpr size_t kMaxIdLength = 40;

// |mount_base_path| is the subfolder where all components are mounted.
// For example "/mnt/imageloader."
base::FilePath GetMountPoint(const base::FilePath& mount_base_path,
                             const std::string& component_name,
                             const std::string& component_version) {
  return mount_base_path.Append(component_name).Append(component_version);
}

bool AssertComponentDirPerms(const base::FilePath& path) {
  int mode;
  if (!GetPosixFilePermissions(path, &mode))
    return false;
  return mode == kComponentDirPerms;
}

}  // namespace

// static
bool ImageLoaderImpl::IsIdValid(const std::string& id) {
  // |id| can not be empty or start with a non-alphanumerical character.
  if (id.empty() || id.length() > kMaxIdLength ||
      (!isalpha(id[0]) && !isdigit(id[0]))) {
    LOG(ERROR) << "Invalid ID: " << id;
    return false;
  }
  // id can only contain alphanumerical character plus '_' and '-'.
  for (const char& c : id) {
    if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') {
      LOG(ERROR) << "Invalid ID: " << id;
      return false;
    }
  }
  return true;
}

bool ImageLoaderImpl::LoadComponent(const std::string& name,
                                    const std::string& mount_point_str,
                                    HelperProcessProxy* proxy) {
  if (!IsIdValid(name)) {
    return false;
  }

  base::FilePath component_path;
  if (!GetPathToCurrentComponentVersion(name, &component_path)) {
    return false;
  }

  std::unique_ptr<Component> component =
      Component::Create(component_path, config_.keys);
  if (!component) {
    LOG(ERROR) << "Failed to initialize component: " << name;
    return false;
  }

  base::FilePath mount_point(mount_point_str);
  return component->Mount(proxy, mount_point);
}

std::string ImageLoaderImpl::LoadComponent(const std::string& name,
                                           HelperProcessProxy* proxy) {
  if (!IsIdValid(name)) {
    return kBadResult;
  }

  base::FilePath component_path;
  if (!GetPathToCurrentComponentVersion(name, &component_path)) {
    return kBadResult;
  }

  return LoadComponentAtPath(name, component_path, proxy);
}

std::string ImageLoaderImpl::LoadDlcImage(const std::string& id,
                                          const std::string& package,
                                          const std::string& a_or_b,
                                          HelperProcessProxy* proxy) {
  if (!IsIdValid(id) || !IsIdValid(package)) {
    return kBadResult;
  }

  Dlc dlc(id, package, config_.mount_path);
  return dlc.Mount(proxy, a_or_b) ? dlc.GetMountPoint().value() : kBadResult;
}

std::string ImageLoaderImpl::LoadComponentAtPath(
    const std::string& name,
    const base::FilePath& component_path,
    HelperProcessProxy* proxy) {
  if (!IsIdValid(name)) {
    return kBadResult;
  }

  std::unique_ptr<Component> component =
      Component::Create(component_path, config_.keys);
  if (!component) {
    LOG(ERROR) << "Failed to initialize component: " << name;
    return kBadResult;
  }

  base::FilePath mount_point(
      GetMountPoint(config_.mount_path, name, component->manifest().version()));
  return component->Mount(proxy, mount_point) ? mount_point.value()
                                              : kBadResult;
}

bool ImageLoaderImpl::RemoveComponent(const std::string& name) {
  if (!IsIdValid(name)) {
    return false;
  }

  base::FilePath component_root(GetComponentRoot(name));
  base::FilePath component_path;
  if (!GetPathToCurrentComponentVersion(name, &component_path)) {
    LOG(ERROR) << "Failed to get current component version: " << name;
    return false;
  }
  return RemoveComponentAtPath(name, component_root, component_path);
}

bool ImageLoaderImpl::CleanupAll(bool dry_run,
                                 const base::FilePath& parent_dir,
                                 std::vector<std::string>* paths,
                                 HelperProcessProxy* proxy) {
  return proxy->SendUnmountAllCommand(dry_run, parent_dir.value(), paths);
}

bool ImageLoaderImpl::Cleanup(const base::FilePath& path,
                              HelperProcessProxy* proxy) {
  return proxy->SendUnmountCommand(path.value());
}

bool ImageLoaderImpl::UnloadDlcImage(const std::string& id,
                                     const std::string& package,
                                     HelperProcessProxy* proxy) {
  if (!IsIdValid(id)) {
    return false;
  }

  return proxy->SendUnmountCommand(
      Dlc::GetMountPoint(config_.mount_path, id, package).value());
}

bool ImageLoaderImpl::RemoveComponentAtPath(
    const std::string& name,
    const base::FilePath& component_root,
    const base::FilePath& component_path) {
  if (!IsIdValid(name)) {
    return false;
  }

  // Check if component is removable.
  std::unique_ptr<Component> component =
      Component::Create(component_path, config_.keys);
  if (!component) {
    LOG(ERROR) << "Failed to initialize component: " << name;
    return false;
  }
  if (!component->manifest().is_removable()) {
    LOG(ERROR) << "Component is not removable";
    return false;
  }

  // Remove the component (all versions) and latest-version file.
  if (!base::DeletePathRecursively(component_root)) {
    LOG(ERROR) << "Failed to delete component.";
    return false;
  }
  return true;
}

bool ImageLoaderImpl::RegisterComponent(
    const std::string& name,
    const std::string& version,
    const std::string& component_folder_abs_path) {
  if (!IsIdValid(name)) {
    return false;
  }

  base::FilePath components_dir(config_.storage_dir);

  // If the directory is writable by others, do not trust the components.
  if (!AssertComponentDirPerms(components_dir))
    return false;

  std::string old_version_hint;
  base::FilePath version_hint_path(GetLatestVersionFilePath(name));
  bool have_old_version = base::PathExists(version_hint_path);
  if (have_old_version) {
    if (!base::ReadFileToStringWithMaxSize(version_hint_path, &old_version_hint,
                                           kMaximumLatestVersionSize)) {
      return false;
    }

    // Check for version rollback.
    base::Version current_version(old_version_hint);
    base::Version new_version(version);
    if (!new_version.IsValid()) {
      return false;
    }

    if (current_version.IsValid() && new_version <= current_version) {
      LOG(ERROR) << "Version [" << new_version << "] is not newer than ["
                 << current_version << "] for component [" << name
                 << "] and cannot be registered.";
      return false;
    }
  }

  // Check if this specific component already exists in the filesystem.
  base::FilePath component_root(GetComponentRoot(name));
  if (!base::PathExists(component_root)) {
    if (mkdir(component_root.value().c_str(), kComponentDirPerms) != 0) {
      PLOG(ERROR) << "Could not create component specific directory.";
      return false;
    }
  }

  std::unique_ptr<Component> component = Component::Create(
      base::FilePath(component_folder_abs_path), config_.keys);
  if (!component)
    return false;

  // Check that the reported version matches the component manifest version.
  if (component->manifest().version() != version) {
    LOG(ERROR) << "Version in signed manifest does not match the reported "
                  "component version.";
    return false;
  }

  // Take ownership of the component and verify it.
  base::FilePath version_path(GetVersionPath(name, version));
  // If |version_path| exists but was not the active version, ImageLoader
  // probably crashed previously and could not cleanup.
  if (base::PathExists(version_path)) {
    base::DeletePathRecursively(version_path);
  }

  if (mkdir(version_path.value().c_str(), kComponentDirPerms) != 0) {
    PLOG(ERROR) << "Could not create directory for new component version.";
    return false;
  }

  if (!component->CopyTo(version_path)) {
    base::DeletePathRecursively(version_path);
    return false;
  }

  if (!base::ImportantFileWriter::WriteFileAtomically(version_hint_path,
                                                      version)) {
    base::DeletePathRecursively(version_path);
    LOG(ERROR) << "Failed to update current version hint file.";
    return false;
  }

  // Now delete the old component version, if there was one.
  if (have_old_version) {
    base::DeletePathRecursively(GetVersionPath(name, old_version_hint));
  }

  return true;
}

std::string ImageLoaderImpl::GetComponentVersion(const std::string& name) {
  if (!IsIdValid(name)) {
    return kBadResult;
  }

  base::FilePath component_path;
  if (!GetPathToCurrentComponentVersion(name, &component_path)) {
    return kBadResult;
  }

  std::unique_ptr<Component> component =
      Component::Create(component_path, config_.keys);
  if (!component)
    return kBadResult;

  return component->manifest().version();
}

bool ImageLoaderImpl::GetComponentMetadata(
    const std::string& name, std::map<std::string, std::string>* out_metadata) {
  if (!IsIdValid(name)) {
    return false;
  }

  base::FilePath component_path;
  if (!GetPathToCurrentComponentVersion(name, &component_path)) {
    return false;
  }

  std::unique_ptr<Component> component =
      Component::Create(component_path, config_.keys);
  if (!component)
    return false;

  *out_metadata = component->manifest().metadata();
  return true;
}

base::FilePath ImageLoaderImpl::GetLatestVersionFilePath(
    const std::string& component_name) {
  return config_.storage_dir.Append(component_name).Append(kLatestVersionFile);
}

base::FilePath ImageLoaderImpl::GetVersionPath(
    const std::string& component_name, const std::string& version) {
  return config_.storage_dir.Append(component_name).Append(version);
}

base::FilePath ImageLoaderImpl::GetComponentRoot(
    const std::string& component_name) {
  return config_.storage_dir.Append(component_name);
}

bool ImageLoaderImpl::GetPathToCurrentComponentVersion(
    const std::string& component_name, base::FilePath* result) {
  base::FilePath component_root(GetComponentRoot(component_name));
  base::FilePath latest_version_path = GetLatestVersionFilePath(component_name);

  // Check that the version file exists, otherwise the logging when
  // ReadFileToString fails confuses the crash reporting. If the file doesn't
  // exist, the component most likely isn't installed.
  if (!base::PathExists(latest_version_path)) {
    LOG(INFO) << "The latest-version file does not exist. Component "
              << component_name << " is probably not installed.";
    return false;
  }

  std::string latest_version;
  if (!base::ReadFileToStringWithMaxSize(latest_version_path, &latest_version,
                                         kMaximumLatestVersionSize)) {
    LOG(ERROR) << "Failed to read latest-version file.";
    return false;
  }

  *result = component_root.Append(latest_version);
  return true;
}

}  // namespace imageloader
