// Copyright (c) 2011 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/udev_device.h"

#include <fcntl.h>
#include <libudev.h>
#include <linux/limits.h>
#include <stdlib.h>
#include <sys/statvfs.h>

#include <base/logging.h>
#include <base/sha1.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <rootdev/rootdev.h>

#include "cros-disks/mount_info.h"
#include "cros-disks/usb_device_info.h"

using std::string;
using std::vector;

namespace {

const char kNullDeviceFile[] = "/dev/null";
const char kAttributeIdProduct[] = "idProduct";
const char kAttributeIdVendor[] = "idVendor";
const char kAttributePartition[] = "partition";
const char kAttributeRange[] = "range";
const char kAttributeReadOnly[] = "ro";
const char kAttributeRemovable[] = "removable";
const char kAttributeSize[] = "size";
const char kDriverMMCBlock[] = "mmcblk";
const char kPropertyBlkIdFilesystemType[] = "TYPE";
const char kPropertyBlkIdFilesystemLabel[] = "LABEL";
const char kPropertyBlkIdFilesystemUUID[] = "UUID";
const char kPropertyCDROM[] = "ID_CDROM";
const char kPropertyCDROMDVD[] = "ID_CDROM_DVD";
const char kPropertyCDROMMedia[] = "ID_CDROM_MEDIA";
const char kPropertyCDROMMediaTrackCountData[] =
    "ID_CDROM_MEDIA_TRACK_COUNT_DATA";
const char kPropertyDeviceType[] = "DEVTYPE";
const char kPropertyDeviceTypeUSBDevice[] = "usb_device";
const char kPropertyFilesystemUsage[] = "ID_FS_USAGE";
const char kPropertyMistSupportedDevice[] = "MIST_SUPPORTED_DEVICE";
const char kPropertyModel[] = "ID_MODEL";
const char kPropertyPartitionEntryType[] = "ID_PART_ENTRY_TYPE";
const char kPropertyPartitionSize[] = "UDISKS_PARTITION_SIZE";
const char kPropertyPresentationHide[] = "UDISKS_PRESENTATION_HIDE";
const char kPropertyRotationRate[] = "ID_ATA_ROTATION_RATE_RPM";
const char kPropertySerial[] = "ID_SERIAL";
const char kSubsystemUsb[] = "usb";
const char kVirtualDevicePathPrefix[] = "/sys/devices/virtual/";
const char kLoopDevicePathPrefix[] = "/sys/devices/virtual/block/loop";
const char kUSBDeviceInfoFile[] = "/opt/google/cros-disks/usb-device-info";
const char kUSBIdentifierDatabase[] = "/usr/share/misc/usb.ids";
const char* kPartitionTypesToHide[] = {
  "c12a7328-f81f-11d2-ba4b-00a0c93ec93b",  // EFI system partition
  "fe3a2a5d-4f32-41a7-b725-accc3285a309",  // Chrome OS kernel
  "3cb8e202-3b7e-47dd-8a3c-7ff2a13cfcec",  // Chrome OS root filesystem
  "cab6e88e-abf3-4102-a07a-d4bb9be3c1d3",  // Chrome OS firmware
  "2e0a753d-9e48-43b0-8337-b15192cb1b5e",  // Chrome OS reserved
};

}  // namespace

namespace cros_disks {

UdevDevice::UdevDevice(udev_device *dev)
    : dev_(dev),
      blkid_cache_(nullptr) {
  CHECK(dev_) << "Invalid udev device";
  udev_device_ref(dev_);
}

UdevDevice::~UdevDevice() {
  if (blkid_cache_) {
    // It needs to call blkid_put_cache to deallocate the blkid cache.
    blkid_put_cache(blkid_cache_);
  }
  udev_device_unref(dev_);
}

// static
string UdevDevice::EnsureUTF8String(const string& str) {
  return base::IsStringUTF8(str) ? str : "";
}

// static
bool UdevDevice::IsValueBooleanTrue(const char *value) {
  return value && strcmp(value, "1") == 0;
}

string UdevDevice::GetAttribute(const char *key) const {
  const char *value = udev_device_get_sysattr_value(dev_, key);
  return (value) ? value : "";
}

bool UdevDevice::IsAttributeTrue(const char *key) const {
  const char *value = udev_device_get_sysattr_value(dev_, key);
  return IsValueBooleanTrue(value);
}

bool UdevDevice::HasAttribute(const char *key) const {
  const char *value = udev_device_get_sysattr_value(dev_, key);
  return value != nullptr;
}

string UdevDevice::GetProperty(const char *key) const {
  const char *value = udev_device_get_property_value(dev_, key);
  return (value) ? value : "";
}

bool UdevDevice::IsPropertyTrue(const char *key) const {
  const char *value = udev_device_get_property_value(dev_, key);
  return IsValueBooleanTrue(value);
}

bool UdevDevice::HasProperty(const char *key) const {
  const char *value = udev_device_get_property_value(dev_, key);
  return value != nullptr;
}

string UdevDevice::GetPropertyFromBlkId(const char *key) {
  string value;
  const char *dev_file = udev_device_get_devnode(dev_);
  if (dev_file) {
    // No cache file is used as it should always query information from
    // the device, i.e. setting cache file to /dev/null.
    if (blkid_cache_ || blkid_get_cache(&blkid_cache_, kNullDeviceFile) == 0) {
      blkid_dev dev = blkid_get_dev(blkid_cache_, dev_file, BLKID_DEV_NORMAL);
      if (dev) {
        char *tag_value = blkid_get_tag_value(blkid_cache_, key, dev_file);
        if (tag_value) {
          value = tag_value;
          free(tag_value);
        }
      }
    }
  }
  return value;
}

void UdevDevice::GetSizeInfo(uint64_t *total_size,
                             uint64_t *remaining_size) const {
  static const int kSectorSize = 512;
  uint64_t total = 0, remaining = 0;

  // If the device is mounted, obtain the total and remaining size in bytes
  // using statvfs.
  vector<string> mount_paths = GetMountPaths();
  if (!mount_paths.empty()) {
    struct statvfs stat;
    if (statvfs(mount_paths[0].c_str(), &stat) == 0) {
      total = stat.f_blocks * stat.f_frsize;
      remaining = stat.f_bfree * stat.f_frsize;
    }
  }

  // If the UDISKS_PARTITION_SIZE property is set, use it as the total size
  // instead. If the UDISKS_PARTITION_SIZE property is not set but sysfs
  // provides a size value, which is the actual size in bytes divided by 512,
  // use that as the total size instead.
  const char *partition_size =
      udev_device_get_property_value(dev_, kPropertyPartitionSize);
  int64_t size = 0;
  if (partition_size) {
    base::StringToInt64(partition_size, &size);
    total = size;
  } else {
    const char *size_attr = udev_device_get_sysattr_value(dev_, kAttributeSize);
    if (size_attr) {
      base::StringToInt64(size_attr, &size);
      total = size * kSectorSize;
    }
  }

  if (total_size)
    *total_size = total;
  if (remaining_size)
    *remaining_size = remaining;
}

size_t UdevDevice::GetPartitionCount() const {
  size_t partition_count = 0;
  const char *dev_file = udev_device_get_devnode(dev_);
  if (dev_file) {
    blkid_probe probe = blkid_new_probe_from_filename(dev_file);
    if (probe) {
      blkid_partlist partitions = blkid_probe_get_partitions(probe);
      if (partitions) {
        partition_count = blkid_partlist_numof_partitions(partitions);
      }
      blkid_free_probe(probe);
    }
  }
  return partition_count;
}

DeviceMediaType UdevDevice::GetDeviceMediaType() const {
  if (IsPropertyTrue(kPropertyCDROMDVD))
    return DEVICE_MEDIA_DVD;

  if (IsPropertyTrue(kPropertyCDROM))
    return DEVICE_MEDIA_OPTICAL_DISC;

  if (IsOnMMCDevice())
    return DEVICE_MEDIA_SD;

  string vendor_id, product_id;
  if (GetVendorAndProductId(&vendor_id, &product_id)) {
    USBDeviceInfo info;
    info.RetrieveFromFile(kUSBDeviceInfoFile);
    return info.GetDeviceMediaType(vendor_id, product_id);
  }
  return DEVICE_MEDIA_UNKNOWN;
}

bool UdevDevice::GetVendorAndProductId(
    string* vendor_id, string* product_id) const {
  // Search up the parent device tree to obtain the vendor and product ID
  // of the first device with a device type "usb_device". Then look up the
  // media type based on the vendor and product ID from a USB device info file.
  for (udev_device *dev = dev_; dev; dev = udev_device_get_parent(dev)) {
    const char *device_type =
        udev_device_get_property_value(dev, kPropertyDeviceType);
    if (device_type && strcmp(device_type, kPropertyDeviceTypeUSBDevice) == 0) {
      const char *vendor_id_attr =
          udev_device_get_sysattr_value(dev, kAttributeIdVendor);
      const char *product_id_attr =
          udev_device_get_sysattr_value(dev, kAttributeIdProduct);
      if (vendor_id_attr && product_id_attr) {
        *vendor_id = vendor_id_attr;
        *product_id = product_id_attr;
        return true;
      }
    }
  }
  return false;
}

bool UdevDevice::IsMediaAvailable() const {
  bool is_media_available = true;
  if (IsAttributeTrue(kAttributeRemovable)) {
    if (IsPropertyTrue(kPropertyCDROM)) {
      is_media_available = IsPropertyTrue(kPropertyCDROMMedia);
    } else {
      const char *dev_file = udev_device_get_devnode(dev_);
      if (dev_file) {
        int fd = open(dev_file, O_RDONLY);
        if (fd < 0) {
          is_media_available = false;
        } else {
          close(fd);
        }
      }
    }
  }
  return is_media_available;
}

bool UdevDevice::IsMobileBroadbandDevice() const {
  // Check if a parent device, which belongs to the "usb" subsystem and has a
  // device type "usb_device", has a property "MIST_SUPPORTED_DEVICE=1". If so,
  // it is a mobile broadband device supported by mist.
  udev_device *parent = udev_device_get_parent_with_subsystem_devtype(
      dev_, kSubsystemUsb, kPropertyDeviceTypeUSBDevice);
  if (!parent)
    return false;

  const char* value =
      udev_device_get_property_value(parent, kPropertyMistSupportedDevice);
  return IsValueBooleanTrue(value);
}

bool UdevDevice::IsAutoMountable() const {
  // TODO(benchan): Find a reliable way to detect if a device is a removable
  // storage as the removable attribute in sysfs does not always tell the truth.
  return !IsOnBootDevice() && !IsVirtual();
}

bool UdevDevice::IsHidden() {
  if (IsPropertyTrue(kPropertyPresentationHide))
    return true;

  // Hide an optical disc without any data track.
  // udev/cdrom_id only sets ID_CDROM_MEDIA_TRACK_COUNT_DATA when there is at
  // least one data track.
  if (IsPropertyTrue(kPropertyCDROM) &&
      !HasProperty(kPropertyCDROMMediaTrackCountData)) {
    return true;
  }

  // Hide a mobile broadband device, which may initially expose itself as a USB
  // mass storage device and later be switched to a modem by mist.
  if (IsMobileBroadbandDevice())
    return true;

  // Hide a device that is neither marked as a partition nor a filesystem,
  // unless it has no valid partitions (e.g. the device is unformatted or
  // corrupted). An unformatted or corrupted device is visible in the file
  // the file browser so that we can provide a way to format it.
  if (!HasAttribute(kAttributePartition) &&
      !HasProperty(kPropertyFilesystemUsage) &&
      (GetPartitionCount() > 0))
    return true;

  // Hide special partitions based on partition type.
  string partition_type = GetProperty(kPropertyPartitionEntryType);
  if (!partition_type.empty()) {
    for (size_t i = 0; i < arraysize(kPartitionTypesToHide); ++i) {
      if (partition_type == kPartitionTypesToHide[i])
        return true;
    }
  }
  return false;
}

bool UdevDevice::IsIgnored() const {
  return IsVirtual() && !IsLoopDevice();
}

bool UdevDevice::IsOnBootDevice() const {
  // Obtain the boot device path, e.g. /dev/sda
  char boot_device_path[PATH_MAX];
  if (rootdev(boot_device_path, sizeof(boot_device_path), true, true)) {
    LOG(ERROR) << "Could not determine root device";
    // Assume it is on the boot device when there is any uncertainty.
    // This is to prevent a device, which is potentially on the boot device,
    // from being auto mounted and exposed to users.
    // TODO(benchan): Find a way to eliminate the uncertainty.
    return true;
  }

  // Compare the device file path of the current device and all its parents
  // with the boot device path. Any match indicates that the current device
  // is on the boot device.
  for (udev_device *dev = dev_; dev; dev = udev_device_get_parent(dev)) {
    const char *dev_file = udev_device_get_devnode(dev);
    if (dev_file) {
      if (strncmp(boot_device_path, dev_file, PATH_MAX) == 0) {
        return true;
      }
    }
  }
  return false;
}

bool UdevDevice::IsOnMMCDevice() const {
  for (udev_device *dev = dev_; dev; dev = udev_device_get_parent(dev)) {
    const char *driver = udev_device_get_driver(dev);
    if (driver && strcmp(driver, kDriverMMCBlock) == 0) {
      return true;
    }
  }
  return false;
}

bool UdevDevice::IsOnRemovableDevice() const {
  for (udev_device *dev = dev_; dev; dev = udev_device_get_parent(dev)) {
    const char *value = udev_device_get_sysattr_value(dev, kAttributeRemovable);
    if (IsValueBooleanTrue(value))
      return true;
  }
  return false;
}

bool UdevDevice::IsVirtual() const {
  const char *sys_path = udev_device_get_syspath(dev_);
  if (sys_path) {
    return base::StartsWith(sys_path, kVirtualDevicePathPrefix,
                            base::CompareCase::SENSITIVE);
  }
  // To be safe, mark it as virtual device if sys path cannot be determined.
  return true;
}

bool UdevDevice::IsLoopDevice() const {
  const char *sys_path = udev_device_get_syspath(dev_);
  if (sys_path) {
    return base::StartsWith(sys_path, kLoopDevicePathPrefix,
                            base::CompareCase::SENSITIVE);
  }
  return false;
}

string UdevDevice::NativePath() const {
  const char *sys_path = udev_device_get_syspath(dev_);
  return sys_path ? sys_path : "";
}

vector<string> UdevDevice::GetMountPaths() const {
  const char *device_path = udev_device_get_devnode(dev_);
  if (device_path) {
    return GetMountPaths(device_path);
  }
  return vector<string>();
}

vector<string> UdevDevice::GetMountPaths(const string& device_path) {
  MountInfo mount_info;
  if (mount_info.RetrieveFromCurrentProcess()) {
    return mount_info.GetMountPaths(device_path);
  }
  return vector<string>();
}

Disk UdevDevice::ToDisk() {
  Disk disk;

  disk.set_is_auto_mountable(IsAutoMountable());
  disk.set_is_read_only(IsAttributeTrue(kAttributeReadOnly));
  disk.set_is_drive(HasAttribute(kAttributeRange));
  disk.set_is_rotational(HasProperty(kPropertyRotationRate));
  disk.set_is_hidden(IsHidden());
  disk.set_is_media_available(IsMediaAvailable());
  disk.set_is_on_boot_device(IsOnBootDevice());
  disk.set_is_on_removable_device(IsOnRemovableDevice());
  disk.set_is_virtual(IsVirtual());
  disk.set_media_type(GetDeviceMediaType());
  disk.set_filesystem_type(GetPropertyFromBlkId(kPropertyBlkIdFilesystemType));
  disk.set_native_path(NativePath());

  // Drive model and filesystem label may not be UTF-8 encoded, so we
  // need to ensure that they are either set to a valid UTF-8 string or
  // an empty string before later passed to a DBus message iterator.
  disk.set_drive_model(EnsureUTF8String(GetProperty(kPropertyModel)));
  disk.set_label(
      EnsureUTF8String(GetPropertyFromBlkId(kPropertyBlkIdFilesystemLabel)));

  string vendor_id, product_id;
  if (GetVendorAndProductId(&vendor_id, &product_id)) {
    disk.set_vendor_id(vendor_id);
    disk.set_product_id(product_id);

    string vendor_name, product_name;
    USBDeviceInfo info;
    if (info.GetVendorAndProductName(kUSBIdentifierDatabase,
                                     vendor_id, product_id,
                                     &vendor_name, &product_name)) {
      disk.set_vendor_name(EnsureUTF8String(vendor_name));
      disk.set_product_name(EnsureUTF8String(product_name));
    }
  }

  // TODO(benchan): Add a proper unit test when fixing crbug.com/221380.
  string uuid_hash = base::SHA1HashString(
      vendor_id + product_id + GetProperty(kPropertySerial) +
      GetPropertyFromBlkId(kPropertyBlkIdFilesystemUUID));
  disk.set_uuid(base::HexEncode(uuid_hash.data(), uuid_hash.size()));

  const char *dev_file = udev_device_get_devnode(dev_);
  if (dev_file)
    disk.set_device_file(dev_file);

  vector<string> mount_paths = GetMountPaths();
  disk.set_is_mounted(!mount_paths.empty());
  disk.set_mount_paths(mount_paths);

  uint64_t total_size, remaining_size;
  GetSizeInfo(&total_size, &remaining_size);
  disk.set_device_capacity(total_size);
  disk.set_bytes_remaining(remaining_size);

  return disk;
}

}  // namespace cros_disks
