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

#include <base/bind.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/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";

// 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(std::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 std::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

DiskMonitor::DiskMonitor() : udev_(udev_new()), udev_monitor_fd_(0) {
  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_);
}

DiskMonitor::~DiskMonitor() {
  udev_monitor_unref(udev_monitor_);
  udev_unref(udev_);
}

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::Bind(&DiskMonitor::EmulateBlockDeviceEvent,
                                   base::Unretained(this), kUdevAddAction));
  return true;
}

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

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

  return true;  // Continue the enumeration.
}

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

void DiskMonitor::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);
    VLOG(1) << "   Subsystem: " << udev_device_get_subsystem(dev);
    VLOG(1) << "   Devtype: " << udev_device_get_devtype(dev);
    VLOG(1) << "   Devpath: " << udev_device_get_devpath(dev);
    VLOG(1) << "   Sysname: " << udev_device_get_sysname(dev);
    VLOG(1) << "   Syspath: " << udev_device_get_syspath(dev);
    VLOG(2) << "   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);
      VLOG(2) << "      " << key << " = " << value;
    }

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

void DiskMonitor::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;
      }
    }
  }

  std::string device_path = device.NativePath();
  if (disk_added) {
    if (device.IsAutoMountable()) {
      if (base::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] = {};

        // 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) {
          std::string parent_device_path = UdevDevice(parent).NativePath();
          if (base::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 (base::ContainsKey(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) {
        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 DiskMonitor::ProcessMmcOrScsiDeviceEvents(udev_device* dev,
                                               const char* action,
                                               DeviceEventList* events) {
  UdevDevice device(dev);
  if (device.IsMobileBroadbandDevice())
    return;

  std::string device_path = device.NativePath();
  if (strcmp(action, kUdevAddAction) == 0) {
    if (base::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 (base::ContainsKey(devices_detected_, device_path)) {
      devices_detected_.erase(device_path);
      events->push_back(DeviceEvent(DeviceEvent::kDeviceRemoved, device_path));
    }
  }
}

bool DiskMonitor::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);
  // Some device events (i.e. USB drive removal) result in devnode being NULL,
  // which ostream::operator<<(char*) can't handle. Wrapping the output in a
  // base::StringPiece() lets the LOG handle NULL without crashing.
  LOG(INFO) << "   Node: " << base::StringPiece(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 DiskMonitor::GetDiskByDevicePath(const base::FilePath& device_path,
                                      Disk* disk) const {
  if (device_path.empty())
    return false;

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

bool DiskMonitor::IsPathRecognized(const base::FilePath& path) const {
  // The following paths are handled:
  //     /sys/...
  //     /devices/...
  //     /dev/...
  return base::StartsWith(path.value(), "/sys/",
                          base::CompareCase::SENSITIVE) ||
         base::StartsWith(path.value(), "/devices/",
                          base::CompareCase::SENSITIVE) ||
         base::StartsWith(path.value(), "/dev/", base::CompareCase::SENSITIVE);
}

}  // namespace cros_disks
