// 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 <base/logging.h>
#include <base/memory/scoped_ptr.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::vector;

namespace {

const char kBlockSubsystem[] = "block";
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";

}  // namespace

namespace cros_disks {

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, NULL);
  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();

  // Initialize |disks_detected_| with auto-mountable devices that already
  // exist when disk manager starts since there is no udev add event that adds
  // these devices to |disks_detected_|.
  vector<Disk> disks = EnumerateDisks();
  for (vector<Disk>::const_iterator disk_iterator = disks.begin();
       disk_iterator != disks.end(); ++disk_iterator) {
    if (disk_iterator->is_auto_mountable()) {
      disks_detected_.insert(
          std::make_pair(disk_iterator->native_path(), set<string>()));
    }
  }

  return MountManager::Initialize();
}

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

vector<Disk> DiskManager::EnumerateDisks() const {
  vector<Disk> disks;

  struct udev_enumerate *enumerate = udev_enumerate_new(udev_);
  udev_enumerate_add_match_subsystem(enumerate, kBlockSubsystem);
  udev_enumerate_scan_devices(enumerate);

  struct 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 == NULL) 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: ";
    struct 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;
    }

    UdevDevice device(dev);
    if (!device.IsIgnored()) {
      disks.push_back(device.ToDisk());
    }
    udev_device_unref(dev);
  }

  udev_enumerate_unref(enumerate);

  return disks;
}

void DiskManager::ProcessBlockDeviceEvents(
    struct 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_|.
        struct 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) {
    if (ContainsKey(disks_detected_, device_path)) {
      set<string>& child_disks = disks_detected_[device_path];
      for (set<string>::const_iterator child_iter = child_disks.begin();
           child_iter != child_disks.end(); ++child_iter) {
        events->push_back(DeviceEvent(DeviceEvent::kDiskRemoved, *child_iter));
      }
    }
  }
}

void DiskManager::ProcessScsiDeviceEvents(
    struct 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";

  struct 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 or scsi device changes, so
  // subsystem is either "block" or "scsi".
  if (strcmp(subsystem, kBlockSubsystem) == 0) {
    ProcessBlockDeviceEvents(dev, action, events);
  } else {  // strcmp(subsystem, kScsiSubsystem) == 0
    ProcessScsiDeviceEvents(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 is_sys_path = StartsWithASCII(device_path, "/sys/", true);
  bool is_dev_path = StartsWithASCII(device_path, "/devices/", true);
  bool is_dev_file = StartsWithASCII(device_path, "/dev/", true);
  bool disk_found = false;

  struct udev_enumerate *enumerate = udev_enumerate_new(udev_);
  udev_enumerate_add_match_subsystem(enumerate, kBlockSubsystem);
  udev_enumerate_scan_devices(enumerate);

  struct 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 *sys_path = udev_list_entry_get_name(device_list_entry);
    udev_device *dev = udev_device_new_from_syspath(udev_, sys_path);
    if (dev == NULL) continue;

    const char *dev_path = udev_device_get_devpath(dev);
    const char *dev_file = udev_device_get_devnode(dev);
    if ((is_sys_path && device_path == sys_path) ||
        (is_dev_path && device_path == dev_path) ||
        (is_dev_file && dev_file && device_path == dev_file)) {
      disk_found = true;
      if (disk)
        *disk = UdevDevice(dev).ToDisk();
    }
    udev_device_unref(dev);
    if (disk_found)
      break;
  }

  udev_enumerate_unref(enumerate);

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

  if (!platform()->experimental_features_enabled() &&
      filesystem_iterator->second.is_experimental())
    return NULL;

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

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

MountErrorType DiskManager::DoMount(const string& source_path,
                                    const string& filesystem_type,
                                    const vector<string>& options,
                                    const string& mount_path) {
  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 == NULL) {
    LOG(ERROR) << "File system type '" << device_filesystem_type
               << "' on device '" << source_path << "' is not supported";
    return MOUNT_ERROR_UNSUPPORTED_FILESYSTEM;
  }

  scoped_ptr<Mounter> mounter(CreateMounter(disk, *filesystem, mount_path,
                                            options));
  CHECK(mounter.get() != NULL) << "Failed to create a mounter";

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

  return error_type;
}

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

  int unmount_flags;
  if (!ExtractUnmountOptions(options, &unmount_flags)) {
    LOG(ERROR) << "Invalid unmount options";
    return MOUNT_ERROR_INVALID_UNMOUNT_OPTIONS;
  }

  if (umount2(path.c_str(), unmount_flags) != 0) {
    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
