// Copyright 2020 The Fuchsia 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 "src/storage/fshost/block-device-manager.h"

#include <fidl/fuchsia.device/cpp/markers.h>
#include <fidl/fuchsia.device/cpp/wire.h>
#include <inttypes.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/device/block.h>
#include <zircon/hw/gpt.h>

#include <set>
#include <utility>

#include "lib/fdio/directory.h"
#include "lib/fidl/llcpp/channel.h"
#include "lib/service/llcpp/service.h"
#include "src/lib/storage/fs_management/cpp/format.h"
#include "src/storage/fshost/block-device-interface.h"
#include "src/storage/fshost/constants.h"
#include "src/storage/fshost/copier.h"
#include "zircon/errors.h"

namespace fshost {
namespace {

// Setting for the maximum bytes to allow a partition to grow to.
struct PartitionLimit {
  // When unset, this limit will apply only to non-ramdisk devices. See
  // Config::kApplyLimitsToRamdisk.
  bool apply_to_ramdisk = false;

  // Partition max size in bytes, 0 means "no limit".
  uint64_t max_bytes = 0;
};

// Splits the path into a directory and the last component.
std::pair<std::string_view, std::string_view> SplitPath(std::string_view path) {
  size_t separator = path.rfind('/');
  if (separator != std::string::npos) {
    return std::make_pair(path.substr(0, separator), path.substr(separator + 1));
  }
  return std::make_pair(std::string_view(), path);
}

bool IsRamdisk(const BlockDeviceInterface& device) {
  constexpr std::string_view kRamdiskPrefix = "/dev/sys/platform/00:00:2d/ramctl/";
  return device.topological_path().compare(0, kRamdiskPrefix.length(), kRamdiskPrefix) == 0;
}

// Matches all NAND devices.
class NandMatcher : public BlockDeviceManager::Matcher {
 public:
  fs_management::DiskFormat Match(const BlockDeviceInterface& device) override {
    if (device.IsNand()) {
      return fs_management::kDiskFormatNandBroker;
    }
    return fs_management::kDiskFormatUnknown;
  }

  zx_status_t Add(BlockDeviceInterface& device) override {
    zx_status_t status = device.Add();
    if (status != ZX_OK) {
      return status;
    }
    if (path_.empty()) {
      path_ = device.topological_path();
    }
    return ZX_OK;
  }

  const std::string& path() const { return path_; }

 private:
  std::string path_;
};

// Matches anything that appears to have the given content and keeps track of the first device it
// finds.
class ContentMatcher : public BlockDeviceManager::Matcher {
 public:
  // If |allow_multiple| is true, multiple devices will be matched.  Otherwise, only the first
  // device that appears will match.
  ContentMatcher(fs_management::DiskFormat format, bool allow_multiple)
      : format_(format), allow_multiple_(allow_multiple) {}

  fs_management::DiskFormat Match(const BlockDeviceInterface& device) override {
    if (!allow_multiple_ && !path_.empty()) {
      // Only match the first occurrence.
      return fs_management::kDiskFormatUnknown;
    }
    if (device.content_format() == format_) {
      return format_;
    }
    return fs_management::kDiskFormatUnknown;
  }

  zx_status_t Add(BlockDeviceInterface& device) override {
    zx_status_t status = device.Add();
    if (status != ZX_OK) {
      return status;
    }
    if (path_.empty()) {
      path_ = device.topological_path();
    }
    return ZX_OK;
  }

  const std::string& path() const { return path_; }

 private:
  const fs_management::DiskFormat format_;
  const bool allow_multiple_;
  std::string path_;
};

// Matches devices that handle groups of partitions.
class PartitionMapMatcher : public ContentMatcher {
 public:
  // |suffix| is a device that is expected to appear when the driver is bound. For example, FVM,
  // will add a "/fvm" device before adding children whilst GPT won't add anything.  If
  // |ramdisk_required| is set, this matcher will only match against a ram-disk.
  PartitionMapMatcher(fs_management::DiskFormat format, bool allow_multiple,
                      std::string_view suffix, bool ramdisk_required)
      : ContentMatcher(format, allow_multiple),
        suffix_(suffix),
        ramdisk_required_(ramdisk_required) {}

  bool ramdisk_required() const { return ramdisk_required_; }

  fs_management::DiskFormat Match(const BlockDeviceInterface& device) override {
    if (ramdisk_required_ && !IsRamdisk(device)) {
      return fs_management::kDiskFormatUnknown;
    }
    return ContentMatcher::Match(device);
  }

  // Returns true if |device| is a child of the device matched by this matcher.
  bool IsChild(const BlockDeviceInterface& device) const {
    if (path().empty()) {
      return false;
    }
    // Child partitions should have topological paths of the form:
    //   .../<suffix>/<partition-name>/block
    auto [dir1, base1] = SplitPath(device.topological_path());
    if (base1 != "block") {
      return false;
    }
    auto [dir2, base2] = SplitPath(dir1);
    // base should be something like <partition-name>-p-1, but we ignore that.
    return path() + suffix_ == dir2;
  }

 private:
  const std::string suffix_;
  const bool ramdisk_required_;
};

// Extracts the path that the FVM driver responds to FIDL requests at given the PartitionMapMatcher
// for the path.
std::string GetFvmPathForPartitionMap(const PartitionMapMatcher& matcher) {
  return matcher.path() + "/fvm";
}

// Matches a partition with a given name and expected type GUID.
class SimpleMatcher : public BlockDeviceManager::Matcher {
 public:
  SimpleMatcher(PartitionMapMatcher& map, std::string partition_name,
                const fuchsia_hardware_block_partition::wire::Guid& type_guid,
                fs_management::DiskFormat format, PartitionLimit limit)
      : map_(map),
        partition_name_(std::move(partition_name)),
        type_guid_(type_guid),
        format_(format),
        limit_(limit) {}

  fs_management::DiskFormat Match(const BlockDeviceInterface& device) override {
    if (map_.IsChild(device) && device.partition_name() == partition_name_ &&
        !memcmp(&device.GetTypeGuid(), &type_guid_, sizeof(type_guid_))) {
      return format_;
    }
    return fs_management::kDiskFormatUnknown;
  }

  zx_status_t Add(BlockDeviceInterface& device) override {
    if (limit_.max_bytes) {
      if (limit_.apply_to_ramdisk || !IsRamdisk(device)) {
        // Set the max size for this partition in FVM. Ignore failures since the max size is
        // mostly a guard rail against bad behavior and we can still function.
        auto status =
            device.SetPartitionMaxSize(GetFvmPathForPartitionMap(map_), limit_.max_bytes);
        ZX_DEBUG_ASSERT(status == ZX_OK);
      }
    }
    return device.Add();
  }

 private:
  const PartitionMapMatcher& map_;
  const std::string partition_name_;
  const fuchsia_hardware_block_partition::wire::Guid type_guid_;
  const fs_management::DiskFormat format_;
  const PartitionLimit limit_;
};

constexpr std::string_view kZxcryptSuffix = "/zxcrypt/unsealed/block";

// Matches Fxfs partitions and manages migrations that may need to happen, e.g. removing zxcrypt
// from beneath Fxfs or migrating from a zxcrypt+minfs partition.
class FxfsMatcher : public BlockDeviceManager::Matcher {
 public:
  using PartitionNames = std::set<std::string, std::less<>>;

  FxfsMatcher(const PartitionMapMatcher& map, PartitionNames partition_names,
              const fuchsia_hardware_block_partition::wire::Guid& type_guid, PartitionLimit limit,
              bool format_on_corruption)
      : map_(map),
        partition_names_(std::move(partition_names)),
        type_guid_(type_guid),
        limit_(limit),
        format_on_corruption_(format_on_corruption) {}

  fs_management::DiskFormat Match(const BlockDeviceInterface& device) override {
    bool is_child =
        zxcrypt_parent_path_.empty()
            ? map_.IsChild(device)
            : device.topological_path() == zxcrypt_parent_path_ + std::string(kZxcryptSuffix);
    if (!is_child || memcmp(&device.GetTypeGuid(), &type_guid_, sizeof(type_guid_)) != 0 ||
        partition_names_.find(device.partition_name()) == partition_names_.end()) {
      return fs_management::kDiskFormatUnknown;
    }
    // We don't actually want to mount a zxcrypt-contained data partition, but we need to extract
    // any data stored therein (to support paving flows which currently only create zxcrypt+minfs
    // partitions).  When we find a zxcrypt-formatted data partition, we will bind it, pull the data
    // off, and then reformat to Fxfs (without zxcrypt).
    if (device.content_format() == fs_management::kDiskFormatZxcrypt) {
      if (!zxcrypt_parent_path_.empty()) {
        FX_LOGS(WARNING) << "Unexpectedly found nested zxcrypt devices.  Not proceeding.";
        return fs_management::kDiskFormatUnknown;
      }
      return fs_management::kDiskFormatZxcrypt;
    }
    return fs_management::kDiskFormatFxfs;
  }

  zx_status_t Add(BlockDeviceInterface& device) override {
    if (limit_.max_bytes) {
      if (limit_.apply_to_ramdisk || !IsRamdisk(device)) {
        // Set the max size for this partition in FVM. This is not persisted so we need to set it
        // every time on mount. Ignore failures since the max size is mostly a guard rail against
        // bad behavior and we can still function.
        auto status =
            device.SetPartitionMaxSize(GetFvmPathForPartitionMap(map_), limit_.max_bytes);
        ZX_DEBUG_ASSERT(status == ZX_OK);
      }
    }
    if (device.GetFormat() == fs_management::kDiskFormatZxcrypt) {
      // The channel needs to be cloned before Add is called, since BlockDevice::Add consumes the
      // device channel for zxcrypt.
      zxcrypt_parent_path_ = device.topological_path();
      return device.Add(format_on_corruption_);
    }
    if (zxcrypt_parent_path_.empty()) {
      return device.Add(format_on_corruption_);
    }
    // Copy the data out of the child device.
    FX_LOGS(INFO) << "Copying data out of " << device.topological_path();
    auto copier_or = device.ExtractData();
    Copier copied_data;
    if (copier_or.is_error()) {
      FX_LOGS(WARNING) << "Failed to copy data out from old partition: "
                       << copier_or.status_string() << ".  Reformatting.  Expect data loss!";
    } else {
      copied_data = std::move(*copier_or);
    }
    // Once we have done so, tear down the zxcrypt device so that we can use it for Fxfs.
    FX_LOGS(INFO) << "Shutting down zxcrypt...";
    auto controller_or = service::Connect<fuchsia_device::Controller>(zxcrypt_parent_path_.c_str());
    if (controller_or.is_error()) {
      FX_LOGS(ERROR) << "Failed to connect to zcxrypt: " << controller_or.status_string();
      return ZX_ERR_BAD_STATE;
    }
    auto resp = fidl::WireCall(*controller_or)->UnbindChildren();
    zx_status_t status = resp.status();
    if (status != ZX_OK) {
      FX_LOGS(WARNING) << "Failed to send UnbindChildren: " << zx_status_get_string(status);
      return ZX_ERR_BAD_STATE;
    }
    if (resp->is_error()) {
      FX_LOGS(WARNING) << "UnbindChildren failed: " << zx_status_get_string(resp->error_value());
      return ZX_ERR_BAD_STATE;
    }

    FX_LOGS(INFO) << "Shut down zxcrypt.  Re-adding device " << zxcrypt_parent_path_;
    auto parent_or = device.OpenBlockDevice(zxcrypt_parent_path_.c_str());
    if (parent_or.is_error()) {
      FX_LOGS(WARNING) << "Failed to open parent: " << parent_or.status_string();
      return ZX_ERR_BAD_STATE;
    }
    zxcrypt_parent_path_.clear();
    parent_or->AddData(std::move(copied_data));
    parent_or->SetFormat(fs_management::DiskFormat::kDiskFormatFxfs);
    return parent_or->Add();
  }

 private:
  const PartitionMapMatcher& map_;
  const PartitionNames partition_names_;
  const fuchsia_hardware_block_partition::wire::Guid type_guid_;
  const PartitionLimit limit_;
  const bool format_on_corruption_;

  // Set to the topological path of the block device containing zxcrypt once it's been bound.
  std::string zxcrypt_parent_path_;
};

// Matches a data partition, which is a mutable filesystem (e.g. minfs) optionally backed by
// zxcrypt.
// Note that Fxfs partitions are matched by FxfsMatcher.
class DataPartitionMatcher : public BlockDeviceManager::Matcher {
 public:
  using PartitionNames = std::set<std::string, std::less<>>;
  enum class ZxcryptVariant {
    // A regular data partition backed by zxcrypt.
    kNormal,
    // A data partition not backed by zxcrypt.
    kNoZxcrypt,
    // Only attach and unseal the zxcrypt partition; doesn't mount the filesystem.
    kZxcryptOnly
  };

  struct Variant {
    ZxcryptVariant zxcrypt = ZxcryptVariant::kNormal;
    fs_management::DiskFormat format = fs_management::kDiskFormatMinfs;
    bool format_data_on_corruption = true;
  };

  DataPartitionMatcher(const PartitionMapMatcher& map, PartitionNames partition_names,
                       std::string_view preferred_name,
                       const fuchsia_hardware_block_partition::wire::Guid& type_guid,
                       Variant variant, PartitionLimit limit)
      : map_(map),
        partition_names_(std::move(partition_names)),
        preferred_name_(preferred_name),
        type_guid_(type_guid),
        variant_(variant),
        limit_(limit) {}

  static Variant GetVariantFromConfig(const fshost_config::Config& config) {
    Variant variant;
    if (config.no_zxcrypt()) {
      variant.zxcrypt = ZxcryptVariant::kNoZxcrypt;
    } else {
      variant.zxcrypt = ZxcryptVariant::kNormal;
    }

    if (!config.data_filesystem_format().empty())
      variant.format = fs_management::DiskFormatFromString(config.data_filesystem_format());

    variant.format_data_on_corruption = config.format_data_on_corruption();
    return variant;
  }

  fs_management::DiskFormat Match(const BlockDeviceInterface& device) override {
    if (expected_inner_path_.empty()) {
      if (map_.IsChild(device) && !memcmp(&device.GetTypeGuid(), &type_guid_, sizeof(type_guid_))) {
        if (partition_names_.find(device.partition_name()) == partition_names_.end()) {
          FX_LOGS(INFO) << "Ignoring data partition with label '" << device.partition_name() << "'";
          return fs_management::kDiskFormatUnknown;
        }
        switch (variant_.zxcrypt) {
          case ZxcryptVariant::kNormal:
            return map_.ramdisk_required() ? variant_.format : fs_management::kDiskFormatZxcrypt;
          case ZxcryptVariant::kNoZxcrypt:
            return variant_.format;
          case ZxcryptVariant::kZxcryptOnly:
            return fs_management::kDiskFormatZxcrypt;
        }
      }
    } else if (variant_.zxcrypt == ZxcryptVariant::kNormal &&
               device.topological_path() == expected_inner_path_ &&
               !memcmp(&device.GetTypeGuid(), &type_guid_, sizeof(type_guid_))) {
      return variant_.format;
    }
    return fs_management::kDiskFormatUnknown;
  }

  zx_status_t Add(BlockDeviceInterface& device) override {
    if (limit_.max_bytes) {
      if (limit_.apply_to_ramdisk || !IsRamdisk(device)) {
        // Set the max size for this partition in FVM. This is not persisted so we need to set it
        // every time on mount. Ignore failures since the max size is mostly a guard rail against
        // bad behavior and we can still function.
        auto status =
            device.SetPartitionMaxSize(GetFvmPathForPartitionMap(map_), limit_.max_bytes);
        ZX_DEBUG_ASSERT(status == ZX_OK);
      }
    }

    if (expected_inner_path_.empty() && !preferred_name_.empty() &&
        device.partition_name() != preferred_name_) {
      if (zx_status_t status =
              device.SetPartitionName(GetFvmPathForPartitionMap(map_), preferred_name_);
          status != ZX_OK) {
        FX_LOGS(ERROR) << "Failed to change data partition name to '" << preferred_name_
                       << "': " << zx_status_get_string(status);
        // Continue since not fatal...
      } else {
        FX_LOGS(INFO) << "Changed data partition name to '" << preferred_name_ << "'";
      }
    }

    // If the volume doesn't appear to be zxcrypt, assume that it's because it was never formatted
    // as such, or the keys have been shredded, so skip straight to reformatting.  Strictly
    // speaking, it's not necessary, because attempting to unseal should trigger the same
    // behaviour, but the log messages in that case are scary.
    if (device.GetFormat() == fs_management::kDiskFormatZxcrypt) {
      if (device.content_format() != fs_management::kDiskFormatZxcrypt) {
        FX_LOGS(INFO) << "Formatting as zxcrypt partition";
        zx_status_t status = device.FormatZxcrypt();
        if (status != ZX_OK) {
          return status;
        }
        // Set the reformat_ flag so that when the Minfs device appears we can skip straight to
        // reformatting it (and skip any fsck).  Again, this isn't strictly required because
        // mounting should fail and we'll reformat, but we can skip that when we know we need to
        // reformat.
        reformat_ = true;
      }
    } else if (reformat_) {
      // We formatted zxcrypt, so skip straight to formatting the filesystem.
      zx_status_t status = device.FormatFilesystem();
      if (status != ZX_OK) {
        return status;
      }
      reformat_ = false;
    }
    zx_status_t status = device.Add(variant_.format_data_on_corruption);
    if (status != ZX_OK) {
      return status;
    }
    if (device.GetFormat() == fs_management::kDiskFormatZxcrypt) {
      expected_inner_path_ = device.topological_path();
      expected_inner_path_.append(kZxcryptSuffix);
    }
    return ZX_OK;
  }

 private:
  const PartitionMapMatcher& map_;
  const PartitionNames partition_names_;
  const std::string preferred_name_;
  const fuchsia_hardware_block_partition::wire::Guid type_guid_;
  const Variant variant_;
  const PartitionLimit limit_;

  // Once we have matched a zxcrypt partition, this field will be set to the expected topological
  // path of the child device, which will then be matched against directly.
  std::string expected_inner_path_;
  // If we reformat the zxcrypt device, this flag is set so that we know we should reformat the
  // minfs device when it appears.
  bool reformat_ = false;
};

// Matches the factory partition.
class FactoryfsMatcher : public BlockDeviceManager::Matcher {
 public:
  static constexpr std::string_view kVerityMutableSuffix = "/verity/mutable/block";
  static constexpr std::string_view kVerityVerifiedSuffix = "/verity/verified/block";

  explicit FactoryfsMatcher(const PartitionMapMatcher& map) : map_(map) {}

  fs_management::DiskFormat Match(const BlockDeviceInterface& device) override {
    static constexpr fuchsia_hardware_block_partition::wire::Guid factory_type_guid =
        GPT_FACTORY_TYPE_GUID;
    if (base_path_.empty()) {
      if (map_.IsChild(device) &&
          !memcmp(&device.GetTypeGuid(), &factory_type_guid, sizeof(factory_type_guid)) &&
          device.partition_name() == "factory") {
        return fs_management::kDiskFormatBlockVerity;
      }
    } else if (!memcmp(&device.GetTypeGuid(), &factory_type_guid, sizeof(factory_type_guid)) &&
               (device.topological_path() == std::string(base_path_).append(kVerityMutableSuffix) ||
                device.topological_path() ==
                    std::string(base_path_).append(kVerityVerifiedSuffix))) {
      return fs_management::kDiskFormatFactoryfs;
    }
    return fs_management::kDiskFormatUnknown;
  }

  zx_status_t Add(BlockDeviceInterface& device) override {
    zx_status_t status = device.Add();
    if (status != ZX_OK) {
      return status;
    }
    base_path_ = device.topological_path();
    return ZX_OK;
  }

 private:
  const PartitionMapMatcher& map_;
  std::string base_path_;
};

// Matches devices that report flags with BLOCK_FLAG_BOOTPART set.
class BootpartMatcher : public BlockDeviceManager::Matcher {
 public:
  fs_management::DiskFormat Match(const BlockDeviceInterface& device) override {
    fuchsia_hardware_block_BlockInfo info;
    zx_status_t status = device.GetInfo(&info);
    if (status != ZX_OK) {
      return fs_management::kDiskFormatUnknown;
    }
    return info.flags & BLOCK_FLAG_BOOTPART ? fs_management::kDiskFormatBootpart
                                            : fs_management::kDiskFormatUnknown;
  }
};

DataPartitionMatcher::PartitionNames GetDataPartitionNames(bool include_legacy) {
  if (include_legacy) {
    return {std::string(kDataPartitionLabel), "minfs", "fuchsia-data"};
  }
  return {std::string(kDataPartitionLabel)};
}

}  // namespace

BlockDeviceManager::BlockDeviceManager(const fshost_config::Config* config) : config_(*config) {
  static constexpr fuchsia_hardware_block_partition::wire::Guid data_type_guid = GUID_DATA_VALUE;

  if (config_.bootpart()) {
    matchers_.push_back(std::make_unique<BootpartMatcher>());
  }
  if (config_.nand()) {
    matchers_.push_back(std::make_unique<NandMatcher>());
  }

  auto gpt =
      std::make_unique<PartitionMapMatcher>(fs_management::kDiskFormatGpt, config_.gpt_all(), "",
                                            /*ramdisk_required=*/false);
  auto fvm = std::make_unique<PartitionMapMatcher>(
      fs_management::kDiskFormatFvm, /*allow_multiple=*/false, "/fvm", config_.fvm_ramdisk());

  bool gpt_required = config_.gpt() || config_.gpt_all();
  bool fvm_required = config_.fvm();

  // Maximum partition limits. The limits only apply to physical devices (not ramdisks) unless
  // apply_limits_to_ramdisk is set.
  PartitionLimit blobfs_limit{.apply_to_ramdisk = config_.apply_limits_to_ramdisk(),
                              .max_bytes = config_.blobfs_max_bytes()};
  PartitionLimit data_limit{.apply_to_ramdisk = config_.apply_limits_to_ramdisk(),
                            .max_bytes = config_.data_max_bytes()};

  if (!config_.netboot()) {
    // GPT partitions:
    if (config_.durable()) {
      static constexpr fuchsia_hardware_block_partition::wire::Guid durable_type_guid =
          GPT_DURABLE_TYPE_GUID;
      matchers_.push_back(std::make_unique<DataPartitionMatcher>(
          *gpt, DataPartitionMatcher::PartitionNames{GPT_DURABLE_NAME}, std::string_view(),
          durable_type_guid, DataPartitionMatcher::GetVariantFromConfig(config_),
          PartitionLimit()));
      gpt_required = true;
    }
    if (config_.factory()) {
      matchers_.push_back(std::make_unique<FactoryfsMatcher>(*gpt));
      gpt_required = true;
    }

    // FVM partitions:
    if (config_.blobfs()) {
      static constexpr fuchsia_hardware_block_partition::wire::Guid blobfs_type_guid =
          GUID_BLOB_VALUE;
      matchers_.push_back(std::make_unique<SimpleMatcher>(
          *fvm, std::string(kBlobfsPartitionLabel), blobfs_type_guid,
          fs_management::kDiskFormatBlobfs, blobfs_limit));
      fvm_required = true;
    }
    if (config_.data()) {
      if (config_.data_filesystem_format() == "fxfs") {
        matchers_.push_back(std::make_unique<FxfsMatcher>(
            *fvm, GetDataPartitionNames(config_.allow_legacy_data_partition_names()),
            data_type_guid, data_limit, config_.format_data_on_corruption()));
      } else {
        matchers_.push_back(std::make_unique<DataPartitionMatcher>(
            *fvm, GetDataPartitionNames(config_.allow_legacy_data_partition_names()),
            kDataPartitionLabel, data_type_guid,
            DataPartitionMatcher::GetVariantFromConfig(config_), data_limit));
      }
      fvm_required = true;
    }
  }

  // The partition map matchers go last because they match on content.
  if (fvm_required) {
    std::unique_ptr<PartitionMapMatcher> non_ramdisk_fvm;
    if (config_.fvm_ramdisk()) {
      // Add another matcher for the non-ramdisk version of FVM.
      non_ramdisk_fvm = std::make_unique<PartitionMapMatcher>(fs_management::kDiskFormatFvm,
                                                              /*allow_multiple=*/false, "/fvm",
                                                              /*ramdisk_required=*/false);

      if (config_.zxcrypt_non_ramdisk()) {
        matchers_.push_back(std::make_unique<DataPartitionMatcher>(
            *non_ramdisk_fvm, GetDataPartitionNames(config_.allow_legacy_data_partition_names()),
            kDataPartitionLabel, data_type_guid,
            DataPartitionMatcher::Variant{.zxcrypt =
                                              DataPartitionMatcher::ZxcryptVariant::kZxcryptOnly},
            data_limit));
      }
    }
    matchers_.push_back(std::move(fvm));
    if (non_ramdisk_fvm) {
      matchers_.push_back(std::move(non_ramdisk_fvm));
    }
  }
  if (gpt_required) {
    matchers_.push_back(std::move(gpt));
  }
  if (config_.mbr()) {
    // Default to allowing multiple devices because mbr support is disabled by default and if
    // it's enabled, it's likely required for removable devices and so supporting multiple
    // devices is probably appropriate.
    matchers_.push_back(std::make_unique<PartitionMapMatcher>(fs_management::kDiskFormatMbr,
                                                              /*allow_multiple=*/true, "",
                                                              /*ramdisk_required=*/false));
  }
}

zx_status_t BlockDeviceManager::AddDevice(BlockDeviceInterface& device) {
  if (device.topological_path().empty()) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  FX_LOGS(INFO) << "Device " << device.topological_path() << " has content format "
                << fs_management::DiskFormatString(device.content_format());
  for (auto& matcher : matchers_) {
    fs_management::DiskFormat format = matcher->Match(device);
    if (format != fs_management::kDiskFormatUnknown) {
      FX_LOGS(INFO) << "Device " << device.topological_path() << " matched format "
                    << fs_management::DiskFormatString(format);
      device.SetFormat(format);
      return matcher->Add(device);
    }
  }
  return ZX_ERR_NOT_SUPPORTED;
}

}  // namespace fshost
