// 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 <libudev.h>
#include <string.h>
#include <sys/mount.h>

#include <memory>
#include <utility>

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

#include "cros-disks/disk.h"
#include "cros-disks/exfat_mounter.h"
#include "cros-disks/external_mounter.h"
#include "cros-disks/filesystem.h"
#include "cros-disks/metrics.h"
#include "cros-disks/mount_options.h"
#include "cros-disks/ntfs_mounter.h"
#include "cros-disks/platform.h"
#include "cros-disks/system_mounter.h"
#include "cros-disks/udev_device.h"

using std::map;
using std::set;
using std::string;
using std::unique_ptr;
using std::vector;

namespace cros_disks {

namespace {

const char kBlockSubsystem[] = "block";
const char kMmcSubsystem[] = "mmc";
const char kScsiSubsystem[] = "scsi";
const char kScsiDevice[] = "scsi_device";
const char kUdevAddAction[] = "add";
const char kUdevChangeAction[] = "change";
const char kUdevRemoveAction[] = "remove";
const char kPropertyDiskEjectRequest[] = "DISK_EJECT_REQUEST";
const char kPropertyDiskMediaChange[] = "DISK_MEDIA_CHANGE";

// An EnumerateBlockDevices callback that appends a Disk object, created from
// |dev|, to |disks| if |dev| should not be ignored by cros-disks. Always
// returns true to continue the enumeration in EnumerateBlockDevices.
bool AppendDiskIfNotIgnored(vector<Disk>* disks, udev_device* dev) {
  DCHECK(disks);
  DCHECK(dev);

  UdevDevice device(dev);
  if (!device.IsIgnored())
    disks->push_back(device.ToDisk());

  return true;  // Continue the enumeration.
}

// An EnumerateBlockDevices callback that checks if |dev| matches |path|. If
// it's a match, sets |match| to true and |disk| (if not NULL) to a Disk object
// created from |dev|, and returns false to stop the enumeration in
// EnumerateBlockDevices. Otherwise, sets |match| to false, leaves |disk|
// unchanged, and returns true to continue the enumeration in
// EnumerateBlockDevices.
bool MatchDiskByPath(const string& path, bool* match, Disk* disk,
                     udev_device* dev) {
  DCHECK(match);
  DCHECK(dev);

  const char* sys_path = udev_device_get_syspath(dev);
  const char* dev_path = udev_device_get_devpath(dev);
  const char* dev_file = udev_device_get_devnode(dev);
  *match = (sys_path && path == sys_path) ||
           (dev_path && path == dev_path) ||
           (dev_file && path == dev_file);
  if (!*match)
    return true;  // Not a match. Continue the enumeration.

  if (disk)
    *disk = UdevDevice(dev).ToDisk();

  return false;  // Match. Stop enumeration.
}

}  // namespace

DiskManager::DiskManager(const string& mount_root, Platform* platform,
                         Metrics* metrics, DeviceEjector* device_ejector)
    : MountManager(mount_root, platform, metrics),
      device_ejector_(device_ejector),
      udev_(udev_new()),
      udev_monitor_fd_(0),
      eject_device_on_unmount_(true) {
  CHECK(device_ejector_) << "Invalid device ejector";
  CHECK(udev_) << "Failed to initialize udev";
  udev_monitor_ = udev_monitor_new_from_netlink(udev_, "udev");
  CHECK(udev_monitor_) << "Failed to create a udev monitor";
  udev_monitor_filter_add_match_subsystem_devtype(udev_monitor_,
                                                  kBlockSubsystem, nullptr);
  udev_monitor_filter_add_match_subsystem_devtype(udev_monitor_,
                                                  kMmcSubsystem, nullptr);
  udev_monitor_filter_add_match_subsystem_devtype(udev_monitor_,
                                                  kScsiSubsystem, kScsiDevice);
  udev_monitor_enable_receiving(udev_monitor_);
  udev_monitor_fd_ = udev_monitor_get_fd(udev_monitor_);
}

DiskManager::~DiskManager() {
  UnmountAll();
  udev_monitor_unref(udev_monitor_);
  udev_unref(udev_);
}

bool DiskManager::Initialize() {
  RegisterDefaultFilesystems();

  // Since there are no udev add events for the devices that already exist
  // when the disk manager starts, emulate udev add events for these devices
  // to correctly populate |disks_detected_|.
  EnumerateBlockDevices(base::Bind(&DiskManager::EmulateBlockDeviceEvent,
                                   base::Unretained(this),
                                   kUdevAddAction));

  return MountManager::Initialize();
}

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

bool DiskManager::EmulateBlockDeviceEvent(const char* action,
                                          udev_device* dev) {
  DCHECK(dev);

  DeviceEventList events;
  ProcessBlockDeviceEvents(dev, action, &events);

  return true;  // Continue the enumeration.
}

vector<Disk> DiskManager::EnumerateDisks() const {
  vector<Disk> disks;
  EnumerateBlockDevices(
      base::Bind(&AppendDiskIfNotIgnored, base::Unretained(&disks)));
  return disks;
}

void DiskManager::EnumerateBlockDevices(
    const base::Callback<bool(udev_device* dev)>& callback) const {
  udev_enumerate *enumerate = udev_enumerate_new(udev_);
  udev_enumerate_add_match_subsystem(enumerate, kBlockSubsystem);
  udev_enumerate_scan_devices(enumerate);

  udev_list_entry *device_list, *device_list_entry;
  device_list = udev_enumerate_get_list_entry(enumerate);
  udev_list_entry_foreach(device_list_entry, device_list) {
    const char *path = udev_list_entry_get_name(device_list_entry);
    udev_device *dev = udev_device_new_from_syspath(udev_, path);
    if (dev == nullptr) continue;

    LOG(INFO) << "Device";
    LOG(INFO) << "   Node: " << udev_device_get_devnode(dev);
    LOG(INFO) << "   Subsystem: " << udev_device_get_subsystem(dev);
    LOG(INFO) << "   Devtype: " << udev_device_get_devtype(dev);
    LOG(INFO) << "   Devpath: " << udev_device_get_devpath(dev);
    LOG(INFO) << "   Sysname: " << udev_device_get_sysname(dev);
    LOG(INFO) << "   Syspath: " << udev_device_get_syspath(dev);
    LOG(INFO) << "   Properties: ";
    udev_list_entry *property_list, *property_list_entry;
    property_list = udev_device_get_properties_list_entry(dev);
    udev_list_entry_foreach(property_list_entry, property_list) {
      const char *key = udev_list_entry_get_name(property_list_entry);
      const char *value = udev_list_entry_get_value(property_list_entry);
      LOG(INFO) << "      " << key << " = " << value;
    }

    bool continue_enumeration = callback.Run(dev);
    udev_device_unref(dev);
    if (!continue_enumeration)
      break;
  }
  udev_enumerate_unref(enumerate);
}

void DiskManager::ProcessBlockDeviceEvents(
    udev_device* dev, const char* action, DeviceEventList* events) {
  UdevDevice device(dev);
  if (device.IsIgnored())
    return;

  bool disk_added = false;
  bool disk_removed = false;
  bool child_disk_removed = false;
  if (strcmp(action, kUdevAddAction) == 0) {
    disk_added = true;
  } else if (strcmp(action, kUdevRemoveAction) == 0) {
    disk_removed = true;
  } else if (strcmp(action, kUdevChangeAction) == 0) {
    // For removable devices like CD-ROM, an eject request event
    // is treated as disk removal, while a media change event with
    // media available is treated as disk insertion.
    if (device.IsPropertyTrue(kPropertyDiskEjectRequest)) {
      disk_removed = true;
    } else if (device.IsPropertyTrue(kPropertyDiskMediaChange)) {
      if (device.IsMediaAvailable()) {
        disk_added = true;
      } else {
        child_disk_removed = true;
      }
    }
  }

  string device_path = device.NativePath();
  if (disk_added) {
    if (device.IsAutoMountable()) {
      if (ContainsKey(disks_detected_, device_path)) {
        // Disk already exists, so remove it and then add it again.
        events->push_back(DeviceEvent(DeviceEvent::kDiskRemoved, device_path));
      } else {
        disks_detected_[device_path] = set<string>();

        // Add the disk as a child of its parent if the parent is already
        // added to |disks_detected_|.
        udev_device* parent = udev_device_get_parent(dev);
        if (parent) {
          string parent_device_path = UdevDevice(parent).NativePath();
          if (ContainsKey(disks_detected_, parent_device_path)) {
            disks_detected_[parent_device_path].insert(device_path);
          }
        }
      }
      events->push_back(DeviceEvent(DeviceEvent::kDiskAdded, device_path));
    }
  } else if (disk_removed) {
    disks_detected_.erase(device_path);
    events->push_back(DeviceEvent(DeviceEvent::kDiskRemoved, device_path));
  } else if (child_disk_removed) {
    bool no_child_disks_found = true;
    if (ContainsKey(disks_detected_, device_path)) {
      set<string>& child_disks = disks_detected_[device_path];
      no_child_disks_found = child_disks.empty();
      for (const auto& child_disk : child_disks) {
        events->push_back(DeviceEvent(DeviceEvent::kDiskRemoved, child_disk));
      }
    }
    // When the device contains a full-disk partition, there are no child disks.
    // Remove the device instead.
    if (no_child_disks_found)
      events->push_back(DeviceEvent(DeviceEvent::kDiskRemoved, device_path));
  }
}

void DiskManager::ProcessMmcOrScsiDeviceEvents(
    udev_device* dev, const char* action, DeviceEventList* events) {
  UdevDevice device(dev);
  if (device.IsMobileBroadbandDevice())
    return;

  string device_path = device.NativePath();
  if (strcmp(action, kUdevAddAction) == 0) {
    if (ContainsKey(devices_detected_, device_path)) {
      events->push_back(DeviceEvent(DeviceEvent::kDeviceScanned, device_path));
    } else {
      devices_detected_.insert(device_path);
      events->push_back(DeviceEvent(DeviceEvent::kDeviceAdded, device_path));
    }
  } else if (strcmp(action, kUdevRemoveAction) == 0) {
    if (ContainsKey(devices_detected_, device_path)) {
      devices_detected_.erase(device_path);
      events->push_back(DeviceEvent(DeviceEvent::kDeviceRemoved, device_path));
    }
  }
}

bool DiskManager::GetDeviceEvents(DeviceEventList* events) {
  CHECK(events) << "Invalid device event list";

  udev_device *dev = udev_monitor_receive_device(udev_monitor_);
  if (!dev) {
    LOG(WARNING) << "Ignore device event with no associated udev device.";
    return false;
  }

  LOG(INFO) << "Got Device";
  LOG(INFO) << "   Syspath: " << udev_device_get_syspath(dev);
  LOG(INFO) << "   Node: " << udev_device_get_devnode(dev);
  LOG(INFO) << "   Subsystem: " << udev_device_get_subsystem(dev);
  LOG(INFO) << "   Devtype: " << udev_device_get_devtype(dev);
  LOG(INFO) << "   Action: " << udev_device_get_action(dev);

  const char *sys_path = udev_device_get_syspath(dev);
  const char *subsystem = udev_device_get_subsystem(dev);
  const char *action = udev_device_get_action(dev);
  if (!sys_path || !subsystem || !action) {
    udev_device_unref(dev);
    return false;
  }

  // |udev_monitor_| only monitors block, mmc, and scsi device changes, so
  // subsystem is either "block", "mmc", or "scsi".
  if (strcmp(subsystem, kBlockSubsystem) == 0) {
    ProcessBlockDeviceEvents(dev, action, events);
  } else {
    // strcmp(subsystem, kMmcSubsystem) == 0 ||
    // strcmp(subsystem, kScsiSubsystem) == 0
    ProcessMmcOrScsiDeviceEvents(dev, action, events);
  }

  udev_device_unref(dev);
  return true;
}

bool DiskManager::GetDiskByDevicePath(const string& device_path,
                                      Disk *disk) const {
  if (device_path.empty())
    return false;

  bool disk_found = false;
  EnumerateBlockDevices(base::Bind(&MatchDiskByPath,
                                   device_path,
                                   base::Unretained(&disk_found),
                                   base::Unretained(disk)));
  return disk_found;
}

const Filesystem* DiskManager::GetFilesystem(
    const string& filesystem_type) const {
  map<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.set_accepts_user_and_group_id(true);
  vfat_fs.AddExtraMountOption(MountOptions::kOptionDirSync);
  vfat_fs.AddExtraMountOption(MountOptions::kOptionFlush);
  vfat_fs.AddExtraMountOption("shortname=mixed");
  vfat_fs.AddExtraMountOption(MountOptions::kOptionUtf8);
  RegisterFilesystem(vfat_fs);

  Filesystem exfat_fs("exfat");
  exfat_fs.set_mounter_type(ExFATMounter::kMounterType);
  exfat_fs.set_accepts_user_and_group_id(true);
  exfat_fs.AddExtraMountOption(MountOptions::kOptionDirSync);
  RegisterFilesystem(exfat_fs);

  Filesystem ntfs_fs("ntfs");
  ntfs_fs.set_mounter_type(NTFSMounter::kMounterType);
  ntfs_fs.set_accepts_user_and_group_id(true);
  ntfs_fs.AddExtraMountOption(MountOptions::kOptionDirSync);
  RegisterFilesystem(ntfs_fs);

  Filesystem hfsplus_fs("hfsplus");
  hfsplus_fs.set_accepts_user_and_group_id(true);
  hfsplus_fs.AddExtraMountOption(MountOptions::kOptionDirSync);
  RegisterFilesystem(hfsplus_fs);

  Filesystem iso9660_fs("iso9660");
  iso9660_fs.set_is_mounted_read_only(true);
  iso9660_fs.set_accepts_user_and_group_id(true);
  iso9660_fs.AddExtraMountOption(MountOptions::kOptionUtf8);
  RegisterFilesystem(iso9660_fs);

  Filesystem udf_fs("udf");
  udf_fs.set_is_mounted_read_only(true);
  udf_fs.set_accepts_user_and_group_id(true);
  udf_fs.AddExtraMountOption(MountOptions::kOptionUtf8);
  RegisterFilesystem(udf_fs);

  Filesystem ext2_fs("ext2");
  ext2_fs.AddExtraMountOption(MountOptions::kOptionDirSync);
  RegisterFilesystem(ext2_fs);

  Filesystem ext3_fs("ext3");
  ext3_fs.AddExtraMountOption(MountOptions::kOptionDirSync);
  RegisterFilesystem(ext3_fs);

  Filesystem ext4_fs("ext4");
  ext4_fs.AddExtraMountOption(MountOptions::kOptionDirSync);
  RegisterFilesystem(ext4_fs);
}

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

Mounter* DiskManager::CreateMounter(const Disk& disk,
                                    const Filesystem& filesystem,
                                    const string& target_path,
                                    const vector<string>& options) const {
  const vector<string>& extra_options = filesystem.extra_mount_options();
  vector<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());

  string default_user_id, default_group_id;
  bool set_user_and_group_id = filesystem.accepts_user_and_group_id();
  if (set_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.Initialize(extended_options, set_user_and_group_id,
                           default_user_id, default_group_id);

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

  const string& mounter_type = filesystem.mounter_type();
  if (mounter_type == SystemMounter::kMounterType)
    return new(std::nothrow) SystemMounter(disk.device_file(), target_path,
                                           filesystem.mount_type(),
                                           mount_options);

  if (mounter_type == ExternalMounter::kMounterType)
    return new(std::nothrow) ExternalMounter(disk.device_file(), target_path,
                                             filesystem.mount_type(),
                                             mount_options);

  if (mounter_type == ExFATMounter::kMounterType)
    return new(std::nothrow) ExFATMounter(disk.device_file(), target_path,
                                          filesystem.mount_type(),
                                          mount_options, platform());

  if (mounter_type == NTFSMounter::kMounterType)
    return new(std::nothrow) NTFSMounter(disk.device_file(), target_path,
                                         filesystem.mount_type(),
                                         mount_options, platform());

  LOG(FATAL) << "Invalid mounter type '" << mounter_type << "'";
  return nullptr;
}

bool DiskManager::CanMount(const 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);
}

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

  Disk disk;
  if (!GetDiskByDevicePath(source_path, &disk)) {
    LOG(ERROR) << "'" << source_path << "' is not a valid device.";
    return MOUNT_ERROR_INVALID_DEVICE_PATH;
  }

  const string& device_file = disk.device_file();
  if (device_file.empty()) {
    LOG(ERROR) << "'" << source_path << "' does not have a device file";
    return MOUNT_ERROR_INVALID_DEVICE_PATH;
  }

  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) << "Failed to determine the file system type of device '"
               << source_path << "'";
    return MOUNT_ERROR_UNKNOWN_FILESYSTEM;
  }

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

  unique_ptr<Mounter> mounter(
      CreateMounter(disk, *filesystem, mount_path, options));
  CHECK(mounter) << "Failed to create a mounter";

  MountErrorType error_type = mounter->Mount();
  if (error_type == MOUNT_ERROR_NONE) {
    ScheduleEjectOnUnmount(mount_path, disk);
  }
  *applied_options = mounter->mount_options();

  return error_type;
}

MountErrorType DiskManager::DoUnmount(const string& path,
                                      const vector<string>& options) {
  CHECK(!path.empty()) << "Invalid path argument";

  // TODO(benchan): Deprecate "force" unmount options after updating the
  // cros-disks client on the Chrome side.
  int unmount_flags;
  if (!ExtractUnmountOptions(options, &unmount_flags)) {
    LOG(ERROR) << "Invalid unmount options";
    return MOUNT_ERROR_INVALID_UNMOUNT_OPTIONS;
  }

  // Temporarily filter out the force unmount flag set by Chrome.
  // TODO(benchan): Remove this after the force unmount option is deprecated.
  unmount_flags &= ~MNT_FORCE;

  // The USB or SD drive on some system may be powered off after the system
  // goes into the S3 suspend state. To avoid leaving a mount point in a stale
  // state while its associated physical drive is gone, the cros-disks client
  // on the Chrome side unmounts all the mount points it manages before the
  // system goes into suspend. However, an ongoing filesystem access may keep a
  // mount point busy, which is beyond the control of Chrome or cros-disks. We
  // used to force umount the mount points but that has become undesirable. For
  // instance, when force unmounting a mount point backed by a FUSE process,
  // umount2() reports an error and the mount point is left in a half-broken
  // state. Lazy unmount is preferred over force unmount under such condition
  // (although it still doesn't necessarily guarantee a clean unmount if the
  // filesystem access doesn't finish before the USB or SD drive is powered
  // off). To better handle this kind of situation, we first try performing a
  // normal unmount. If that fails with errno == EBUSY, we retry with a lazy
  // unmount before giving up and reporting an error.
  bool unmount_failed = (umount2(path.c_str(), unmount_flags) != 0);
  if (unmount_failed && errno == EBUSY) {
    LOG(ERROR) << "Failed to unmount '" << path
               << "' as it is busy; retry with lazy unmount";
    unmount_flags |= MNT_DETACH;
    unmount_failed = (umount2(path.c_str(), unmount_flags) != 0);
  }
  if (unmount_failed) {
    PLOG(ERROR) << "Failed to unmount '" << path << "'";
    // TODO(benchan): Extract error from low-level unmount operation.
    return MOUNT_ERROR_UNKNOWN;
  }

  EjectDeviceOfMountPath(path);

  return MOUNT_ERROR_NONE;
}

string DiskManager::SuggestMountPath(const string& source_path) const {
  Disk disk;
  GetDiskByDevicePath(source_path, &disk);
  // If GetDiskByDevicePath fails, disk.GetPresentationName() returns
  // the fallback presentation name.
  return string(mount_root()) + "/" + disk.GetPresentationName();
}

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

bool DiskManager::ScheduleEjectOnUnmount(const string& mount_path,
                                         const Disk& disk) {
  if (!disk.is_optical_disk())
    return false;

  devices_to_eject_on_unmount_[mount_path] = disk.device_file();
  return true;
}

bool DiskManager::EjectDeviceOfMountPath(const string& mount_path) {
  map<string, string>::iterator device_iterator =
      devices_to_eject_on_unmount_.find(mount_path);
  if (device_iterator == devices_to_eject_on_unmount_.end())
    return false;

  string device_file = device_iterator->second;
  devices_to_eject_on_unmount_.erase(device_iterator);

  if (!eject_device_on_unmount_)
    return false;

  LOG(INFO) << "Eject device '" << device_file << "'.";
  if (!device_ejector_->Eject(device_file)) {
    LOG(WARNING) << "Failed to eject media from optical device '"
                 << device_file << "'.";
    return false;
  }

  return true;
}

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
