// 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/callback.h>
#include <base/check.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 {

// Options passed to the mount syscall for various filesystem types.
constexpr char kMountOptionFlush[] = "flush";
constexpr char kMountOptionUtf8[] = "utf8";

// Options passed to the FUSE module for various filesystem types.
constexpr char kFUSEOptionDirSync[] = "dirsync";
constexpr char kFUSEOptionDmask[] = "dmask=0027";  // directory permissions 0750
constexpr char kFUSEOptionFmask[] = "fmask=0027";  // file permissions 0750

// Implementation of FUSEMounter aimed at removable storage with
// exFAT or NTFS filesystems.
class DiskFUSEMounter : public FUSEMounter {
 public:
  DiskFUSEMounter(const Platform* platform,
                  brillo::ProcessReaper* reaper,
                  std::string filesystem_type,
                  const SandboxedProcessFactory* upstream_factory,
                  SandboxedExecutable executable,
                  OwnerUser run_as,
                  std::vector<std::string> options)
      : FUSEMounter(platform, reaper, std::move(filesystem_type), {}),
        upstream_factory_(upstream_factory),
        sandbox_factory_(platform,
                         std::move(executable),
                         run_as,
                         false,  // no network needed
                         {},
                         {}),
        options_(std::move(options)) {}

 private:
  // FUSEMounter overrides:
  bool CanMount(const std::string& source,
                const std::vector<std::string>& params,
                base::FilePath* suggested_name) const override {
    if (suggested_name)
      *suggested_name = base::FilePath("disk");
    return true;
  }

  std::unique_ptr<SandboxedProcess> PrepareSandbox(
      const std::string& source,
      const base::FilePath&,
      std::vector<std::string>,
      MountErrorType* error) const override {
    auto device = base::FilePath(source);

    if (!device.IsAbsolute() || device.ReferencesParent() ||
        !base::StartsWith(device.value(), "/dev/",
                          base::CompareCase::SENSITIVE)) {
      LOG(ERROR) << "Source path " << quote(device) << " is invalid";
      *error = MOUNT_ERROR_INVALID_ARGUMENT;
      return nullptr;
    }

    if (!platform()->PathExists(device.value())) {
      LOG(ERROR) << "Source path " << quote(device) << " does not exist";
      *error = MOUNT_ERROR_INVALID_DEVICE_PATH;
      return nullptr;
    }

    // Make sure the FUSE user can read-write to the device.
    if (!platform()->SetOwnership(device.value(), getuid(),
                                  sandbox_factory_.run_as().gid) ||
        !platform()->SetPermissions(source,
                                    S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) {
      LOG(ERROR) << "Can't set up permissions on " << quote(source);
      *error = MOUNT_ERROR_INSUFFICIENT_PERMISSIONS;
      return nullptr;
    }

    std::unique_ptr<SandboxedProcess> sandbox;
    // For tests we use injected factory.
    if (upstream_factory_) {
      sandbox = upstream_factory_->CreateSandboxedProcess();
      sandbox->AddArgument(sandbox_factory_.executable().value());
    } else {
      sandbox = sandbox_factory_.CreateSandboxedProcess();
    }

    // Bind-mount the device into the sandbox.
    if (!sandbox->BindMount(device.value(), device.value(), true, false)) {
      LOG(ERROR) << "Can't bind the device " << quote(device)
                 << " into the sandbox";
      *error = MOUNT_ERROR_INTERNAL;
      return nullptr;
    }

    if (!options_.empty()) {
      std::string options;
      if (!JoinParamsIntoOptions(options_, &options)) {
        *error = MOUNT_ERROR_INVALID_MOUNT_OPTIONS;
        return nullptr;
      }
      sandbox->AddArgument("-o");
      sandbox->AddArgument(options);
    }

    sandbox->AddArgument(device.value());

    *error = MOUNT_ERROR_NONE;
    return sandbox;
  }

  // Used to inject mocks for testing.
  const SandboxedProcessFactory* const upstream_factory_;

  const FUSESandboxedProcessFactory sandbox_factory_;
  const std::vector<std::string> options_;
};

// Specialization of a system mounter which deals with FAT-specific
// mount options.
class FATMounter : public SystemMounter {
 public:
  FATMounter(const Platform* platform, std::vector<std::string> options)
      : SystemMounter(
            platform, "vfat", /* read_only= */ false, std::move(options)) {}

 private:
  MountErrorType ParseParams(
      std::vector<std::string> params,
      std::vector<std::string>* mount_options) const override {
    // 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.
    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;
    std::string offset_option =
        base::StringPrintf("time_offset=%" PRId64, offset_minutes);

    mount_options->push_back(offset_option);

    return SystemMounter::ParseParams(std::move(params), mount_options);
  }
};

}  // namespace

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

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

bool DiskManager::Initialize() {
  OwnerUser run_as_exfat;
  if (!platform()->GetUserAndGroupId("fuse-exfat", &run_as_exfat.uid,
                                     &run_as_exfat.gid)) {
    PLOG(ERROR) << "Cannot resolve fuse-exfat user";
    return false;
  }
  OwnerUser run_as_ntfs;
  if (!platform()->GetUserAndGroupId("ntfs-3g", &run_as_ntfs.uid,
                                     &run_as_ntfs.gid)) {
    PLOG(ERROR) << "Cannot resolve ntfs-3g user";
    return false;
  }

  std::string uid = base::StringPrintf("uid=%d", kChronosUID);
  std::string gid = base::StringPrintf("gid=%d", kChronosAccessGID);

  // FAT32 - typical USB stick/SD card filesystem.
  mounters_["vfat"] = std::make_unique<FATMounter>(
      platform(), std::vector<std::string>{kMountOptionFlush, "shortname=mixed",
                                           kMountOptionUtf8, uid, gid});

  // Fancier newer version of FAT used for new big SD cards and USB sticks.
  mounters_["exfat"] = std::make_unique<DiskFUSEMounter>(
      platform(), process_reaper(), "exfat", test_sandbox_factory_,
      SandboxedExecutable{base::FilePath("/usr/sbin/mount.exfat-fuse")},
      run_as_exfat,
      std::vector<std::string>{kFUSEOptionDirSync, kFUSEOptionDmask,
                               kFUSEOptionFmask, uid, gid});

  // External drives and some big USB sticks would likely have NTFS.
  mounters_["ntfs"] = std::make_unique<DiskFUSEMounter>(
      platform(), process_reaper(), "ntfs", test_sandbox_factory_,
      SandboxedExecutable{base::FilePath("/usr/bin/ntfs-3g")}, run_as_ntfs,
      std::vector<std::string>{kFUSEOptionDirSync, kFUSEOptionDmask,
                               kFUSEOptionFmask, uid, gid});

  // Typical CD/DVD filesystem. Inherently read-only.
  mounters_["iso9660"] = std::make_unique<SystemMounter>(
      platform(), "iso9660", true,
      std::vector<std::string>{kMountOptionUtf8, uid, gid});

  // Newer DVD filesystem. Inherently read-only.
  mounters_["udf"] = std::make_unique<SystemMounter>(
      platform(), "udf", true,
      std::vector<std::string>{kMountOptionUtf8, uid, gid});

  // MacOS's HFS+ is not properly/officially supported, but sort of works,
  // although with severe limitaions.
  mounters_["hfsplus"] = std::make_unique<SystemMounter>(
      platform(), "hfsplus", false, std::vector<std::string>{uid, gid});

  // Have no reasonable explanation why would one have external media
  // with a native Linux, filesystem and use CrOS to access it, given
  // all the problems and limitations they would face, but for compatibility
  // with previous versions we keep it unofficially supported.
  mounters_["ext4"] = std::make_unique<SystemMounter>(
      platform(), "ext4", false, std::vector<std::string>{});
  mounters_["ext3"] = std::make_unique<SystemMounter>(
      platform(), "ext3", false, std::vector<std::string>{});
  mounters_["ext2"] = std::make_unique<SystemMounter>(
      platform(), "ext2", false, std::vector<std::string>{});

  return MountManager::Initialize();
}

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

  if (!platform()->PathExists(disk.device_file)) {
    LOG(ERROR) << quote(source_path) << " has device file "
               << quote(disk.device_file) << " which is missing";
    *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 filesystem type of device "
               << quote(source_path);
    *error = MOUNT_ERROR_UNKNOWN_FILESYSTEM;
    return nullptr;
  }

  const auto it = mounters_.find(device_filesystem_type);
  if (it == mounters_.end()) {
    LOG(ERROR) << "Cannot handle filesystem type "
               << quote(device_filesystem_type) << " of device "
               << quote(source_path);
    *error = MOUNT_ERROR_UNSUPPORTED_FILESYSTEM;
    return nullptr;
  }

  const Mounter* const mounter = it->second.get();

  auto applied_options = options;
  if (const bool media_read_only = disk.is_read_only || disk.IsOpticalDisk();
      media_read_only && !IsReadOnlyMount(applied_options)) {
    applied_options.push_back("ro");
  }

  std::unique_ptr<MountPoint> mount_point =
      mounter->Mount(disk.device_file, mount_path, applied_options, error);
  if (*error != MOUNT_ERROR_NONE) {
    DCHECK(!mount_point);
    // Try to mount the filesystem read-only if mounting it read-write failed.
    if (!IsReadOnlyMount(applied_options)) {
      LOG(INFO) << "Trying to mount " << quote(source_path) << " read-only";
      applied_options.push_back("ro");
      mount_point =
          mounter->Mount(disk.device_file, mount_path, applied_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) {
  DCHECK(mount_point);

  if (disk.IsOpticalDisk()) {
    mount_point->SetEject(base::BindOnce(
        [](DiskManager* const disk_manager, const std::string& device_file) {
          if (!disk_manager->EjectDevice(device_file))
            LOG(ERROR) << "Cannot eject device " << quote(device_file);
        },
        this, disk.device_file));
  }

  return mount_point;
}

void 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;
  MountManager::UnmountAll();
  eject_device_on_unmount_ = true;
}

}  // namespace cros_disks
