// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// StorageMonitorLinux implementation.

#include "components/storage_monitor/storage_monitor_linux.h"

#include <mntent.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/stat.h>

#include <limits>
#include <list>
#include <memory>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/process/process.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task_runner_util.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "components/storage_monitor/media_storage_util.h"
#include "components/storage_monitor/removable_device_constants.h"
#include "components/storage_monitor/storage_info.h"
#include "components/storage_monitor/udev_util_linux.h"
#include "device/udev_linux/scoped_udev.h"

namespace storage_monitor {

using MountPointDeviceMap = MtabWatcherLinux::MountPointDeviceMap;

namespace {

// udev device property constants.
const char kBlockSubsystemKey[] = "block";
const char kDiskDeviceTypeKey[] = "disk";
const char kFsUUID[] = "ID_FS_UUID";
const char kLabel[] = "ID_FS_LABEL";
const char kModel[] = "ID_MODEL";
const char kModelID[] = "ID_MODEL_ID";
const char kRemovableSysAttr[] = "removable";
const char kSerialShort[] = "ID_SERIAL_SHORT";
const char kSizeSysAttr[] = "size";
const char kVendor[] = "ID_VENDOR";
const char kVendorID[] = "ID_VENDOR_ID";

// Construct a device id using label or manufacturer (vendor and model) details.
std::string MakeDeviceUniqueId(struct udev_device* device) {
  std::string uuid = device::UdevDeviceGetPropertyValue(device, kFsUUID);
  if (!uuid.empty())
    return kFSUniqueIdPrefix + uuid;

  // If one of the vendor, model, serial information is missing, its value
  // in the string is empty.
  // Format: VendorModelSerial:VendorInfo:ModelInfo:SerialShortInfo
  // E.g.: VendorModelSerial:Kn:DataTravel_12.10:8000000000006CB02CDB
  std::string vendor = device::UdevDeviceGetPropertyValue(device, kVendorID);
  std::string model = device::UdevDeviceGetPropertyValue(device, kModelID);
  std::string serial_short =
      device::UdevDeviceGetPropertyValue(device, kSerialShort);
  if (vendor.empty() && model.empty() && serial_short.empty())
    return std::string();

  return kVendorModelSerialPrefix + vendor + ":" + model + ":" + serial_short;
}

// Records GetDeviceInfo result on destruction, to see how often we fail to get
// device details.
class ScopedGetDeviceInfoResultRecorder {
 public:
  ScopedGetDeviceInfoResultRecorder() : result_(false) {}
  ~ScopedGetDeviceInfoResultRecorder() {
    UMA_HISTOGRAM_BOOLEAN("MediaDeviceNotification.UdevRequestSuccess",
                          result_);
  }

  void set_result(bool result) {
    result_ = result;
  }

 private:
  bool result_;

  DISALLOW_COPY_AND_ASSIGN(ScopedGetDeviceInfoResultRecorder);
};

// Returns the storage partition size of the device specified by |device_path|.
// If the requested information is unavailable, returns 0.
uint64_t GetDeviceStorageSize(const base::FilePath& device_path,
                              struct udev_device* device) {
  // sysfs provides the device size in units of 512-byte blocks.
  const std::string partition_size =
      device::UdevDeviceGetSysattrValue(device, kSizeSysAttr);

  uint64_t total_size_in_bytes = 0;
  if (!base::StringToUint64(partition_size, &total_size_in_bytes))
    return 0;
  return (total_size_in_bytes <= std::numeric_limits<uint64_t>::max() / 512)
             ? total_size_in_bytes * 512
             : 0;
}

// Gets the device information using udev library.
std::unique_ptr<StorageInfo> GetDeviceInfo(const base::FilePath& device_path,
                                           const base::FilePath& mount_point) {
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  DCHECK(!device_path.empty());

  std::unique_ptr<StorageInfo> storage_info;

  ScopedGetDeviceInfoResultRecorder results_recorder;

  device::ScopedUdevPtr udev_obj(device::udev_new());
  if (!udev_obj.get())
    return storage_info;

  struct stat device_stat;
  if (stat(device_path.value().c_str(), &device_stat) < 0)
    return storage_info;

  char device_type;
  if (S_ISCHR(device_stat.st_mode))
    device_type = 'c';
  else if (S_ISBLK(device_stat.st_mode))
    device_type = 'b';
  else
    return storage_info;  // Not a supported type.

  device::ScopedUdevDevicePtr device(
      device::udev_device_new_from_devnum(udev_obj.get(), device_type,
                                          device_stat.st_rdev));
  if (!device.get())
    return storage_info;

  base::string16 volume_label = base::UTF8ToUTF16(
      device::UdevDeviceGetPropertyValue(device.get(), kLabel));
  base::string16 vendor_name = base::UTF8ToUTF16(
      device::UdevDeviceGetPropertyValue(device.get(), kVendor));
  base::string16 model_name = base::UTF8ToUTF16(
      device::UdevDeviceGetPropertyValue(device.get(), kModel));

  std::string unique_id = MakeDeviceUniqueId(device.get());
  const char* value =
      device::udev_device_get_sysattr_value(device.get(), kRemovableSysAttr);
  if (!value) {
    // |parent_device| is owned by |device| and does not need to be cleaned
    // up.
    struct udev_device* parent_device =
        device::udev_device_get_parent_with_subsystem_devtype(
            device.get(),
            kBlockSubsystemKey,
            kDiskDeviceTypeKey);
    value = device::udev_device_get_sysattr_value(parent_device,
                                                  kRemovableSysAttr);
  }
  const bool is_removable = (value && atoi(value) == 1);

  StorageInfo::Type type = StorageInfo::FIXED_MASS_STORAGE;
  if (is_removable) {
    type = MediaStorageUtil::HasDcim(mount_point)
               ? StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM
               : StorageInfo::REMOVABLE_MASS_STORAGE_NO_DCIM;
  }

  results_recorder.set_result(true);

  storage_info = std::make_unique<StorageInfo>(
      StorageInfo::MakeDeviceId(type, unique_id), mount_point.value(),
      volume_label, vendor_name, model_name,
      GetDeviceStorageSize(device_path, device.get()));
  return storage_info;
}

// Runs |callback| with the |new_mtab| on |storage_monitor_task_runner|.
void BounceMtabUpdateToStorageMonitorTaskRunner(
    scoped_refptr<base::SequencedTaskRunner> storage_monitor_task_runner,
    const MtabWatcherLinux::UpdateMtabCallback& callback,
    const MtabWatcherLinux::MountPointDeviceMap& new_mtab) {
  storage_monitor_task_runner->PostTask(FROM_HERE,
                                        base::BindOnce(callback, new_mtab));
}

MtabWatcherLinux* CreateMtabWatcherLinuxOnMtabWatcherTaskRunner(
    const base::FilePath& mtab_path,
    scoped_refptr<base::SequencedTaskRunner> storage_monitor_task_runner,
    const MtabWatcherLinux::UpdateMtabCallback& callback) {
  // Owned by caller.
  return new MtabWatcherLinux(
      mtab_path, base::Bind(&BounceMtabUpdateToStorageMonitorTaskRunner,
                            storage_monitor_task_runner, callback));
}

StorageMonitor::EjectStatus EjectPathOnBlockingTaskRunner(
    const base::FilePath& path,
    const base::FilePath& device) {
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);

  // Note: Linux LSB says umount should exist in /bin.
  static const char kUmountBinary[] = "/bin/umount";
  std::vector<std::string> command;
  command.push_back(kUmountBinary);
  command.push_back(path.value());

  base::LaunchOptions options;
  base::Process process = base::LaunchProcess(command, options);
  if (!process.IsValid())
    return StorageMonitor::EJECT_FAILURE;

  int exit_code = -1;
  if (!process.WaitForExitWithTimeout(base::TimeDelta::FromMilliseconds(3000),
                                      &exit_code)) {
    process.Terminate(-1, false);
    base::EnsureProcessTerminated(std::move(process));
    return StorageMonitor::EJECT_FAILURE;
  }

  // TODO(gbillock): Make sure this is found in documentation
  // somewhere. Experimentally it seems to hold that exit code
  // 1 means device is in use.
  if (exit_code == 1)
    return StorageMonitor::EJECT_IN_USE;
  if (exit_code != 0)
    return StorageMonitor::EJECT_FAILURE;

  return StorageMonitor::EJECT_OK;
}

}  // namespace

StorageMonitorLinux::StorageMonitorLinux(const base::FilePath& path)
    : mtab_path_(path),
      get_device_info_callback_(base::Bind(&GetDeviceInfo)),
      mtab_watcher_task_runner_(
          base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
                                           base::TaskPriority::BEST_EFFORT})) {}

StorageMonitorLinux::~StorageMonitorLinux() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  mtab_watcher_task_runner_->DeleteSoon(FROM_HERE, mtab_watcher_.release());
}

void StorageMonitorLinux::Init() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!mtab_path_.empty());

  base::PostTaskAndReplyWithResult(
      mtab_watcher_task_runner_.get(), FROM_HERE,
      base::Bind(&CreateMtabWatcherLinuxOnMtabWatcherTaskRunner, mtab_path_,
                 base::SequencedTaskRunnerHandle::Get(),
                 base::Bind(&StorageMonitorLinux::UpdateMtab,
                            weak_ptr_factory_.GetWeakPtr())),
      base::Bind(&StorageMonitorLinux::OnMtabWatcherCreated,
                 weak_ptr_factory_.GetWeakPtr()));
}

bool StorageMonitorLinux::GetStorageInfoForPath(
    const base::FilePath& path,
    StorageInfo* device_info) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(device_info);

  if (!path.IsAbsolute())
    return false;

  base::FilePath current = path;
  while (!base::Contains(mount_info_map_, current) &&
         current != current.DirName())
    current = current.DirName();

  auto mount_info = mount_info_map_.find(current);
  if (mount_info == mount_info_map_.end())
    return false;
  *device_info = mount_info->second.storage_info;
  return true;
}

void StorageMonitorLinux::SetGetDeviceInfoCallbackForTest(
    const GetDeviceInfoCallback& get_device_info_callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  get_device_info_callback_ = get_device_info_callback;
}

void StorageMonitorLinux::EjectDevice(
    const std::string& device_id,
    base::Callback<void(EjectStatus)> callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  StorageInfo::Type type;
  if (!StorageInfo::CrackDeviceId(device_id, &type, nullptr)) {
    callback.Run(EJECT_FAILURE);
    return;
  }

  DCHECK_NE(type, StorageInfo::MTP_OR_PTP);

  // Find the mount point for the given device ID.
  base::FilePath path;
  base::FilePath device;
  for (auto mount_info = mount_info_map_.begin();
       mount_info != mount_info_map_.end(); ++mount_info) {
    if (mount_info->second.storage_info.device_id() == device_id) {
      path = mount_info->first;
      device = mount_info->second.mount_device;
      mount_info_map_.erase(mount_info);
      break;
    }
  }

  if (path.empty()) {
    callback.Run(EJECT_NO_SUCH_DEVICE);
    return;
  }

  receiver()->ProcessDetach(device_id);

  base::PostTaskAndReplyWithResult(
      FROM_HERE,
      {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
      base::Bind(&EjectPathOnBlockingTaskRunner, path, device), callback);
}

void StorageMonitorLinux::OnMtabWatcherCreated(MtabWatcherLinux* watcher) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  mtab_watcher_.reset(watcher);
}

void StorageMonitorLinux::UpdateMtab(const MountPointDeviceMap& new_mtab) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  // Check existing mtab entries for unaccounted mount points.
  // These mount points must have been removed in the new mtab.
  std::list<base::FilePath> mount_points_to_erase;
  std::list<base::FilePath> multiple_mounted_devices_needing_reattachment;
  for (MountMap::const_iterator old_iter = mount_info_map_.begin();
       old_iter != mount_info_map_.end(); ++old_iter) {
    const base::FilePath& mount_point = old_iter->first;
    const base::FilePath& mount_device = old_iter->second.mount_device;
    auto new_iter = new_mtab.find(mount_point);
    // |mount_point| not in |new_mtab| or |mount_device| is no longer mounted at
    // |mount_point|.
    if (new_iter == new_mtab.end() || (new_iter->second != mount_device)) {
      auto priority = mount_priority_map_.find(mount_device);
      DCHECK(priority != mount_priority_map_.end());
      ReferencedMountPoint::const_iterator has_priority =
          priority->second.find(mount_point);
      if (StorageInfo::IsRemovableDevice(
              old_iter->second.storage_info.device_id())) {
        DCHECK(has_priority != priority->second.end());
        if (has_priority->second) {
          receiver()->ProcessDetach(old_iter->second.storage_info.device_id());
        }
        if (priority->second.size() > 1)
          multiple_mounted_devices_needing_reattachment.push_back(mount_device);
      }
      priority->second.erase(mount_point);
      if (priority->second.empty())
        mount_priority_map_.erase(mount_device);
      mount_points_to_erase.push_back(mount_point);
    }
  }

  // Erase the |mount_info_map_| entries afterwards. Erasing in the loop above
  // using the iterator is slightly more efficient, but more tricky, since
  // calling std::map::erase() on an iterator invalidates it.
  for (std::list<base::FilePath>::const_iterator it =
           mount_points_to_erase.begin();
       it != mount_points_to_erase.end();
       ++it) {
    mount_info_map_.erase(*it);
  }

  // For any multiply mounted device where the mount that we had notified
  // got detached, send a notification of attachment for one of the other
  // mount points.
  for (std::list<base::FilePath>::const_iterator it =
           multiple_mounted_devices_needing_reattachment.begin();
       it != multiple_mounted_devices_needing_reattachment.end();
       ++it) {
    auto first_mount_point_info = mount_priority_map_.find(*it)->second.begin();
    const base::FilePath& mount_point = first_mount_point_info->first;
    first_mount_point_info->second = true;

    const StorageInfo& mount_info =
        mount_info_map_.find(mount_point)->second.storage_info;
    DCHECK(StorageInfo::IsRemovableDevice(mount_info.device_id()));
    receiver()->ProcessAttach(mount_info);
  }

  // Check new mtab entries against existing ones.
  scoped_refptr<base::SequencedTaskRunner> mounting_task_runner =
      base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
                                       base::TaskPriority::BEST_EFFORT});
  for (auto new_iter = new_mtab.begin(); new_iter != new_mtab.end();
       ++new_iter) {
    const base::FilePath& mount_point = new_iter->first;
    const base::FilePath& mount_device = new_iter->second;
    auto old_iter = mount_info_map_.find(mount_point);
    if (old_iter == mount_info_map_.end() ||
        old_iter->second.mount_device != mount_device) {
      // New mount point found or an existing mount point found with a new
      // device.
      if (IsDeviceAlreadyMounted(mount_device)) {
        HandleDeviceMountedMultipleTimes(mount_device, mount_point);
      } else {
        base::PostTaskAndReplyWithResult(
            mounting_task_runner.get(), FROM_HERE,
            base::Bind(get_device_info_callback_, mount_device, mount_point),
            base::Bind(&StorageMonitorLinux::AddNewMount,
                       weak_ptr_factory_.GetWeakPtr(), mount_device));
      }
    }
  }

  // Note: Relies on scheduled tasks on the |mounting_task_runner| being
  // sequential. This block needs to follow the for loop, so that the DoNothing
  // call on the |mounting_task_runner| happens after the scheduled metadata
  // retrievals, meaning that the reply callback will then happen after all the
  // AddNewMount calls.
  if (!IsInitialized()) {
    mounting_task_runner->PostTaskAndReply(
        FROM_HERE, base::DoNothing(),
        base::Bind(&StorageMonitorLinux::MarkInitialized,
                   weak_ptr_factory_.GetWeakPtr()));
  }
}

bool StorageMonitorLinux::IsDeviceAlreadyMounted(
    const base::FilePath& mount_device) const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return base::Contains(mount_priority_map_, mount_device);
}

void StorageMonitorLinux::HandleDeviceMountedMultipleTimes(
    const base::FilePath& mount_device,
    const base::FilePath& mount_point) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  auto priority = mount_priority_map_.find(mount_device);
  DCHECK(priority != mount_priority_map_.end());
  const base::FilePath& other_mount_point = priority->second.begin()->first;
  priority->second[mount_point] = false;
  mount_info_map_[mount_point] =
      mount_info_map_.find(other_mount_point)->second;
}

void StorageMonitorLinux::AddNewMount(
    const base::FilePath& mount_device,
    std::unique_ptr<StorageInfo> storage_info) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (!storage_info)
    return;

  DCHECK(!storage_info->device_id().empty());

  bool removable = StorageInfo::IsRemovableDevice(storage_info->device_id());
  const base::FilePath mount_point(storage_info->location());

  MountPointInfo mount_point_info;
  mount_point_info.mount_device = mount_device;
  mount_point_info.storage_info = *storage_info;
  mount_info_map_[mount_point] = mount_point_info;
  mount_priority_map_[mount_device][mount_point] = removable;
  receiver()->ProcessAttach(*storage_info);
}

StorageMonitor* StorageMonitor::CreateInternal() {
  const base::FilePath kDefaultMtabPath("/etc/mtab");
  return new StorageMonitorLinux(kDefaultMtabPath);
}

}  // namespace storage_monitor
