// Copyright 2019 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_monitor.h"

#include <inttypes.h>
#include <string.h>
#include <sys/mount.h>
#include <time.h>

#include <utility>

#include <base/bind.h>
#include <base/check.h>
#include <base/logging.h>
#include <base/containers/contains.h>
#include <base/strings/string_piece.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>
#include <brillo/udev/udev.h>
#include <brillo/udev/udev_device.h>
#include <brillo/udev/udev_enumerate.h>
#include <brillo/udev/udev_monitor.h>

#include "cros-disks/device_ejector.h"
#include "cros-disks/quote.h"
#include "cros-disks/udev_device.h"

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

// Checks if the device is allowed to be used through cros-disks.
bool IsDeviceAllowed(const UdevDevice& device,
                     const std::set<std::string>& allowlist) {
  if (device.IsIgnored())
    return false;
  if (base::Contains(allowlist, device.NativePath()))
    return true;
  if (device.IsLoopDevice())
    return false;
  if (device.IsMobileBroadbandDevice())
    return false;
  if (device.IsOnBootDevice())
    return false;
  return true;
}

// 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(const std::set<std::string>& allowlist,
                            std::vector<Disk>* disks,
                            std::unique_ptr<brillo::UdevDevice> dev) {
  UdevDevice device(std::move(dev));
  if (IsDeviceAllowed(device, allowlist))
    disks->push_back(device.ToDisk());
  return true;  // Continue the enumeration.
}

// An EnumerateBlockDevices callback that checks if |dev| matches |path|. If
// it's a match, populates |device| and returns false to stop the enumeration in
// EnumerateBlockDevices.
bool MatchDiskByPath(const std::string& path,
                     std::unique_ptr<UdevDevice>* device,
                     std::unique_ptr<brillo::UdevDevice> dev) {
  DCHECK(dev);
  DCHECK(device);

  const char* sys_path = dev->GetSysPath();
  const char* dev_path = dev->GetDevicePath();
  const char* dev_file = dev->GetDeviceNode();
  bool 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.

  *device = std::make_unique<UdevDevice>(std::move(dev));
  return false;  // Match. Stop enumeration.
}

// Logs a device with its properties.
void LogUdevDevice(const brillo::UdevDevice& dev) {
  if (!VLOG_IS_ON(1))
    return;

  // Some device events (eg USB drive removal) result in devnode being null.
  // This is gracefully handled by quote() without crashing.
  VLOG(1) << "   node: " << quote(dev.GetDeviceNode());
  VLOG(1) << "   devtype: " << quote(dev.GetDeviceType());
  VLOG(1) << "   syspath: " << quote(dev.GetSysPath());

  if (!VLOG_IS_ON(2))
    return;

  // Log all properties.
  for (std::unique_ptr<brillo::UdevListEntry> prop =
           dev.GetPropertiesListEntry();
       prop; prop = prop->GetNext()) {
    VLOG(2) << "   " << prop->GetName() << ": " << quote(prop->GetValue());
  }
}

void LogDevice(const UdevDevice& dev) {
  if (!VLOG_IS_ON(1))
    return;

  VLOG(1) << "path: " << quote(dev.NativePath());
  VLOG(1) << "  attributes: virtual=" << dev.IsVirtual()
          << " loop=" << dev.IsLoopDevice() << " boot=" << dev.IsOnBootDevice()
          << " removable=" << dev.IsOnRemovableDevice()
          << " broadband=" << dev.IsMobileBroadbandDevice()
          << " automount=" << dev.IsAutoMountable()
          << " media=" << dev.IsMediaAvailable();
}

}  // namespace

DiskMonitor::DiskMonitor() : udev_(brillo::Udev::Create()) {
  CHECK(udev_) << "Failed to initialize udev";
  udev_monitor_ = udev_->CreateMonitorFromNetlink("udev");
  CHECK(udev_monitor_) << "Failed to create a udev monitor";
  udev_monitor_->FilterAddMatchSubsystemDeviceType(kBlockSubsystem, nullptr);
  udev_monitor_->FilterAddMatchSubsystemDeviceType(kMmcSubsystem, nullptr);
  udev_monitor_->FilterAddMatchSubsystemDeviceType(kScsiSubsystem, kScsiDevice);
  CHECK(udev_monitor_->EnableReceiving());
}

DiskMonitor::~DiskMonitor() = default;

int DiskMonitor::udev_monitor_fd() const {
  return udev_monitor_->GetFileDescriptor();
}

bool DiskMonitor::Initialize() {
  // 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::BindRepeating(
      &DiskMonitor::EmulateAddBlockDeviceEvent, base::Unretained(this)));
  return true;
}

bool DiskMonitor::EmulateAddBlockDeviceEvent(
    std::unique_ptr<brillo::UdevDevice> dev) {
  DeviceEventList events;
  LOG(INFO) << "Emulating action 'add' on device " << quote(dev->GetSysName());
  LogUdevDevice(*dev);
  ProcessBlockDeviceEvents(std::move(dev), kUdevAddAction, &events);
  return true;  // Continue the enumeration.
}

std::vector<Disk> DiskMonitor::EnumerateDisks() const {
  std::vector<Disk> disks;
  EnumerateBlockDevices(base::BindRepeating(&AppendDiskIfNotIgnored, allowlist_,
                                            base::Unretained(&disks)));
  return disks;
}

void DiskMonitor::EnumerateBlockDevices(
    base::RepeatingCallback<bool(std::unique_ptr<brillo::UdevDevice> dev)>
        callback) const {
  std::unique_ptr<brillo::UdevEnumerate> enumerate = udev_->CreateEnumerate();
  enumerate->AddMatchSubsystem(kBlockSubsystem);
  enumerate->ScanDevices();

  for (std::unique_ptr<brillo::UdevListEntry> entry = enumerate->GetListEntry();
       entry; entry = entry->GetNext()) {
    std::unique_ptr<brillo::UdevDevice> dev =
        udev_->CreateDeviceFromSysPath(entry->GetName());
    if (!dev)
      continue;

    VLOG(1) << "Found device " << quote(dev->GetSysName());
    LogUdevDevice(*dev);

    bool continue_enumeration = callback.Run(std::move(dev));
    if (!continue_enumeration)
      break;
  }
}

void DiskMonitor::ProcessBlockDeviceEvents(
    std::unique_ptr<brillo::UdevDevice> dev,
    const char* action,
    DeviceEventList* events) {
  brillo::UdevDevice* raw_dev = dev.get();
  UdevDevice device(std::move(dev));
  LogDevice(device);
  if (!IsDeviceAllowed(device, allowlist_))
    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;
      }
    }
  }

  std::string device_path = device.NativePath();
  if (disk_added) {
    if (device.IsAutoMountable()) {
      if (base::Contains(disks_detected_, device_path)) {
        // Disk already exists, so remove it and then add it again.
        LOG(INFO) << "Re-add block device " << quote(device_path);
        events->push_back(DeviceEvent(DeviceEvent::kDiskRemoved, device_path));
      } else {
        disks_detected_[device_path] = {};

        // Add the disk as a child of its parent if the parent is already
        // added to |disks_detected_|.
        std::unique_ptr<brillo::UdevDevice> parent = raw_dev->GetParent();
        if (parent) {
          std::string parent_device_path =
              UdevDevice(std::move(parent)).NativePath();
          if (base::Contains(disks_detected_, parent_device_path)) {
            disks_detected_[parent_device_path].insert(device_path);
          }
        }
      }
      LOG(INFO) << "Add block device " << quote(device_path);
      events->push_back(DeviceEvent(DeviceEvent::kDiskAdded, device_path));
    }
  } else if (disk_removed) {
    disks_detected_.erase(device_path);
    LOG(INFO) << "Remove block device " << quote(device_path);
    events->push_back(DeviceEvent(DeviceEvent::kDiskRemoved, device_path));
  } else if (child_disk_removed) {
    bool no_child_disks_found = true;
    if (base::Contains(disks_detected_, device_path)) {
      auto& child_disks = disks_detected_[device_path];
      no_child_disks_found = child_disks.empty();
      for (const auto& child_disk : child_disks) {
        LOG(INFO) << "Remove child device " << quote(child_disk);
        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) {
      LOG(INFO) << "Remove parent device " << quote(device_path);
      events->push_back(DeviceEvent(DeviceEvent::kDiskRemoved, device_path));
    }
  }
}

void DiskMonitor::ProcessMmcOrScsiDeviceEvents(
    std::unique_ptr<brillo::UdevDevice> dev,
    const char* action,
    DeviceEventList* events) {
  UdevDevice device(std::move(dev));
  LogDevice(device);
  if (!IsDeviceAllowed(device, allowlist_))
    return;

  std::string device_path = device.NativePath();
  if (strcmp(action, kUdevAddAction) == 0) {
    if (base::Contains(devices_detected_, device_path)) {
      LOG(INFO) << "Re-add device " << quote(device_path);
      events->push_back(DeviceEvent(DeviceEvent::kDeviceScanned, device_path));
    } else {
      devices_detected_.insert(device_path);
      LOG(INFO) << "Add device " << quote(device_path);
      events->push_back(DeviceEvent(DeviceEvent::kDeviceAdded, device_path));
    }
  } else if (strcmp(action, kUdevRemoveAction) == 0) {
    if (base::Contains(devices_detected_, device_path)) {
      devices_detected_.erase(device_path);
      LOG(INFO) << "Remove device " << quote(device_path);
      events->push_back(DeviceEvent(DeviceEvent::kDeviceRemoved, device_path));
    }
  }
}

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

  std::unique_ptr<brillo::UdevDevice> dev = udev_monitor_->ReceiveDevice();
  if (!dev) {
    LOG(WARNING) << "Ignore device event with no associated udev device.";
    return false;
  }

  const char* sys_path = dev->GetSysPath();
  const char* subsystem = dev->GetSubsystem();
  const char* action = dev->GetAction();

  LOG(INFO) << "Got action " << quote(action) << " on device "
            << quote(dev->GetSysName());
  LogUdevDevice(*dev);

  if (!sys_path || !subsystem || !action) {
    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(std::move(dev), action, events);
  } else {
    // strcmp(subsystem, kMmcSubsystem) == 0 ||
    // strcmp(subsystem, kScsiSubsystem) == 0
    ProcessMmcOrScsiDeviceEvents(std::move(dev), action, events);
  }

  return true;
}

bool DiskMonitor::GetDiskByDevicePath(const base::FilePath& device_path,
                                      Disk* disk) const {
  LOG(INFO) << "Get disk by path " << quote(device_path);
  if (device_path.empty())
    return false;

  std::unique_ptr<UdevDevice> device;
  EnumerateBlockDevices(base::BindRepeating(
      &MatchDiskByPath, device_path.value(), base::Unretained(&device)));
  if (!device)
    return false;

  LogDevice(*device);
  if (!IsDeviceAllowed(*device, allowlist_))
    return false;

  if (disk)
    *disk = device->ToDisk();
  return true;
}

void DiskMonitor::AddDeviceToAllowlist(const base::FilePath& device) {
  allowlist_.insert(device.value());
}

void DiskMonitor::RemoveDeviceFromAllowlist(const base::FilePath& device) {
  allowlist_.erase(device.value());
}

}  // namespace cros_disks
