// 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/exfat_mounter.h"
#include "cros-disks/filesystem.h"
#include "cros-disks/metrics.h"
#include "cros-disks/mount_options.h"
#include "cros-disks/mount_point.h"
#include "cros-disks/ntfs_mounter.h"
#include "cros-disks/platform.h"
#include "cros-disks/quote.h"
#include "cros-disks/system_mounter.h"

namespace cros_disks {

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 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() {
  // TODO(benchan): Perhaps these settings can be read from a config file.
  Filesystem vfat_fs("vfat");
  vfat_fs.accepts_user_and_group_id = true;
  vfat_fs.extra_mount_options = {MountOptions::kOptionDirSync,
                                 MountOptions::kOptionFlush, "shortname=mixed",
                                 MountOptions::kOptionUtf8};
  RegisterFilesystem(vfat_fs);

  Filesystem exfat_fs("exfat");
  exfat_fs.mounter_type = ExFATMounter::kMounterType;
  exfat_fs.accepts_user_and_group_id = true;
  exfat_fs.extra_mount_options = {MountOptions::kOptionDirSync};
  RegisterFilesystem(exfat_fs);

  Filesystem ntfs_fs("ntfs");
  ntfs_fs.mounter_type = NTFSMounter::kMounterType;
  ntfs_fs.accepts_user_and_group_id = true;
  ntfs_fs.extra_mount_options = {MountOptions::kOptionDirSync};
  RegisterFilesystem(ntfs_fs);

  Filesystem hfsplus_fs("hfsplus");
  hfsplus_fs.accepts_user_and_group_id = true;
  hfsplus_fs.extra_mount_options = {MountOptions::kOptionDirSync};
  RegisterFilesystem(hfsplus_fs);

  Filesystem iso9660_fs("iso9660");
  iso9660_fs.is_mounted_read_only = true;
  iso9660_fs.accepts_user_and_group_id = true;
  iso9660_fs.extra_mount_options = {MountOptions::kOptionUtf8};
  RegisterFilesystem(iso9660_fs);

  Filesystem udf_fs("udf");
  udf_fs.is_mounted_read_only = true;
  udf_fs.accepts_user_and_group_id = true;
  udf_fs.extra_mount_options = {MountOptions::kOptionUtf8};
  RegisterFilesystem(udf_fs);

  Filesystem ext2_fs("ext2");
  ext2_fs.extra_mount_options = {MountOptions::kOptionDirSync};
  RegisterFilesystem(ext2_fs);

  Filesystem ext3_fs("ext3");
  ext3_fs.extra_mount_options = {MountOptions::kOptionDirSync};
  RegisterFilesystem(ext3_fs);

  Filesystem ext4_fs("ext4");
  ext4_fs.extra_mount_options = {MountOptions::kOptionDirSync};
  RegisterFilesystem(ext4_fs);
}

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

std::unique_ptr<MounterCompat> DiskManager::CreateMounter(
    const Disk& disk,
    const Filesystem& filesystem,
    const std::string& target_path,
    const std::vector<std::string>& options) const {
  const std::vector<std::string>& extra_options =
      filesystem.extra_mount_options;
  std::vector<std::string> extended_options;
  extended_options.reserve(options.size() + extra_options.size());
  extended_options.assign(options.begin(), options.end());
  extended_options.insert(extended_options.end(), extra_options.begin(),
                          extra_options.end());

  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.WhitelistOption(MountOptions::kOptionNoSymFollow);
  mount_options.Initialize(extended_options,
                           filesystem.accepts_user_and_group_id,
                           default_user_id, default_group_id);

  if (filesystem.is_mounted_read_only || disk.is_read_only ||
      disk.IsOpticalDisk()) {
    mount_options.SetReadOnlyOption();
  }

  if (filesystem.mounter_type.empty())
    return std::make_unique<MounterCompat>(
        std::make_unique<SystemMounter>(filesystem.mount_type, platform()),
        mount_options);

  if (filesystem.mounter_type == ExFATMounter::kMounterType)
    return std::make_unique<ExFATMounter>(filesystem.mount_type, mount_options,
                                          platform(), process_reaper());

  if (filesystem.mounter_type == NTFSMounter::kMounterType)
    return std::make_unique<NTFSMounter>(filesystem.mount_type, mount_options,
                                         platform(), process_reaper());

  LOG(FATAL) << "Invalid mounter type " << quote(filesystem.mounter_type);
  return nullptr;
}

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

  std::unique_ptr<MounterCompat> 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, mounter->mount_options().options(), error);
  if (*error != MOUNT_ERROR_NONE) {
    DCHECK(!mount_point);
    // Try to mount the filesystem read-only if mounting it read-write failed.
    if (!mounter->mount_options().IsReadOnlyOptionSet()) {
      LOG(INFO) << "Trying to mount " << quote(source_path) << " read-only";
      std::vector<std::string> ro_options = options;
      ro_options.push_back("ro");
      mounter =
          CreateMounter(disk, *filesystem, mount_path.value(), ro_options);
      CHECK(mounter) << "Failed to create a 'ro' mounter";
      mount_point = mounter->Mount(disk.device_file, mount_path,
                                   mounter->mount_options().options(), error);
    }
  }

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

  *applied_options = mounter->mount_options();
  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
