// Copyright 2018 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 "cros-disks/fuse_mount_manager.h"

#include <sys/mount.h>

#include <utility>

#include <base/files/file_path.h>
#include <base/logging.h>
#include <brillo/process/process_reaper.h>

#include "cros-disks/drivefs_helper.h"
#include "cros-disks/fuse_helper.h"
#include "cros-disks/fuse_mounter.h"
#include "cros-disks/platform.h"
#include "cros-disks/quote.h"
#include "cros-disks/smbfs_helper.h"
#include "cros-disks/sshfs_helper.h"
#include "cros-disks/uri.h"

namespace cros_disks {

FUSEMountManager::FUSEMountManager(const std::string& mount_root,
                                   const std::string& working_dirs_root,
                                   Platform* platform,
                                   Metrics* metrics,
                                   brillo::ProcessReaper* process_reaper)
    : MountManager(mount_root, platform, metrics, process_reaper),
      working_dirs_root_(working_dirs_root) {}

FUSEMountManager::~FUSEMountManager() {
  UnmountAll();
}

bool FUSEMountManager::Initialize() {
  if (!MountManager::Initialize())
    return false;

  if (!platform()->DirectoryExists(working_dirs_root_) &&
      !platform()->CreateDirectory(working_dirs_root_)) {
    LOG(ERROR) << "Can't create writable FUSE directory";
    return false;
  }
  if (!platform()->SetOwnership(working_dirs_root_, getuid(), getgid()) ||
      !platform()->SetPermissions(working_dirs_root_, 0755)) {
    LOG(ERROR) << "Can't set up writable FUSE directory";
    return false;
  }

  // Register specific FUSE mount helpers here.
  RegisterHelper(std::make_unique<DrivefsHelper>(platform(), process_reaper()));
  RegisterHelper(std::make_unique<SshfsHelper>(platform(), process_reaper()));
  RegisterHelper(std::make_unique<SmbfsHelper>(platform(), process_reaper()));

  return true;
}

std::unique_ptr<MountPoint> FUSEMountManager::DoMount(
    const std::string& source,
    const std::string& fuse_type,
    const std::vector<std::string>& options,
    const base::FilePath& mount_path,
    MountOptions* applied_options,
    MountErrorType* error) {
  CHECK(!mount_path.empty()) << "Invalid mount path argument";

  Uri uri = Uri::Parse(source);
  CHECK(uri.valid()) << "Source " << quote(source) << " is not a URI";

  const FUSEHelper* selected_helper = nullptr;
  for (const auto& helper : helpers_) {
    if (helper->CanMount(uri)) {
      selected_helper = helper.get();
      break;
    }
  }

  if (!selected_helper) {
    LOG(ERROR) << "Cannot find suitable FUSE module for type "
               << quote(fuse_type) << " and source " << quote(source);
    *error = MOUNT_ERROR_UNKNOWN_FILESYSTEM;
    return nullptr;
  }

  // Make a temporary dir where the helper may keep stuff needed by the mounter
  // process.
  std::string path;
  if (!platform()->CreateTemporaryDirInDir(working_dirs_root_, ".", &path) ||
      !platform()->SetPermissions(path, 0755)) {
    LOG(ERROR) << "Cannot create working directory for FUSE module "
               << quote(selected_helper->type());
    *error = MOUNT_ERROR_DIRECTORY_CREATION_FAILED;
    return nullptr;
  }

  auto mounter = selected_helper->CreateMounter(base::FilePath(path), uri,
                                                mount_path, options);
  if (!mounter) {
    LOG(ERROR) << "Invalid options for FUSE module "
               << quote(selected_helper->type()) << " and source "
               << quote(source);
    *error = MOUNT_ERROR_INVALID_MOUNT_OPTIONS;
    return nullptr;
  }

  // Note: FUSEMounter::Mount() currently ignores |options| and instead uses the
  // MountOptions passed in the constructor.
  return mounter->Mount(source, mount_path, options, error);
}

bool FUSEMountManager::CanMount(const std::string& source) const {
  Uri uri = Uri::Parse(source);
  if (!uri.valid()) {
    return false;
  }

  for (const auto& helper : helpers_) {
    if (helper->CanMount(uri))
      return true;
  }
  return false;
}

std::string FUSEMountManager::SuggestMountPath(
    const std::string& source) const {
  Uri uri = Uri::Parse(source);
  if (!uri.valid()) {
    return "";
  }

  for (const auto& helper : helpers_) {
    if (helper->CanMount(uri))
      return mount_root().Append(helper->GetTargetSuffix(uri)).value();
  }
  base::FilePath base_name = base::FilePath(source).BaseName();
  return mount_root().Append(base_name).value();
}

void FUSEMountManager::RegisterHelper(std::unique_ptr<FUSEHelper> helper) {
  helpers_.push_back(std::move(helper));
}

}  // namespace cros_disks
