// Copyright (c) 2012 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.

// Implements cros-disks::MountManager. See mount-manager.h for details.

#include "cros-disks/mount_manager.h"

#include <sys/mount.h>
#include <unistd.h>

#include <algorithm>
#include <unordered_set>
#include <utility>

#include <base/bind.h>
#include <base/check.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/containers/contains.h>
#include <base/strings/string_util.h>
#include <brillo/process/process_reaper.h>

#include "cros-disks/error_logger.h"
#include "cros-disks/mount_options.h"
#include "cros-disks/mounter.h"
#include "cros-disks/platform.h"
#include "cros-disks/quote.h"
#include "cros-disks/uri.h"

namespace cros_disks {
namespace {

// Permissions to set on the mount root directory (u+rwx,og+rx).
const mode_t kMountRootDirectoryPermissions =
    S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
// Maximum number of trials on creating a mount directory using
// Platform::CreateOrReuseEmptyDirectoryWithFallback().
// A value of 100 seems reasonable and enough to handle directory name
// collisions under common scenarios.
const unsigned kMaxNumMountTrials = 100;

}  // namespace

MountManager::MountManager(const std::string& mount_root,
                           Platform* platform,
                           Metrics* metrics,
                           brillo::ProcessReaper* process_reaper)
    : mount_root_(base::FilePath(mount_root)),
      platform_(platform),
      metrics_(metrics),
      process_reaper_(process_reaper) {
  CHECK(!mount_root_.empty()) << "Invalid mount root directory";
  CHECK(mount_root_.IsAbsolute()) << "Mount root not absolute path";
  CHECK(platform_) << "Invalid platform object";
  CHECK(metrics_) << "Invalid metrics object";
}

MountManager::~MountManager() {
  // UnmountAll() should be called from a derived class instead of this base
  // class as UnmountAll() can be overridden.
  DCHECK(mount_points_.empty());
}

bool MountManager::Initialize() {
  return platform_->CreateDirectory(mount_root_.value()) &&
         platform_->SetOwnership(mount_root_.value(), getuid(), getgid()) &&
         platform_->SetPermissions(mount_root_.value(),
                                   kMountRootDirectoryPermissions) &&
         platform_->CleanUpStaleMountPoints(mount_root_.value());
}

void MountManager::StartSession() {}

void MountManager::StopSession() {
  UnmountAll();
}

void MountManager::Mount(const std::string& source,
                         const std::string& filesystem_type,
                         std::vector<std::string> options,
                         MountCallback callback) {
  DCHECK(callback);

  // Source is not necessary a path, but if it is let's resolve it to
  // some real underlying object.
  std::string real_path;
  if (Uri::IsUri(source) || !ResolvePath(source, &real_path)) {
    real_path = source;
  }

  if (real_path.empty()) {
    LOG(ERROR) << "Cannot mount an invalid path: " << redact(source);
    std::move(callback).Run("", MOUNT_ERROR_INVALID_ARGUMENT);
    return;
  }

  if (RemoveParamsEqualTo(&options, "remount")) {
    // Remount an already-mounted drive.
    std::string mount_path;
    const MountErrorType error =
        Remount(real_path, filesystem_type, std::move(options), &mount_path);
    return std::move(callback).Run(mount_path, error);
  }

  // Mount a new drive.
  MountNewSource(real_path, filesystem_type, std::move(options),
                 std::move(callback));
}

MountErrorType MountManager::Remount(const std::string& source,
                                     const std::string& /*filesystem_type*/,
                                     std::vector<std::string> options,
                                     std::string* mount_path) {
  MountPoint* const mount_point = FindMountBySource(source);
  if (!mount_point) {
    LOG(WARNING) << "Not currently mounted: " << quote(source);
    return MOUNT_ERROR_PATH_NOT_MOUNTED;
  }

  bool read_only = IsReadOnlyMount(options);

  // Perform the underlying mount operation.
  if (const MountErrorType error = mount_point->Remount(read_only)) {
    LOG(ERROR) << "Cannot remount " << quote(source) << ": " << error;
    return error;
  }

  *mount_path = mount_point->path().value();
  LOG(INFO) << "Remounted " << quote(source) << " on " << quote(*mount_path);
  return MOUNT_ERROR_NONE;
}

void MountManager::MountNewSource(const std::string& source,
                                  const std::string& filesystem_type,
                                  std::vector<std::string> options,
                                  MountCallback callback) {
  DCHECK(callback);

  if (const MountPoint* const mp = FindMountBySource(source)) {
    LOG(ERROR) << redact(source) << " is already mounted on "
               << redact(mp->path());
    return std::move(callback).Run(mp->path().value(), mp->error());
  }

  // Extract the mount label string from the passed options.
  std::string label;
  if (const base::StringPiece key = "mountlabel";
      GetParamValue(options, key, &label))
    RemoveParamsWithSameName(&options, key);

  // Create a directory and set up its ownership/permissions for mounting
  // the source path. If an error occurs, ShouldReserveMountPathOnError()
  // is not called to reserve the mount path as a reserved mount path still
  // requires a proper mount directory.
  base::FilePath mount_path;
  if (const MountErrorType error =
          CreateMountPathForSource(source, label, &mount_path))
    return std::move(callback).Run("", error);

  // Perform the underlying mount operation. If an error occurs,
  // ShouldReserveMountPathOnError() is called to check if the mount path
  // should be reserved.
  MountErrorType error = MOUNT_ERROR_UNKNOWN;
  std::unique_ptr<MountPoint> mount_point =
      DoMount(source, filesystem_type, std::move(options), mount_path, &error);

  // Check for both mount_point and error here, since there might be (incorrect)
  // mounters that return no MountPoint and no error (crbug.com/1317877 and
  // crbug.com/1317878).
  if (!mount_point || error) {
    if (!error) {
      LOG(ERROR) << "Mounter for " << redact(source) << " of type "
                 << quote(filesystem_type)
                 << " returned no MountPoint and no error";
      error = MOUNT_ERROR_UNKNOWN;
    } else if (mount_point) {
      LOG(ERROR) << "Mounter for " << redact(source) << " of type "
                 << quote(filesystem_type)
                 << " returned both a mount point and " << error;
      mount_point.reset();
    }

    if (!ShouldReserveMountPathOnError(error)) {
      platform_->RemoveEmptyDirectory(mount_path.value());
      return std::move(callback).Run("", error);
    }

    DCHECK(!mount_point);
    // Create dummy mount point to associate with the mount path.
    mount_point = MountPoint::CreateUnmounted(
        {.mount_path = mount_path, .source = source, .error = error},
        platform_);
    LOG(INFO) << "Reserved mount path " << quote(mount_path) << " for "
              << quote(source);
  }

  DCHECK(mount_point);
  DCHECK_EQ(mount_point->path(), mount_path);

  // For some mounters, the string stored in |mount_point->source()| is
  // different from |source|.
  mount_point->SetSource(source, GetMountSourceType());

  if (const Process* const process = mount_point->process()) {
    // There is a FUSE process to monitor.
    process_reaper_->WatchForChild(
        FROM_HERE, process->pid(),
        base::BindOnce(&MountManager::OnSandboxedProcessExit,
                       base::Unretained(this), mount_path,
                       mount_point->GetWeakPtr()));

    DCHECK(callback);
    mount_point->SetLauncherExitCallback(base::BindOnce(
        &MountManager::OnLauncherExit, base::Unretained(this),
        std::move(callback), mount_path, mount_point->GetWeakPtr()));
  } else {
    // There is no FUSE process.
    std::move(callback).Run(mount_path.value(), error);
  }

  mount_points_.push_back(std::move(mount_point));
}

void MountManager::OnLauncherExit(
    MountCallback callback,
    const base::FilePath& mount_path,
    const base::WeakPtr<const MountPoint> mount_point,
    const MountErrorType error) {
  DCHECK(callback);
  std::move(callback).Run(mount_path.value(), error);

  if (!mount_point)
    return;

  DCHECK_EQ(mount_path, mount_point->path());
  DCHECK_EQ(error, mount_point->error());
  DCHECK_NE(MOUNT_ERROR_IN_PROGRESS, error);

  if (error)
    RemoveMount(mount_point.get());
}

MountErrorType MountManager::Unmount(const std::string& path) {
  // Look for a matching mount point, either by source path or by mount path.
  MountPoint* const mount_point =
      FindMountBySource(path) ?: FindMountByMountPath(base::FilePath(path));
  if (!mount_point)
    return MOUNT_ERROR_PATH_NOT_MOUNTED;

  if (const MountErrorType error = mount_point->Unmount();
      mount_point->is_mounted())
    return error;

  RemoveMount(mount_point);
  return MOUNT_ERROR_NONE;
}

void MountManager::UnmountAll() {
  mount_points_.clear();
}

bool MountManager::ResolvePath(const std::string& path,
                               std::string* real_path) {
  return platform_->GetRealPath(path, real_path);
}

MountPoint* MountManager::FindMountBySource(const std::string& source) const {
  for (const auto& mount_point : mount_points_) {
    DCHECK(mount_point);
    if (mount_point->source() == source)
      return mount_point.get();
  }
  return nullptr;
}

MountPoint* MountManager::FindMountByMountPath(
    const base::FilePath& path) const {
  for (const auto& mount_point : mount_points_) {
    DCHECK(mount_point);
    if (mount_point->path() == path)
      return mount_point.get();
  }
  return nullptr;
}

bool MountManager::RemoveMount(const MountPoint* const mount_point) {
  for (auto it = mount_points_.cbegin(); it != mount_points_.cend(); ++it) {
    if (it->get() == mount_point) {
      mount_points_.erase(it);
      return true;
    }
  }
  return false;
}

void MountManager::OnSandboxedProcessExit(
    const base::FilePath& mount_path,
    const base::WeakPtr<MountPoint> mount_point,
    const siginfo_t& info) {
  DCHECK_EQ(SIGCHLD, info.si_signo);
  if (info.si_code != CLD_EXITED) {
    LOG(ERROR) << "FUSE sandbox for " << redact(mount_path)
               << " was killed by signal " << info.si_status << ": "
               << strsignal(info.si_status);
  } else if (mount_point) {
    LOG(ERROR) << "FUSE daemon for " << redact(mount_path)
               << " finished unexpectedly with exit code " << info.si_status;
  } else {
    LOG(INFO) << "FUSE daemon for " << redact(mount_path)
              << " finished with exit code " << info.si_status;
  }

  if (!mount_point) {
    VLOG(1) << "Mount point " << redact(mount_path) << " was already removed";
    return;
  }

  DCHECK_EQ(mount_path, mount_point->path());
  RemoveMount(mount_point.get());
}

MountErrorType MountManager::CreateMountPathForSource(
    const std::string& source,
    const std::string& label,
    base::FilePath* mount_path) {
  DCHECK(mount_path);
  DCHECK(mount_path->empty());

  *mount_path = base::FilePath(SuggestMountPath(source));
  if (!label.empty()) {
    // Replace the basename(|actual_mount_path|) with |label|.
    *mount_path = mount_path->DirName().Append(label);
  }

  if (!IsValidMountPath(*mount_path)) {
    LOG(ERROR) << "Mount path " << quote(*mount_path) << " is invalid";
    return MOUNT_ERROR_INVALID_PATH;
  }

  std::unordered_set<std::string> reserved_paths;
  reserved_paths.reserve(mount_points_.size());
  for (const auto& mount_point : mount_points_) {
    reserved_paths.insert(mount_point->path().value());
  }

  std::string path = mount_path->value();
  if (!platform_->CreateOrReuseEmptyDirectoryWithFallback(
          &path, kMaxNumMountTrials, reserved_paths)) {
    LOG(ERROR) << "Cannot create directory " << quote(*mount_path)
               << " to mount " << quote(source);
    return MOUNT_ERROR_DIRECTORY_CREATION_FAILED;
  }

  *mount_path = base::FilePath(path);
  return MOUNT_ERROR_NONE;
}

std::vector<const MountPoint*> MountManager::GetMountPoints() const {
  std::vector<const MountPoint*> mount_points;
  mount_points.reserve(mount_points_.size());
  for (const std::unique_ptr<MountPoint>& mount_point : mount_points_) {
    DCHECK(mount_point);
    DCHECK_EQ(mount_point->source_type(), GetMountSourceType());
    mount_points.push_back(mount_point.get());
  }
  return mount_points;
}

bool MountManager::ShouldReserveMountPathOnError(MountErrorType error) const {
  return false;
}

bool MountManager::IsPathImmediateChildOfParent(const base::FilePath& path,
                                                const base::FilePath& parent) {
  std::vector<std::string> path_components, parent_components;
  path.StripTrailingSeparators().GetComponents(&path_components);
  parent.StripTrailingSeparators().GetComponents(&parent_components);
  if (path_components.size() != parent_components.size() + 1)
    return false;

  if (path_components.back() == base::FilePath::kCurrentDirectory ||
      path_components.back() == base::FilePath::kParentDirectory) {
    return false;
  }

  return std::equal(parent_components.begin(), parent_components.end(),
                    path_components.begin());
}

bool MountManager::IsValidMountPath(const base::FilePath& mount_path) const {
  return IsPathImmediateChildOfParent(mount_path, mount_root_);
}

}  // namespace cros_disks
