// 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;

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

// |mount_base_path| is the subfolder where all images (dlc, components, etc.)
// are mounted.
base::FilePath GetMountPoint(const base::FilePath& mount_base_path,
                             const std::string& id) {
  return mount_base_path.Append(id);
}

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

}  // namespace

bool ImageLoaderImpl::LoadComponent(const std::string& name,
                                    const std::string& mount_point_str,
                                    HelperProcessProxy* proxy) {
  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) {
  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& a_or_b,
                                          HelperProcessProxy* proxy) {
  base::FilePath mount_point(GetMountPoint(config_.mount_path, id));

  Dlc dlc(id);
  return dlc.Mount(proxy, a_or_b, mount_point) ? mount_point.value()
                                               : kBadResult;
}

std::string ImageLoaderImpl::LoadComponentAtPath(
    const std::string& name,
    const base::FilePath& component_path,
    HelperProcessProxy* proxy) {
  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) {
  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::RemoveComponentAtPath(
    const std::string& name,
    const base::FilePath& component_root,
    const base::FilePath& component_path) {
  // 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::DeleteFile(component_root, /*recursive=*/true)) {
    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) {
  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::DeleteFile(version_path, /*recursive=*/true);
  }

  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::DeleteFile(version_path, /*recursive=*/true);
    return false;
  }

  if (!base::ImportantFileWriter::WriteFileAtomically(version_hint_path,
                                                      version)) {
    base::DeleteFile(version_path, /*recursive=*/true);
    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::DeleteFile(GetVersionPath(name, old_version_hint),
                     /*recursive=*/true);
  }

  return true;
}

std::string ImageLoaderImpl::GetComponentVersion(const std::string& name) {
  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) {
  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
