// 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/check.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/stl_util.h>
#include <base/strings/string_util.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;
// Prefix of the mount label option.
const char kMountOptionMountLabelPrefix[] = "mountlabel";
// Literal for mount option: "remount".
const char kMountOptionRemount[] = "remount";
// 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() calls MountPoint::Unmount() which may call back into
  // a derived class.
}

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

bool MountManager::StartSession() {
  return true;
}

bool MountManager::StopSession() {
  return UnmountAll();
}

MountErrorType MountManager::Mount(const std::string& source_path,
                                   const std::string& filesystem_type,
                                   std::vector<std::string> options,
                                   std::string* mount_path) {
  // 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_path) || !ResolvePath(source_path, &real_path)) {
    real_path = source_path;
  }

  if (real_path.empty()) {
    LOG(ERROR) << "Failed to mount an invalid path";
    return MOUNT_ERROR_INVALID_ARGUMENT;
  }
  if (!mount_path) {
    LOG(ERROR) << "Invalid mount path argument";
    return MOUNT_ERROR_INVALID_ARGUMENT;
  }

  if (RemoveParamsEqualTo(&options, kMountOptionRemount) == 0) {
    return MountNewSource(real_path, filesystem_type, std::move(options),
                          mount_path);
  } else {
    return Remount(real_path, filesystem_type, std::move(options), mount_path);
  }
}

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

  bool read_only = IsReadOnlyMount(options);

  // Perform the underlying mount operation.
  MountErrorType error_type = mount_point->Remount(read_only);
  if (error_type != MOUNT_ERROR_NONE) {
    LOG(ERROR) << "Cannot remount path " << quote(source_path) << ": "
               << error_type;
    return error_type;
  }

  *mount_path = mount_point->path().value();
  LOG(INFO) << "Path " << quote(source_path) << " on " << quote(*mount_path)
            << " is remounted";
  return error_type;
}

MountErrorType MountManager::MountNewSource(const std::string& source_path,
                                            const std::string& filesystem_type,
                                            std::vector<std::string> options,
                                            std::string* mount_path) {
  MountPoint* mp = FindMountBySource(source_path);
  if (mp) {
    // TODO(dats): Some obscure legacy. Why is this even needed?
    if (mount_path->empty() || mp->path().value() == *mount_path) {
      LOG(WARNING) << "Source " << redact(source_path)
                   << " is already mounted to " << redact(mp->path());
      *mount_path = mp->path().value();
      return GetMountErrorOfReservedMountPath(mp->path());
    }
    LOG(ERROR) << "Source " << redact(source_path) << " is already mounted to "
               << redact(mp->path());
    return MOUNT_ERROR_PATH_ALREADY_MOUNTED;
  }

  std::string mount_label;
  if (GetParamValue(options, kMountOptionMountLabelPrefix, &mount_label)) {
    RemoveParamsWithSameName(&options, kMountOptionMountLabelPrefix);
  }

  // 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 actual_mount_path(*mount_path);
  MountErrorType error =
      CreateMountPathForSource(source_path, mount_label, &actual_mount_path);
  if (error != MOUNT_ERROR_NONE) {
    return error;
  }

  // Perform the underlying mount operation. If an error occurs,
  // ShouldReserveMountPathOnError() is called to check if the mount path
  // should be reserved.
  bool mounted_as_read_only = false;
  MountErrorType error_type = MOUNT_ERROR_UNKNOWN;
  std::unique_ptr<MountPoint> mount_point = DoMount(
      source_path, filesystem_type, std::move(options),
      base::FilePath(actual_mount_path), &mounted_as_read_only, &error_type);
  if (error_type == MOUNT_ERROR_NONE) {
    LOG(INFO) << "Path " << quote(source_path) << " is mounted to "
              << quote(actual_mount_path);
    DCHECK(mount_point);
  } else if (ShouldReserveMountPathOnError(error_type)) {
    LOG(INFO) << "Reserving mount path " << quote(actual_mount_path) << " for "
              << quote(source_path);
    DCHECK(!mount_point);
    ReserveMountPath(actual_mount_path, error_type);
    // Create dummy mount point to associate with the mount path.
    mount_point = MountPoint::CreateLeaking(base::FilePath(actual_mount_path));
  } else {
    LOG(ERROR) << "Cannot mount " << redact(source_path) << " of type "
               << quote(filesystem_type) << ": " << error_type;
    platform_->RemoveEmptyDirectory(actual_mount_path.value());
    return error_type;
  }

  mount_states_.insert({source_path, std::move(mount_point)});
  *mount_path = actual_mount_path.value();
  return error_type;
}

MountErrorType MountManager::Unmount(const std::string& path) {
  // Determine whether the path is a source path or a mount path.
  // Is path a source path?
  MountPoint* mount_point = FindMountBySource(path);
  if (!mount_point) {
    // Not a source path. Is path a mount path?
    mount_point = FindMountByMountPath(base::FilePath(path));
    if (!mount_point) {
      // Not a mount path either.
      return MOUNT_ERROR_PATH_NOT_MOUNTED;
    }
  }

  MountErrorType error_type = MOUNT_ERROR_NONE;
  if (IsMountPathReserved(mount_point->path())) {
    LOG(INFO) << "Removing mount path '" << mount_point->path()
              << "' from the reserved list";
    UnreserveMountPath(mount_point->path());
  } else {
    error_type = mount_point->Unmount();

    switch (error_type) {
      case MOUNT_ERROR_NONE:
        LOG(INFO) << "Unmounted " << quote(mount_point->path());
        break;

      case MOUNT_ERROR_PATH_NOT_MOUNTED:
        LOG(WARNING) << "Not mounted " << quote(mount_point->path());
        break;

      default:
        LOG(ERROR) << "Cannot unmount " << quote(mount_point->path()) << ": "
                   << error_type;
        return error_type;
    }
  }

  platform_->RemoveEmptyDirectory(mount_point->path().value());
  for (auto it = mount_states_.begin(); it != mount_states_.end(); ++it) {
    if (it->second.get() == mount_point) {
      mount_states_.erase(it);
      break;
    }
  }
  return error_type;
}

bool MountManager::UnmountAll() {
  bool all_umounted = true;

  // Enumerate all the mount paths and then unmount, as calling Unmount()
  // modifies the cache.

  std::vector<std::string> paths;
  paths.reserve(mount_states_.size());
  for (const auto& entry : mount_states_) {
    paths.push_back(entry.second->path().value());
  }

  for (const auto& source_path : paths) {
    if (Unmount(source_path) != MOUNT_ERROR_NONE) {
      all_umounted = false;
    }
  }

  return all_umounted;
}

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 auto it = mount_states_.find(source);
  if (it == mount_states_.end())
    return nullptr;
  return it->second.get();
}

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

bool MountManager::RemoveMount(MountPoint* mount_point) {
  for (auto it = mount_states_.begin(); it != mount_states_.end(); ++it) {
    if (it->second.get() == mount_point) {
      mount_states_.erase(it);
      return true;
    }
  }
  return false;
}

MountErrorType MountManager::CreateMountPathForSource(
    const std::string& source,
    const std::string& label,
    base::FilePath* mount_path) {
  base::FilePath actual_mount_path = *mount_path;
  if (actual_mount_path.empty()) {
    actual_mount_path = base::FilePath(SuggestMountPath(source));
    if (!label.empty()) {
      // Replace the basename(|actual_mount_path|) with |label|.
      actual_mount_path = actual_mount_path.DirName().Append(label);
    }
  }

  if (!IsValidMountPath(base::FilePath(actual_mount_path))) {
    LOG(ERROR) << "Mount path " << quote(actual_mount_path) << " is invalid";
    return MOUNT_ERROR_INVALID_PATH;
  }

  bool mount_path_created;
  if (!mount_path->empty()) {
    mount_path_created =
        !IsMountPathReserved(actual_mount_path) &&
        platform_->CreateOrReuseEmptyDirectory(actual_mount_path.value());
  } else {
    std::unordered_set<std::string> reserved_paths;
    for (const auto& entry : reserved_mount_paths_) {
      reserved_paths.insert(entry.first.value());
    }
    std::string path = actual_mount_path.value();
    mount_path_created = platform_->CreateOrReuseEmptyDirectoryWithFallback(
        &path, kMaxNumMountTrials, reserved_paths);
    if (mount_path_created)
      actual_mount_path = base::FilePath(path);
  }
  if (!mount_path_created) {
    LOG(ERROR) << "Cannot create directory " << quote(actual_mount_path)
               << " to mount " << quote(source);
    return MOUNT_ERROR_DIRECTORY_CREATION_FAILED;
  }

  *mount_path = actual_mount_path;
  return MOUNT_ERROR_NONE;
}

bool MountManager::IsMountPathReserved(const base::FilePath& mount_path) const {
  return base::Contains(reserved_mount_paths_, mount_path);
}

MountErrorType MountManager::GetMountErrorOfReservedMountPath(
    const base::FilePath& mount_path) const {
  const auto it = reserved_mount_paths_.find(mount_path);
  return it != reserved_mount_paths_.end() ? it->second : MOUNT_ERROR_NONE;
}

void MountManager::ReserveMountPath(base::FilePath mount_path,
                                    MountErrorType error_type) {
  reserved_mount_paths_.insert({std::move(mount_path), error_type});
}

void MountManager::UnreserveMountPath(const base::FilePath& mount_path) {
  reserved_mount_paths_.erase(mount_path);
}

std::vector<MountEntry> MountManager::GetMountEntries() const {
  std::vector<MountEntry> mount_entries;
  mount_entries.reserve(mount_states_.size());
  for (const auto& entry : mount_states_) {
    const std::string& source_path = entry.first;
    const MountPoint& mount_point = *entry.second;

    mount_entries.push_back(
        {GetMountErrorOfReservedMountPath(mount_point.path()), source_path,
         GetMountSourceType(), mount_point.path().value(),
         mount_point.is_read_only()});
  }
  return mount_entries;
}

bool MountManager::ShouldReserveMountPathOnError(
    MountErrorType error_type) 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
