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

#include "cros-disks/disk_manager.h"

#include <errno.h>
#include <inttypes.h>
#include <libudev.h>
#include <string.h>
#include <sys/mount.h>
#include <time.h>

#include <memory>
#include <utility>

#include <base/bind.h>
#include <base/logging.h>
#include <base/stl_util.h>
#include <base/strings/string_piece.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>

#include "cros-disks/device_ejector.h"
#include "cros-disks/disk_monitor.h"
#include "cros-disks/fuse_mounter.h"
#include "cros-disks/metrics.h"
#include "cros-disks/mount_options.h"
#include "cros-disks/mount_point.h"
#include "cros-disks/platform.h"
#include "cros-disks/quote.h"
#include "cros-disks/system_mounter.h"

namespace cros_disks {

namespace {
constexpr char kMounterTypeExFAT[] = "exfat";
constexpr char kMounterTypeNTFS[] = "ntfs";
}  // namespace

class DiskManager::EjectingMountPoint : public MountPoint {
 public:
  EjectingMountPoint(std::unique_ptr<MountPoint> mount_point,
                     DiskManager* disk_manager,
                     const std::string& device_file)
      : MountPoint(mount_point->path()),
        mount_point_(std::move(mount_point)),
        disk_manager_(disk_manager),
        device_file_(device_file) {
    DCHECK(mount_point_);
    DCHECK(disk_manager_);
    DCHECK(!device_file_.empty());
  }

  ~EjectingMountPoint() override { DestructorUnmount(); }

  void Release() override {
    MountPoint::Release();
    mount_point_->Release();
  }

 protected:
  MountErrorType UnmountImpl() override {
    MountErrorType error = mount_point_->Unmount();
    if (error == MOUNT_ERROR_NONE) {
      bool success = disk_manager_->EjectDevice(device_file_);
      LOG_IF(ERROR, !success)
          << "Unable to eject device " << quote(device_file_)
          << " for mount path " << quote(path());
    }
    return error;
  }

 private:
  const std::unique_ptr<MountPoint> mount_point_;
  DiskManager* const disk_manager_;
  const std::string device_file_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(EjectingMountPoint);
};

DiskManager::DiskManager(const std::string& mount_root,
                         Platform* platform,
                         Metrics* metrics,
                         brillo::ProcessReaper* process_reaper,
                         DiskMonitor* disk_monitor,
                         DeviceEjector* device_ejector)
    : MountManager(mount_root, platform, metrics, process_reaper),
      disk_monitor_(disk_monitor),
      device_ejector_(device_ejector),
      eject_device_on_unmount_(true) {}

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

bool DiskManager::Initialize() {
  RegisterDefaultFilesystems();
  return MountManager::Initialize();
}

const DiskManager::Filesystem* DiskManager::GetFilesystem(
    const std::string& filesystem_type) const {
  std::map<std::string, Filesystem>::const_iterator filesystem_iterator =
      filesystems_.find(filesystem_type);
  if (filesystem_iterator == filesystems_.end())
    return nullptr;

  return &filesystem_iterator->second;
}

void DiskManager::RegisterDefaultFilesystems() {
  std::string uid = base::StringPrintf("uid=%d", platform()->mount_user_id());
  std::string gid = base::StringPrintf("gid=%d", platform()->mount_group_id());

  Filesystem vfat_fs = {.type = "vfat"};
  vfat_fs.extra_mount_options = {MountOptions::kOptionFlush, "shortname=mixed",
                                 MountOptions::kOptionUtf8, uid, gid};
  RegisterFilesystem(vfat_fs);

  Filesystem exfat_fs = {.type = "exfat", .accepts_user_and_group_id = true};
  exfat_fs.extra_mount_options = {MountOptions::kOptionDirSync};
  RegisterFilesystem(exfat_fs);

  Filesystem ntfs_fs = {.type = "ntfs", .accepts_user_and_group_id = true};
  ntfs_fs.extra_mount_options = {MountOptions::kOptionDirSync};
  RegisterFilesystem(ntfs_fs);

  Filesystem hfsplus_fs = {.type = "hfsplus"};
  hfsplus_fs.extra_mount_options = {uid, gid};
  RegisterFilesystem(hfsplus_fs);

  Filesystem iso9660_fs = {.type = "iso9660", .is_read_only = true};
  iso9660_fs.extra_mount_options = {MountOptions::kOptionUtf8, uid, gid};
  RegisterFilesystem(iso9660_fs);

  Filesystem udf_fs = {.type = "udf", .is_read_only = true};
  udf_fs.extra_mount_options = {MountOptions::kOptionUtf8, uid, gid};
  RegisterFilesystem(udf_fs);

  Filesystem ext2_fs = {.type = "ext2"};
  RegisterFilesystem(ext2_fs);

  Filesystem ext3_fs = {.type = "ext3"};
  RegisterFilesystem(ext3_fs);

  Filesystem ext4_fs = {.type = "ext4"};
  RegisterFilesystem(ext4_fs);
}

void DiskManager::RegisterFilesystem(
    const DiskManager::Filesystem& filesystem) {
  filesystems_.emplace(filesystem.type, filesystem);
}

std::unique_ptr<Mounter> DiskManager::CreateMounter(
    const Disk& disk,
    const Filesystem& filesystem,
    const std::string& target_path,
    const std::vector<std::string>& options) const {
  std::vector<std::string> extended_options = filesystem.extra_mount_options;
  if (filesystem.type == "vfat") {
    // FAT32 stores times as local time instead of UTC. By default, the vfat
    // kernel module will use the kernel's time zone, which is set using
    // settimeofday(), to interpret time stamps as local time. However, time
    // zones are complicated and generally a user-space concern in modern Linux.
    // The man page for {get,set}timeofday comments that the |timezone| fields
    // of these functions is obsolete. Chrome OS doesn't appear to set these
    // either. Instead, we pass the time offset explicitly as a mount option so
    // that the user can see file time stamps as local time. This mirrors what
    // the user will see in other operating systems.
    // TODO(amistry): Consider moving this code into a FATMounter.
    time_t now = base::Time::Now().ToTimeT();
    struct tm timestruct;
    // The time zone might have changed since cros-disks was started. Force a
    // re-read of the time zone to ensure the local time is what the user
    // expects.
    tzset();
    localtime_r(&now, &timestruct);
    // tm_gmtoff is a glibc extension.
    int64_t offset_minutes = static_cast<int64_t>(timestruct.tm_gmtoff) / 60;
    extended_options.push_back(
        base::StringPrintf("time_offset=%" PRId64, offset_minutes));
  }

  std::string default_user_id, default_group_id;
  if (filesystem.accepts_user_and_group_id) {
    default_user_id = base::StringPrintf("%d", platform()->mount_user_id());
    default_group_id = base::StringPrintf("%d", platform()->mount_group_id());
  }

  MountOptions mount_options;
  mount_options.AllowOption(MountOptions::kOptionNoSymFollow);
  // TODO(crbug.com/950442): Remove this hack when MountOptions are gone.
  std::vector<std::string> workaround_options = extended_options;
  MountOptions junk_options;
  junk_options.Initialize(options, false, "", "");
  bool read_only_requested =
      (junk_options.ToMountFlagsAndData().first & MS_RDONLY) == MS_RDONLY;
  if (!read_only_requested)
    workaround_options.push_back(MountOptions::kOptionReadWrite);
  mount_options.Initialize(workaround_options,
                           filesystem.accepts_user_and_group_id,
                           default_user_id, default_group_id);

  bool mount_read_only = read_only_requested;
  if (filesystem.is_read_only || disk.is_read_only || disk.IsOpticalDisk()) {
    mount_read_only = true;
    mount_options.SetReadOnlyOption();
  }

  if (filesystem.type == kMounterTypeExFAT)
    return std::make_unique<FUSEMounterLegacy>(FUSEMounterLegacy::Params(
        {.filesystem_type = filesystem.type,
         .mount_options = std::move(mount_options),
         .mount_program = "/usr/sbin/mount.exfat-fuse",
         .mount_user = "fuse-exfat",
         .platform = platform(),
         .process_reaper = process_reaper()}));

  if (filesystem.type == kMounterTypeNTFS)
    return std::make_unique<FUSEMounterLegacy>(
        FUSEMounterLegacy::Params({.filesystem_type = filesystem.type,
                                   .mount_options = std::move(mount_options),
                                   .mount_program = "/usr/bin/ntfs-3g",
                                   .mount_user = "ntfs-3g",
                                   .platform = platform(),
                                   .process_reaper = process_reaper()}));

  // Otherwise use syscall-based mounting.
  return std::make_unique<SystemMounter>(platform(), filesystem.type,
                                         mount_read_only,
                                         std::move(extended_options));
}

bool DiskManager::CanMount(const std::string& source_path) const {
  // The following paths can be mounted:
  //     /sys/...
  //     /devices/...
  //     /dev/...
  return base::StartsWith(source_path, "/sys/", base::CompareCase::SENSITIVE) ||
         base::StartsWith(source_path, "/devices/",
                          base::CompareCase::SENSITIVE) ||
         base::StartsWith(source_path, "/dev/", base::CompareCase::SENSITIVE);
}

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

  Disk disk;
  if (!disk_monitor_->GetDiskByDevicePath(base::FilePath(source_path), &disk)) {
    LOG(ERROR) << quote(source_path) << " is not a valid device";
    *error = MOUNT_ERROR_INVALID_DEVICE_PATH;
    return nullptr;
  }

  if (disk.is_on_boot_device) {
    LOG(ERROR) << quote(source_path)
               << " is on boot device and not allowed to mount";
    *error = MOUNT_ERROR_INVALID_DEVICE_PATH;
    return nullptr;
  }

  if (disk.device_file.empty()) {
    LOG(ERROR) << quote(source_path) << " does not have a device file";
    *error = MOUNT_ERROR_INVALID_DEVICE_PATH;
    return nullptr;
  }

  std::string device_filesystem_type =
      filesystem_type.empty() ? disk.filesystem_type : filesystem_type;
  metrics()->RecordDeviceMediaType(disk.media_type);
  metrics()->RecordFilesystemType(device_filesystem_type);
  if (device_filesystem_type.empty()) {
    LOG(ERROR) << "Cannot determine the file system type of device "
               << quote(source_path);
    *error = MOUNT_ERROR_UNKNOWN_FILESYSTEM;
    return nullptr;
  }

  const Filesystem* filesystem = GetFilesystem(device_filesystem_type);
  if (filesystem == nullptr) {
    LOG(ERROR) << "File system type " << quote(device_filesystem_type)
               << " on device " << quote(source_path) << " is not supported";
    *error = MOUNT_ERROR_UNSUPPORTED_FILESYSTEM;
    return nullptr;
  }

  const auto mounter =
      CreateMounter(disk, *filesystem, mount_path.value(), options);
  CHECK(mounter) << "Failed to create a mounter";

  std::unique_ptr<MountPoint> mount_point =
      mounter->Mount(disk.device_file, mount_path, options, error);
  if (*error != MOUNT_ERROR_NONE) {
    DCHECK(!mount_point);
    // Try to mount the filesystem read-only if mounting it read-write failed.
    if (!base::Contains(options, MountOptions::kOptionReadOnly)) {
      LOG(INFO) << "Trying to mount " << quote(source_path) << " read-only";
      std::vector<std::string> ro_options = options;
      ro_options.push_back("ro");
      mount_point =
          mounter->Mount(disk.device_file, mount_path, ro_options, error);
    }
  }

  if (*error != MOUNT_ERROR_NONE) {
    DCHECK(!mount_point);
    return nullptr;
  }

  return MaybeWrapMountPointForEject(std::move(mount_point), disk);
}

std::string DiskManager::SuggestMountPath(
    const std::string& source_path) const {
  Disk disk;
  disk_monitor_->GetDiskByDevicePath(base::FilePath(source_path), &disk);
  // If GetDiskByDevicePath fails, disk.GetPresentationName() returns
  // the fallback presentation name.
  return mount_root().Append(disk.GetPresentationName()).value();
}

bool DiskManager::ShouldReserveMountPathOnError(
    MountErrorType error_type) const {
  return error_type == MOUNT_ERROR_UNKNOWN_FILESYSTEM ||
         error_type == MOUNT_ERROR_UNSUPPORTED_FILESYSTEM;
}

bool DiskManager::EjectDevice(const std::string& device_file) {
  if (eject_device_on_unmount_) {
    return device_ejector_->Eject(device_file);
  }
  return true;
}

std::unique_ptr<MountPoint> DiskManager::MaybeWrapMountPointForEject(
    std::unique_ptr<MountPoint> mount_point, const Disk& disk) {
  if (!disk.IsOpticalDisk()) {
    return mount_point;
  }
  return std::make_unique<EjectingMountPoint>(std::move(mount_point), this,
                                              disk.device_file);
}

bool DiskManager::UnmountAll() {
  // UnmountAll() is called when a user session ends. We do not want to eject
  // devices in that situation and thus set |eject_device_on_unmount_| to
  // false temporarily to prevent devices from being ejected upon unmount.
  eject_device_on_unmount_ = false;
  bool all_unmounted = MountManager::UnmountAll();
  eject_device_on_unmount_ = true;
  return all_unmounted;
}

}  // namespace cros_disks
