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

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

// 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& a_or_b,
                                          HelperProcessProxy* proxy) {
  if (!IsIdValid(id)) {
    return kBadResult;
  }
  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) {
  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,
                                     HelperProcessProxy* proxy) {
  if (!IsIdValid(id)) {
    return false;
  }

  return proxy->SendUnmountCommand(
      GetMountPoint(config_.mount_path, id).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::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) {
  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::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) {
  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
