// Copyright 2017 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 "block-device.h"

#include <fcntl.h>
#include <fuchsia/device/c/fidl.h>
#include <fuchsia/device/llcpp/fidl.h>
#include <fuchsia/hardware/block/c/fidl.h>
#include <fuchsia/hardware/block/partition/c/fidl.h>
#include <fuchsia/hardware/block/partition/llcpp/fidl.h>
#include <fuchsia/hardware/block/volume/c/fidl.h>
#include <inttypes.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/unsafe.h>
#include <lib/fdio/watcher.h>
#include <lib/fzl/time.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/channel.h>
#include <lib/zx/status.h>
#include <lib/zx/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/device/block.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include <utility>

#include <fbl/algorithm.h>
#include <fbl/auto_call.h>
#include <fbl/string_buffer.h>
#include <fbl/unique_fd.h>
#include <fs-management/format.h>
#include <fs-management/mount.h>
#include <gpt/gpt.h>

#include "block-watcher.h"
#include "encrypted-volume.h"
#include "extract-metadata.h"
#include "pkgfs-launcher.h"
#include "src/devices/block/drivers/block-verity/verified-volume-client.h"
#include "src/storage/minfs/fsck.h"
#include "src/storage/minfs/minfs.h"

namespace devmgr {
namespace {

const char kAllowAuthoringFactoryConfigFile[] = "/boot/config/allow-authoring-factory";

// Attempt to mount the device pointed to be the file descriptor at a known
// location.
//
// Returns ZX_ERR_ALREADY_BOUND if the device could be mounted, but something
// is already mounted at that location. Returns ZX_ERR_INVALID_ARGS if the
// GUID of the device does not match a known valid one. Returns
// ZX_ERR_NOT_SUPPORTED if the GUID is a system GUID. Returns ZX_OK if an
// attempt to mount is made, without checking mount success.
zx_status_t MountMinfs(FilesystemMounter* mounter, zx::channel block_device,
                       mount_options_t* options) {
  fuchsia_hardware_block_partition_GUID type_guid;
  zx_status_t io_status, status;
  io_status = fuchsia_hardware_block_partition_PartitionGetTypeGuid(block_device.get(), &status,
                                                                    &type_guid);
  if (io_status != ZX_OK) {
    return io_status;
  }
  if (status != ZX_OK) {
    return status;
  }

  if (gpt_is_sys_guid(type_guid.value, GPT_GUID_LEN)) {
    return ZX_ERR_NOT_SUPPORTED;
  } else if (gpt_is_data_guid(type_guid.value, GPT_GUID_LEN)) {
    return mounter->MountData(std::move(block_device), *options);
  } else if (gpt_is_install_guid(type_guid.value, GPT_GUID_LEN)) {
    options->readonly = true;
    return mounter->MountInstall(std::move(block_device), *options);
  } else if (gpt_is_durable_guid(type_guid.value, GPT_GUID_LEN)) {
    return mounter->MountDurable(std::move(block_device), *options);
  }
  FX_LOGS(ERROR) << "Unrecognized partition GUID for minfs; not mounting";
  return ZX_ERR_WRONG_TYPE;
}

// return value is ignored
int UnsealZxcryptThread(void* arg) {
  std::unique_ptr<int> fd_ptr(static_cast<int*>(arg));
  fbl::unique_fd fd(*fd_ptr);
  fbl::unique_fd devfs_root(open("/dev", O_RDONLY));
  EncryptedVolume volume(std::move(fd), std::move(devfs_root));
  volume.EnsureUnsealedAndFormatIfNeeded();
  return 0;
}

// Holds thread state for OpenVerityDeviceThread
struct VerityDeviceThreadState {
  fbl::unique_fd fd;
  digest::Digest seal;
};

// return value is ignored
int OpenVerityDeviceThread(void* arg) {
  std::unique_ptr<VerityDeviceThreadState> state(static_cast<VerityDeviceThreadState*>(arg));
  fbl::unique_fd devfs_root(open("/dev", O_RDONLY));

  std::unique_ptr<block_verity::VerifiedVolumeClient> vvc;
  zx_status_t status = block_verity::VerifiedVolumeClient::CreateFromBlockDevice(
      state->fd.get(), std::move(devfs_root),
      block_verity::VerifiedVolumeClient::Disposition::kDriverAlreadyBound, zx::sec(5), &vvc);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Couldn't create VerifiedVolumeClient: " << zx_status_get_string(status);
    return 1;
  }

  fbl::unique_fd inner_block_fd;
  status = vvc->OpenForVerifiedRead(std::move(state->seal), zx::sec(5), inner_block_fd);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "OpenForVerifiedRead failed: " << zx_status_get_string(status);
    return 1;
  }
  return 0;
}

std::string GetTopologicalPath(int fd) {
  fdio_cpp::UnownedFdioCaller disk_connection(fd);
  auto resp = llcpp::fuchsia::device::Controller::Call::GetTopologicalPath(
      zx::unowned_channel(disk_connection.borrow_channel()));
  if (resp.status() != ZX_OK) {
    FX_LOGS(WARNING) << "Unable to get topological path (fidl error): "
                     << zx_status_get_string(resp.status());
    return {};
  }
  if (resp->result.is_err()) {
    FX_LOGS(WARNING) << "Unable to get topological path: "
                     << zx_status_get_string(resp->result.err());
    return {};
  }
  const auto& path = resp->result.response().path;
  return {path.data(), path.size()};
}

}  // namespace

BlockDevice::BlockDevice(FilesystemMounter* mounter, fbl::unique_fd fd, const Config* device_config)
    : mounter_(mounter),
      fd_(std::move(fd)),
      device_config_(device_config),
      topological_path_(GetTopologicalPath(fd_.get())) {}

disk_format_t BlockDevice::content_format() const {
  if (content_format_) {
    return *content_format_;
  }
  content_format_ = detect_disk_format(fd_.get());
  return *content_format_;
}

disk_format_t BlockDevice::GetFormat() { return format_; }

void BlockDevice::SetFormat(disk_format_t format) { format_ = format; }

const std::string& BlockDevice::partition_name() const {
  if (!partition_name_.empty()) {
    return partition_name_;
  }
  // The block device might not support the partition protocol in which case the connection will be
  // closed, so clone the channel in case that happens.
  fdio_cpp::UnownedFdioCaller connection(fd_.get());
  zx::channel channel(fdio_service_clone(connection.borrow_channel()));
  auto resp =
      llcpp::fuchsia::hardware::block::partition::Partition::Call::GetName(channel.borrow());
  if (resp.status() != ZX_OK) {
    FX_LOGS(ERROR) << "Unable to get partiton name (fidl error): "
                   << zx_status_get_string(resp.status());
    return partition_name_;
  }
  if (resp->status != ZX_OK) {
    FX_LOGS(ERROR) << "Unable to get partiton name: " << zx_status_get_string(resp->status);
    return partition_name_;
  }
  partition_name_ = std::string(resp->name.data(), resp->name.size());
  return partition_name_;
}

zx_status_t BlockDevice::GetInfo(fuchsia_hardware_block_BlockInfo* out_info) const {
  if (info_.has_value()) {
    memcpy(out_info, &*info_, sizeof(*out_info));
    return ZX_OK;
  }
  fdio_cpp::UnownedFdioCaller connection(fd_.get());
  zx_status_t io_status, call_status;
  io_status =
      fuchsia_hardware_block_BlockGetInfo(connection.borrow_channel(), &call_status, out_info);
  if (io_status != ZX_OK) {
    return io_status;
  }
  info_ = *out_info;
  return call_status;
}

const fuchsia_hardware_block_partition_GUID& BlockDevice::GetInstanceGuid() const {
  if (instance_guid_) {
    return *instance_guid_;
  }
  instance_guid_.emplace();
  fdio_cpp::UnownedFdioCaller connection(fd_.get());
  // The block device might not support the partition protocol in which case the connection will be
  // closed, so clone the channel in case that happens.
  zx::channel channel(fdio_service_clone(connection.borrow_channel()));
  zx_status_t io_status, call_status;
  io_status = fuchsia_hardware_block_partition_PartitionGetInstanceGuid(channel.get(), &call_status,
                                                                        &instance_guid_.value());
  if (io_status != ZX_OK) {
    FX_LOGS(ERROR) << "Unable to get partition instance GUID (fidl error)";
  } else if (call_status != ZX_OK) {
    FX_LOGS(ERROR) << "Unable to get partition instance GUID";
  }
  return *instance_guid_;
}

const fuchsia_hardware_block_partition_GUID& BlockDevice::GetTypeGuid() const {
  if (type_guid_) {
    return *type_guid_;
  }
  type_guid_.emplace();
  fdio_cpp::UnownedFdioCaller connection(fd_.get());
  // The block device might not support the partition protocol in which case the connection will be
  // closed, so clone the channel in case that happens.
  zx::channel channel(fdio_service_clone(connection.borrow_channel()));
  zx_status_t io_status, call_status;
  io_status = fuchsia_hardware_block_partition_PartitionGetTypeGuid(channel.get(), &call_status,
                                                                    &type_guid_.value());
  if (io_status != ZX_OK) {
    FX_LOGS(ERROR) << "Unable to get partition type GUID (fidl error)";
  } else if (call_status != ZX_OK) {
    FX_LOGS(ERROR) << "Unable to get partition type GUID";
  }
  return *type_guid_;
}

zx_status_t BlockDevice::AttachDriver(const std::string_view& driver) {
  FX_LOGS(INFO) << "Binding: " << driver;
  fdio_cpp::UnownedFdioCaller connection(fd_.get());
  zx_status_t call_status = ZX_OK;
  auto resp = ::llcpp::fuchsia::device::Controller::Call::Bind(
      zx::unowned_channel(connection.borrow_channel()),
      ::fidl::unowned_str(driver.data(), driver.length()));
  zx_status_t io_status = resp.status();
  if (io_status != ZX_OK) {
    return io_status;
  }
  if (resp->result.is_err()) {
    call_status = resp->result.err();
  }
  return call_status;
}

zx_status_t BlockDevice::UnsealZxcrypt() {
  FX_LOGS(INFO) << "unsealing zxcrypt";
  // Bind and unseal the driver from a separate thread, since we
  // have to wait for a number of devices to do I/O and settle,
  // and we don't want to block block-watcher for any nontrivial
  // length of time.

  // We transfer fd to the spawned thread.  Since it's UB to cast
  // ints to pointers and back, we allocate the fd on the heap.
  int loose_fd = fd_.release();
  int* raw_fd_ptr = new int(loose_fd);
  thrd_t th;
  int err = thrd_create_with_name(&th, &UnsealZxcryptThread, raw_fd_ptr, "zxcrypt-unseal");
  if (err != thrd_success) {
    FX_LOGS(ERROR) << "failed to spawn zxcrypt worker thread";
    close(loose_fd);
    delete raw_fd_ptr;
    return ZX_ERR_INTERNAL;
  } else {
    thrd_detach(th);
  }
  return ZX_OK;
}

zx_status_t BlockDevice::OpenBlockVerityForVerifiedRead(std::string seal_hex) {
  FX_LOGS(INFO) << "preparing block-verity";

  std::unique_ptr<VerityDeviceThreadState> state = std::make_unique<VerityDeviceThreadState>();
  zx_status_t rc = state->seal.Parse(seal_hex.c_str());
  if (rc != ZX_OK) {
    FX_LOGS(ERROR) << "block-verity seal " << seal_hex
                   << " did not parse as SHA256 hex digest: " << zx_status_get_string(rc);
    return rc;
  }

  // Transfer FD to thread state.
  state->fd = std::move(fd_);

  thrd_t th;
  int err = thrd_create_with_name(&th, OpenVerityDeviceThread, state.get(), "block-verity-open");
  if (err != thrd_success) {
    FX_LOGS(ERROR) << "failed to spawn block-verity worker thread";
    return ZX_ERR_INTERNAL;
  } else {
    // Release our reference to the state now owned by the other thread.
    state.release();
    thrd_detach(th);
  }

  return ZX_OK;
}

zx_status_t BlockDevice::FormatZxcrypt() {
  fbl::unique_fd devfs_root_fd(open("/dev", O_RDONLY));
  if (!devfs_root_fd) {
    return ZX_ERR_NOT_FOUND;
  }
  EncryptedVolume volume(fd_.duplicate(), std::move(devfs_root_fd));
  return volume.Format();
}

zx::status<std::string> BlockDevice::VeritySeal() {
  return mounter_->boot_args()->block_verity_seal();
}

bool BlockDevice::ShouldAllowAuthoringFactory() {
  // Checks for presence of /boot/config/allow-authoring-factory
  fbl::unique_fd allow_authoring_factory_fd(open(kAllowAuthoringFactoryConfigFile, O_RDONLY));
  return allow_authoring_factory_fd.is_valid();
}

zx_status_t BlockDevice::SetPartitionMaxSize(const std::string& fvm_path, uint64_t max_size) {
  // Get the partition GUID for talking to FVM.
  const fuchsia_hardware_block_partition_GUID& instance_guid = GetInstanceGuid();
  if (std::all_of(std::begin(instance_guid.value), std::end(instance_guid.value),
                  [](auto val) { return val == 0; }))
    return ZX_ERR_NOT_SUPPORTED;  // Not a partition, nothing to do.

  fbl::unique_fd fvm_fd(open(fvm_path.c_str(), O_RDONLY));
  if (!fvm_fd)
    return ZX_ERR_NOT_SUPPORTED;  // Not in FVM, nothing to do.

  // Actually set the limit.
  fdio_cpp::UnownedFdioCaller caller(fvm_fd.get());
  zx_status_t set_status;
  if (zx_status_t fidl_status = fuchsia_hardware_block_volume_VolumeManagerSetPartitionLimit(
          caller.channel()->get(), &instance_guid, max_size, &set_status);
      fidl_status != ZX_OK || set_status != ZX_OK) {
    FX_LOGS(ERROR) << "Unable to set partition limit for " << topological_path() << " to "
                   << max_size << " bytes";
    return fidl_status != ZX_OK ? fidl_status : set_status;
  }

  return ZX_OK;
}

bool BlockDevice::ShouldCheckFilesystems() { return mounter_->ShouldCheckFilesystems(); }

zx_status_t BlockDevice::CheckFilesystem() {
  if (!ShouldCheckFilesystems()) {
    return ZX_OK;
  }

  zx_status_t status;
  fuchsia_hardware_block_BlockInfo info;
  if ((status = GetInfo(&info)) != ZX_OK) {
    return status;
  }

  switch (format_) {
    case DISK_FORMAT_BLOBFS: {
      FX_LOGS(INFO) << "Skipping blobfs consistency checker.";
      return ZX_OK;
    }

    case DISK_FORMAT_FACTORYFS: {
      FX_LOGS(INFO) << "Skipping factory consistency checker.";
      return ZX_OK;
    }

    case DISK_FORMAT_MINFS: {
      zx::ticks before = zx::ticks::now();
      auto timer = fbl::MakeAutoCall([before]() {
        auto after = zx::ticks::now();
        auto duration = fzl::TicksToNs(after - before);
        FX_LOGS(INFO) << "fsck took " << duration.to_secs() << "." << duration.to_msecs() % 1000
                      << " seconds";
      });
      FX_LOGS(INFO) << "fsck of " << disk_format_string_[format_] << " started";
      uint64_t device_size = info.block_size * info.block_count / minfs::kMinfsBlockSize;
      std::unique_ptr<block_client::BlockDevice> device;
      zx_status_t status = minfs::FdToBlockDevice(fd_, &device);
      if (status != ZX_OK) {
        FX_LOGS(ERROR) << "Cannot convert fd to block device: " << status;
        return status;
      }
      std::unique_ptr<minfs::Bcache> bc;
      status = minfs::Bcache::Create(std::move(device), static_cast<uint32_t>(device_size), &bc);
      if (status != ZX_OK) {
        FX_LOGS(ERROR) << "Could not initialize minfs bcache.";
        return status;
      }
      status = minfs::Fsck(std::move(bc), minfs::FsckOptions{.repair = true});

      if (status != ZX_OK) {
        mounter_->mutable_metrics()->LogMinfsCorruption();
        mounter_->FlushMetrics();
        FX_LOGS(ERROR) << "\n--------------------------------------------------------------\n"
                          "|\n"
                          "|   WARNING: fshost fsck failure!\n"
                          "|   Corrupt "
                       << disk_format_string_[format_]
                       << " filesystem\n"
                          "|\n"
                          "|   If your system was shutdown cleanly (via 'dm poweroff'\n"
                          "|   or an OTA), report this device to the local-storage\n"
                          "|   team. Please file bugs with logs before and after reboot.\n"
                          "|\n"
                          "--------------------------------------------------------------";
        MaybeDumpMetadata(fd_.duplicate(), {.disk_format = DISK_FORMAT_MINFS});
      } else {
        FX_LOGS(INFO) << "fsck of " << disk_format_string_[format_] << " completed OK";
      }
      return status;
    }
    default:
      FX_LOGS(ERROR) << "Not checking unknown filesystem";
      return ZX_ERR_NOT_SUPPORTED;
  }
}

zx_status_t BlockDevice::FormatFilesystem() {
  zx_status_t status;
  fuchsia_hardware_block_BlockInfo info;
  if ((status = GetInfo(&info)) != ZX_OK) {
    return status;
  }

  switch (format_) {
    case DISK_FORMAT_BLOBFS: {
      FX_LOGS(ERROR) << "Not formatting blobfs.";
      return ZX_ERR_NOT_SUPPORTED;
    }
    case DISK_FORMAT_FACTORYFS: {
      FX_LOGS(ERROR) << "Not formatting factoryfs.";
      return ZX_ERR_NOT_SUPPORTED;
    }
    case DISK_FORMAT_MINFS: {
      FX_LOGS(INFO) << "Formatting minfs.";
      uint64_t blocks = info.block_size * info.block_count / minfs::kMinfsBlockSize;
      std::unique_ptr<block_client::BlockDevice> device;
      zx_status_t status = minfs::FdToBlockDevice(fd_, &device);
      if (status != ZX_OK) {
        FX_LOGS(ERROR) << "Cannot convert fd to block device: " << status;
        return status;
      }
      std::unique_ptr<minfs::Bcache> bc;
      status = minfs::Bcache::Create(std::move(device), static_cast<uint32_t>(blocks), &bc);
      if (status != ZX_OK) {
        FX_LOGS(ERROR) << "Could not initialize minfs bcache.";
        return status;
      }
      minfs::MountOptions options = {};
      if ((status = minfs::Mkfs(options, bc.get())) != ZX_OK) {
        FX_LOGS(ERROR) << "Could not format minfs filesystem.";
        return status;
      }
      FX_LOGS(INFO) << "Minfs filesystem re-formatted. Expect data loss.";
      return ZX_OK;
    }
    default:
      FX_LOGS(ERROR) << "Not formatting unknown filesystem.";
      return ZX_ERR_NOT_SUPPORTED;
  }
}

zx_status_t BlockDevice::MountFilesystem() {
  if (!fd_) {
    return ZX_ERR_BAD_HANDLE;
  }
  zx::channel block_device;
  {
    fdio_cpp::UnownedFdioCaller disk_connection(fd_.get());
    zx::unowned_channel channel(disk_connection.borrow_channel());
    block_device.reset(fdio_service_clone(channel->get()));
  }
  switch (format_) {
    case DISK_FORMAT_FACTORYFS: {
      FX_LOGS(INFO) << "BlockDevice::MountFilesystem(factoryfs)";
      mount_options_t options = default_mount_options;
      options.collect_metrics = false;
      options.readonly = true;

      zx_status_t status = mounter_->MountFactoryFs(std::move(block_device), options);
      if (status != ZX_OK) {
        FX_LOGS(ERROR) << "Failed to mount factoryfs partition: " << zx_status_get_string(status)
                       << ".";
      }
      return status;
    }
    case DISK_FORMAT_BLOBFS: {
      FX_LOGS(INFO) << "BlockDevice::MountFilesystem(blobfs)";
      mount_options_t options = default_mount_options;
      options.collect_metrics = true;
      std::optional<std::string> algorithm = std::nullopt;
      std::optional<std::string> eviction_policy = std::nullopt;
      if (mounter_->boot_args()) {
        algorithm = mounter_->boot_args()->blobfs_write_compression_algorithm();
        if (algorithm == "ZSTD" || algorithm == "ZSTD_SEEKABLE") {
          // These two algorithms are deprecated.
          FX_LOGS(INFO) << "Ignoring " << *algorithm << " algorithm";
          algorithm = std::nullopt;
        }
        eviction_policy = mounter_->boot_args()->blobfs_eviction_policy();
      }
      options.write_compression_algorithm = algorithm ? algorithm->c_str() : nullptr;
      options.cache_eviction_policy = eviction_policy ? eviction_policy->c_str() : nullptr;
      if (device_config_->is_set(Config::kSandboxDecompression)) {
        options.sandbox_decompression = true;
      }
      zx_status_t status = mounter_->MountBlob(std::move(block_device), options);
      if (status != ZX_OK) {
        FX_LOGS(ERROR) << "Failed to mount blobfs partition: " << zx_status_get_string(status)
                       << ".";
        return status;
      }
      mounter_->TryMountPkgfs();
      return ZX_OK;
    }
    case DISK_FORMAT_MINFS: {
      mount_options_t options = default_mount_options;
      FX_LOGS(INFO) << "BlockDevice::MountFilesystem(minfs)";
      zx_status_t status = MountMinfs(mounter_, std::move(block_device), &options);
      if (status != ZX_OK) {
        FX_LOGS(ERROR) << "Failed to mount minfs partition: " << zx_status_get_string(status)
                       << ".";
        MaybeDumpMetadata(fd_.duplicate(), {.disk_format = DISK_FORMAT_MINFS});
        return status;
      }
      mounter_->TryMountPkgfs();
      return ZX_OK;
    }
    default:
      FX_LOGS(ERROR) << "BlockDevice::MountFilesystem(unknown)";
      return ZX_ERR_NOT_SUPPORTED;
  }
}

zx_status_t BlockDeviceInterface::Add(bool format_on_corruption) {
  switch (GetFormat()) {
    case DISK_FORMAT_BOOTPART: {
      return AttachDriver(kBootpartDriverPath);
    }
    case DISK_FORMAT_GPT: {
      return AttachDriver(kGPTDriverPath);
    }
    case DISK_FORMAT_FVM: {
      return AttachDriver(kFVMDriverPath);
    }
    case DISK_FORMAT_MBR: {
      return AttachDriver(kMBRDriverPath);
    }
    case DISK_FORMAT_BLOCK_VERITY: {
      if (zx_status_t status = AttachDriver(kBlockVerityDriverPath); status != ZX_OK) {
        return status;
      }

      if (!ShouldAllowAuthoringFactory()) {
        zx::status<std::string> seal_text = VeritySeal();
        if (seal_text.is_error()) {
          FX_LOGS(ERROR) << "Couldn't get block-verity seal: " << seal_text.status_string();
          return seal_text.error_value();
        }

        return OpenBlockVerityForVerifiedRead(seal_text.value());
      }

      return ZX_OK;
    }
    case DISK_FORMAT_FACTORYFS: {
      if (zx_status_t status = CheckFilesystem(); status != ZX_OK) {
        return status;
      }

      return MountFilesystem();
    }
    case DISK_FORMAT_ZXCRYPT: {
      return UnsealZxcrypt();
    }
    case DISK_FORMAT_BLOBFS: {
      if (zx_status_t status = CheckFilesystem(); status != ZX_OK) {
        return status;
      }
      return MountFilesystem();
    }
    case DISK_FORMAT_MINFS: {
      FX_LOGS(INFO) << "mounting minfs: format on corruption is "
                    << (format_on_corruption ? "enabled" : "disabled");
      if (zx_status_t status = CheckFilesystem(); status != ZX_OK) {
        if (!format_on_corruption) {
          FX_LOGS(INFO) << "formatting minfs on this target is disabled";
          return status;
        }
        if (zx_status_t status = FormatFilesystem(); status != ZX_OK) {
          return status;
        }
      }
      if (zx_status_t status = MountFilesystem(); status != ZX_OK) {
        FX_LOGS(ERROR) << "failed to mount filesystem: " << zx_status_get_string(status);
        if (!format_on_corruption) {
          FX_LOGS(ERROR) << "formatting minfs on this target is disabled";
          return status;
        }
        if ((status = FormatFilesystem()) != ZX_OK) {
          return status;
        }
        return MountFilesystem();
      }
      return ZX_OK;
    }
    case DISK_FORMAT_FAT:
    case DISK_FORMAT_VBMETA:
    case DISK_FORMAT_UNKNOWN:
    case DISK_FORMAT_COUNT_:
      return ZX_ERR_NOT_SUPPORTED;
  }
  return ZX_ERR_NOT_SUPPORTED;
}

}  // namespace devmgr
