// Copyright 2022 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.

use crate::boot_args::BootArgs;
use crate::copier::recursive_copy;
use crate::crypt::fxfs::{self, CryptService};
use crate::crypt::zxcrypt::{UnsealOutcome, ZxcryptDevice};
use crate::crypt::{get_policy, Policy};
use crate::device::constants::{
    BLOBFS_PARTITION_LABEL, BLOBFS_TYPE_GUID, DATA_PARTITION_LABEL, DATA_TYPE_GUID,
    DEFAULT_F2FS_MIN_BYTES, FVM_DRIVER_PATH, LEGACY_DATA_PARTITION_LABEL, ZXCRYPT_DRIVER_PATH,
};
use crate::device::{BlockDevice, Device};
use crate::inspect::register_migration_status;
use anyhow::{anyhow, bail, Context, Error};
use async_trait::async_trait;
use device_watcher::{recursive_wait, recursive_wait_and_open};
use fidl::endpoints::{create_proxy, ServerEnd};
use fidl_fuchsia_fxfs::MountOptions;
use fidl_fuchsia_hardware_block_partition::Guid;
use fidl_fuchsia_hardware_block_volume::{VolumeManagerMarker, VolumeMarker};
use fs_management::filesystem::{
    ServingMultiVolumeFilesystem, ServingSingleVolumeFilesystem, ServingVolume,
};
use fs_management::format::DiskFormat;
use fs_management::partition::fvm_allocate_partition;
use fs_management::{Blobfs, ComponentType, F2fs, FSConfig, Fxfs, Minfs};
use fuchsia_component::client::{connect_to_protocol, connect_to_protocol_at_path};
use futures::lock::Mutex;
use std::collections::HashSet;
use std::sync::Arc;
use uuid::Uuid;
use {fidl_fuchsia_io as fio, fuchsia_async as fasync, fuchsia_zircon as zx};

const INITIAL_SLICE_COUNT: u64 = 1;

/// Returned from Environment::launch_data to signal when formatting is required.
pub enum ServeFilesystemStatus {
    Serving(Filesystem),
    FormatRequired,
}

/// Environment is a trait that performs actions when a device is matched.
/// Nb: matcher.rs depend on this interface being used in order to mock tests.
#[async_trait]
pub trait Environment: Send + Sync {
    /// Attaches the specified driver to the device.
    async fn attach_driver(&self, device: &mut dyn Device, driver_path: &str) -> Result<(), Error>;

    /// Binds the fvm driver and returns a list of the names of the child partitions.
    async fn bind_and_enumerate_fvm(
        &mut self,
        device: &mut dyn Device,
    ) -> Result<Vec<String>, Error>;

    /// Creates a static instance of Fxfs on `device` and calls serve_multi_volume(). Only creates
    /// the overall Fxfs instance. Mount_blob_volume and mount_data_volume still need to be called.
    async fn mount_fxblob(&mut self, device: &mut dyn Device) -> Result<(), Error>;

    /// Mounts Fxblob's blob volume on the given device.
    async fn mount_blob_volume(&mut self) -> Result<(), Error>;

    /// Mounts Fxblob's data volume on the given device.
    async fn mount_data_volume(&mut self) -> Result<(), Error>;

    /// Called after the fvm driver is bound. Waits for the block driver to bind itself to the
    /// blobfs partition before creating a blobfs BlockDevice, which it passes into mount_blobfs().
    async fn mount_blobfs_on(&mut self, blobfs_partition_name: &str) -> Result<(), Error>;

    /// Called after the fvm driver is bound. Waits for the block driver to bind itself to the
    /// data partition before creating a data BlockDevice, which it then passes into launch_data().
    /// Calls bind_data() on the mounted filesystem.
    async fn mount_data_on(&mut self, data_partition_name: &str) -> Result<(), Error>;

    /// Wipe and recreate data partition before reformatting with a filesystem.
    async fn format_data(&mut self, fvm_topo_path: &str) -> Result<Filesystem, Error>;

    /// Attempt to migrate |filesystem|, if requested, to some other format.
    /// |device| should refer to the FVM partition for |filesystem|.
    ///
    /// Returns either:
    ///   None if the original filesystem should be used.
    ///   Some(filesystem) a migrated to a different filesystem should be used.
    async fn try_migrate_data(
        &mut self,
        _device: &mut dyn Device,
        _filesystem: &mut Filesystem,
    ) -> Result<Option<Filesystem>, Error> {
        Ok(None)
    }

    /// Binds |filesystem| to the `/data` path. Fails if already bound.
    fn bind_data(&mut self, filesystem: Filesystem) -> Result<(), Error>;

    /// Shreds the data volume, triggering a reformat on reboot.
    /// The data volume must be Fxfs-formatted and must be currently serving.
    async fn shred_data(&mut self) -> Result<(), Error>;

    /// Synchronously shut down all associated filesystems.
    async fn shutdown(&mut self) -> Result<(), Error>;
}

// Before a filesystem is mounted, we queue requests.
pub enum Filesystem {
    Queue(Vec<ServerEnd<fio::DirectoryMarker>>),
    Serving(ServingSingleVolumeFilesystem),
    ServingMultiVolume(
        // We hold onto crypt service here to avoid it prematurely shutting down.
        // Fxfs may expect to find it in via VFS at a later time and it stops running
        // when all channels are closed.
        #[allow(dead_code)] CryptService,
        ServingMultiVolumeFilesystem,
        String,
    ),
    ServingVolumeInFxblob(
        // We hold onto crypt service here to avoid it prematurely shutting down.
        #[allow(dead_code)] Option<CryptService>,
        String,
    ),
    Shutdown,
}

impl Filesystem {
    fn is_serving(&self) -> bool {
        if let Self::Queue(_) = self {
            false
        } else {
            true
        }
    }

    pub fn exposed_dir(
        &mut self,
        serving_fs: Option<&mut ServingMultiVolumeFilesystem>,
    ) -> Result<fio::DirectoryProxy, Error> {
        let (proxy, server) = create_proxy::<fio::DirectoryMarker>()?;
        match self {
            Filesystem::Queue(queue) => queue.push(server),
            Filesystem::Serving(fs) => fs
                .exposed_dir()
                .clone(fio::OpenFlags::CLONE_SAME_RIGHTS, server.into_channel().into())?,
            Filesystem::ServingMultiVolume(_, fs, data_volume_name) => fs
                .volume(&data_volume_name)
                .ok_or(anyhow!("data volume {} not found", data_volume_name))?
                .exposed_dir()
                .clone(fio::OpenFlags::CLONE_SAME_RIGHTS, server.into_channel().into())?,
            Filesystem::ServingVolumeInFxblob(_, data_volume_name) => serving_fs
                .unwrap()
                .volume(&data_volume_name)
                .ok_or(anyhow!("data volume {} not found", data_volume_name))?
                .exposed_dir()
                .clone(fio::OpenFlags::CLONE_SAME_RIGHTS, server.into_channel().into())?,
            Filesystem::Shutdown => bail!(anyhow!("filesystem is shutting down")),
        }
        Ok(proxy)
    }

    pub fn root(
        &mut self,
        serving_fs: Option<&mut ServingMultiVolumeFilesystem>,
    ) -> Result<fio::DirectoryProxy, Error> {
        let root = fuchsia_fs::directory::open_directory_no_describe(
            &self.exposed_dir(serving_fs).context("failed to get exposed dir")?,
            "root",
            fio::OpenFlags::RIGHT_READABLE
                | fio::OpenFlags::POSIX_EXECUTABLE
                | fio::OpenFlags::POSIX_WRITABLE,
        )
        .context("failed to open the root directory")?;
        Ok(root)
    }

    pub fn volume(&mut self, volume_name: &str) -> Option<&mut ServingVolume> {
        match self {
            Filesystem::ServingMultiVolume(_, fs, _) => fs.volume_mut(&volume_name),
            Filesystem::ServingVolumeInFxblob(..) => unreachable!(),
            _ => None,
        }
    }

    fn queue(&mut self) -> Option<&mut Vec<ServerEnd<fio::DirectoryMarker>>> {
        match self {
            Filesystem::Queue(queue) => Some(queue),
            _ => None,
        }
    }

    pub async fn shutdown(
        &mut self,
        serving_fs: Option<&mut ServingMultiVolumeFilesystem>,
    ) -> Result<(), Error> {
        let old = std::mem::replace(self, Filesystem::Shutdown);
        match old {
            Filesystem::Queue(_) => Ok(()),
            Filesystem::Serving(fs) => fs.shutdown().await.context("shutdown failed"),
            Filesystem::ServingMultiVolume(_, fs, _) => {
                fs.shutdown().await.context("shutdown failed")
            }
            Filesystem::ServingVolumeInFxblob(_, volume_name) => {
                serving_fs.unwrap().shutdown_volume(&volume_name).await.context("shutdown failed")
            }
            Filesystem::Shutdown => Err(anyhow!("double shutdown!")),
        }
    }
}

/// Implements the Environment trait and keeps track of mounted filesystems.
pub struct FshostEnvironment {
    config: Arc<fshost_config::Config>,
    // `fxblob` is set inside mount_fxblob() and represents the overall Fxfs instance which
    // contains both a data and blob volume.
    fxblob: Option<ServingMultiVolumeFilesystem>,
    blobfs: Filesystem,
    data: Filesystem,
    fvm: Option<(/*topological_path*/ String, /*device_directory*/ fio::DirectoryProxy)>,
    launcher: Arc<FilesystemLauncher>,
    /// This lock can be taken and device.path() added to the vector to have them
    /// ignored the next time they appear to the Watcher/Matcher code.
    matcher_lock: Arc<Mutex<HashSet<String>>>,
    inspector: fuchsia_inspect::Inspector,
}

impl FshostEnvironment {
    pub fn new(
        config: Arc<fshost_config::Config>,
        boot_args: BootArgs,
        ramdisk_prefix: Option<String>,
        matcher_lock: Arc<Mutex<HashSet<String>>>,
        inspector: fuchsia_inspect::Inspector,
    ) -> Self {
        Self {
            config: config.clone(),
            fxblob: None,
            blobfs: Filesystem::Queue(Vec::new()),
            data: Filesystem::Queue(Vec::new()),
            fvm: None,
            launcher: Arc::new(FilesystemLauncher { config, boot_args, ramdisk_prefix }),
            matcher_lock,
            inspector,
        }
    }

    fn get_fvm(&self) -> Result<(&String, &fio::DirectoryProxy), Error> {
        debug_assert!(
            self.fvm.is_some(),
            "fvm was not initialized, ensure `bind_and_enumerate_fvm()` was called!"
        );
        if let Some((ref fvm_topo_path, ref fvm_dir)) = self.fvm {
            return Ok((fvm_topo_path, fvm_dir));
        }
        bail!("fvm was not initialized");
    }

    /// Returns a proxy for the exposed dir of the Blobfs filesystem.  This can be called before
    /// Blobfs is mounted and it will get routed once Blobfs is mounted.
    pub fn blobfs_exposed_dir(&mut self) -> Result<fio::DirectoryProxy, Error> {
        self.blobfs.exposed_dir(self.fxblob.as_mut())
    }

    /// Returns a proxy for the exposed dir of the data filesystem.  This can be called before
    /// "/data" is mounted and it will get routed once the data partition is mounted.
    pub fn data_exposed_dir(&mut self) -> Result<fio::DirectoryProxy, Error> {
        self.data.exposed_dir(self.fxblob.as_mut())
    }

    /// Returns a proxy for the root of the data filesystem.  This can be called before "/data" is
    /// mounted and it will get routed once the data partition is mounted.
    pub fn data_root(&mut self) -> Result<fio::DirectoryProxy, Error> {
        self.data.root(self.fxblob.as_mut())
    }

    pub fn launcher(&self) -> Arc<FilesystemLauncher> {
        self.launcher.clone()
    }

    /// Set the max partition size for data
    async fn apply_data_partition_limits(&self, device: &mut dyn Device) {
        if !self.launcher.is_ramdisk_device(device) {
            if let Err(error) = device.set_partition_max_bytes(self.config.data_max_bytes).await {
                tracing::warn!(%error, "Failed to set max partition size for data");
            }
        }
    }

    /// Formats a device with the specified disk format. Normally we only format the configured
    /// format but this level of abstraction lets us select the format for use in migration code
    /// paths.
    async fn format_data_with_disk_format(
        &mut self,
        format: DiskFormat,
        device: &mut dyn Device,
    ) -> Result<Filesystem, Error> {
        // Potentially bind and format zxcrypt first.
        let mut zxcrypt_device;
        let device = if (self.config.use_disk_migration && format == DiskFormat::Zxcrypt)
            || self.launcher.requires_zxcrypt(format, device)
        {
            tracing::info!(
                path = device.path(),
                "Formatting zxcrypt before formatting inner data partition.",
            );
            let ignore_paths = &mut *self.matcher_lock.lock().await;
            self.attach_driver(device, ZXCRYPT_DRIVER_PATH).await?;
            zxcrypt_device =
                Box::new(ZxcryptDevice::format(device).await.context("zxcrypt format failed")?);
            ignore_paths.insert(zxcrypt_device.topological_path().to_string());
            zxcrypt_device.as_mut()
        } else {
            device
        };

        // Set the max partition size for data
        self.apply_data_partition_limits(device).await;

        let filesystem = match format {
            DiskFormat::Fxfs => {
                let config =
                    Fxfs { component_type: ComponentType::StaticChild, ..Default::default() };
                self.launcher.format_data(device, config).await?
            }
            DiskFormat::F2fs => {
                let config =
                    F2fs { component_type: ComponentType::StaticChild, ..Default::default() };
                self.launcher.format_data(device, config).await?
            }
            DiskFormat::Minfs => {
                let config =
                    Minfs { component_type: ComponentType::StaticChild, ..Default::default() };
                self.launcher.format_data(device, config).await?
            }
            format => {
                tracing::warn!("Unsupported format {:?}", format);
                return Err(anyhow!("Cannot format filesystem"));
            }
        };

        Ok(filesystem)
    }

    async fn try_migrate_data_internal(
        &mut self,
        device: &mut dyn Device,
        filesystem: &mut Filesystem,
    ) -> Result<Option<Filesystem>, Error> {
        // Take note of the original device GUID. We will mark it inactive on success.
        let device_guid = device.partition_instance().await.map(|guid| *guid).ok();

        // The filesystem may be zxcrypt wrapped so we can't use device.content_type() here.
        // We query the FS directly.
        let device_format = match filesystem {
            Filesystem::Serving(filesystem) => {
                if let Some(vfs_type) =
                    fidl_fuchsia_fs::VfsType::from_primitive(filesystem.query().await?.fs_type)
                {
                    match vfs_type {
                        fidl_fuchsia_fs::VfsType::Minfs => DiskFormat::Minfs,
                        fidl_fuchsia_fs::VfsType::F2Fs => DiskFormat::F2fs,
                        fidl_fuchsia_fs::VfsType::Fxfs => DiskFormat::Fxfs,
                        _ => {
                            return Ok(None);
                        }
                    }
                } else {
                    return Ok(None);
                }
            }
            Filesystem::ServingMultiVolume(_, _, _) => DiskFormat::Fxfs,
            _ => {
                return Ok(None);
            }
        };

        let root = filesystem.root(None)?;

        // Read desired format from fs_switch, use config as default.
        let desired_format = match fuchsia_fs::directory::open_file(
            &root,
            "fs_switch",
            fio::OpenFlags::RIGHT_READABLE,
        )
        .await
        {
            Ok(file) => {
                let mut desired_format = fuchsia_fs::file::read_to_string(&file).await?;
                desired_format = desired_format.trim_end().to_string();
                // "toggle" is a special format request that flip-flops between fxfs and minfs.
                if desired_format.as_str() == "toggle" {
                    desired_format =
                        if device_format == DiskFormat::Fxfs { "minfs" } else { "fxfs" }
                            .to_string();
                }
                desired_format
            }
            Err(error) => {
                tracing::info!(%error, default_format=self.config.data_filesystem_format.as_str(),
                    "fs_switch open failed.");
                self.config.data_filesystem_format.to_string()
            }
        };
        let desired_format = match desired_format.as_str().into() {
            DiskFormat::Fxfs => DiskFormat::Fxfs,
            DiskFormat::F2fs => DiskFormat::F2fs,
            _ => DiskFormat::Minfs,
        };

        if device_format != desired_format {
            tracing::info!(
                device_format = device_format.as_str(),
                desired_format = desired_format.as_str(),
                "Attempting migration"
            );

            let volume_manager = connect_to_protocol_at_path::<VolumeManagerMarker>(
                &device.fvm_path().ok_or(anyhow!("Not an fvm device"))?,
            )
            .context("Failed to connect to fvm volume manager")?;
            let new_instance_guid = *uuid::Uuid::new_v4().as_bytes();

            // Note that if we are using fxfs or f2fs we should always be setting data_max_bytes
            // because these filesystems cannot automatically grow/shrink themselves.
            let slices = self.config.data_max_bytes / self.config.fvm_slice_size;
            if slices == 0 {
                bail!("data_max_bytes not set. Cannot migrate.");
            }
            tracing::info!(slices, "Allocating new partition");
            let new_data_partition_controller = fvm_allocate_partition(
                &volume_manager,
                DATA_TYPE_GUID,
                new_instance_guid,
                DATA_PARTITION_LABEL,
                fidl_fuchsia_hardware_block_volume::ALLOCATE_PARTITION_FLAG_INACTIVE,
                slices,
            )
            .await
            .context("Allocate migration partition.")?;

            let device_path = new_data_partition_controller
                .get_topological_path()
                .await?
                .map_err(zx::Status::from_raw)?;

            let mut new_device =
                BlockDevice::from_proxy(new_data_partition_controller, device_path).await?;

            let mut new_filesystem =
                self.format_data_with_disk_format(desired_format, &mut new_device).await?;

            recursive_copy(&filesystem.root(None)?, &new_filesystem.root(None)?)
                .await
                .context("copy data")?;

            // Ensure the watcher won't process the device we just added.
            {
                let mut ignore_paths = self.matcher_lock.lock().await;
                ignore_paths.insert(new_device.topological_path().to_string());
            }

            // Mark the old partition inactive (deletion at next boot).
            if let Some(old_instance_guid) = device_guid {
                zx::Status::ok(
                    volume_manager
                        .activate(
                            &Guid { value: old_instance_guid },
                            &Guid { value: new_instance_guid },
                        )
                        .await?,
                )?;
            }
            Ok(Some(new_filesystem))
        } else {
            Ok(None)
        }
    }

    /// Mounts Blobfs on the given device.
    async fn mount_blobfs(&mut self, device: &mut dyn Device) -> Result<(), Error> {
        let queue = self.blobfs.queue().ok_or(anyhow!("blobfs already mounted"))?;

        let mut fs = self.launcher.serve_blobfs(device).await?;

        let exposed_dir = fs.exposed_dir(None)?;
        for server in queue.drain(..) {
            exposed_dir.clone(fio::OpenFlags::CLONE_SAME_RIGHTS, server.into_channel().into())?;
        }
        self.blobfs = fs;
        Ok(())
    }

    /// Launch data partition on the given device.
    /// If formatting is required, returns ServeFilesystemStatus::FormatRequired.
    async fn launch_data(
        &mut self,
        device: &mut dyn Device,
    ) -> Result<ServeFilesystemStatus, Error> {
        let _ = self.data.queue().ok_or_else(|| anyhow!("data partition already mounted"))?;

        let mut format: DiskFormat = if self.config.use_disk_migration {
            let format = device.content_format().await?;
            tracing::info!(
                format = format.as_str(),
                "Using detected disk format to potentially \
                migrate data"
            );
            format
        } else {
            match self.config.data_filesystem_format.as_str().into() {
                DiskFormat::Fxfs => DiskFormat::Fxfs,
                DiskFormat::F2fs => DiskFormat::F2fs,
                // Default to minfs if we don't match expected filesystems.
                _ => DiskFormat::Minfs,
            }
        };

        // Potentially bind and unseal zxcrypt before serving data.
        let mut zxcrypt_device = None;
        let device = if (self.config.use_disk_migration && format == DiskFormat::Zxcrypt)
            || self.launcher.requires_zxcrypt(format, device)
        {
            tracing::info!(path = device.path(), "Attempting to unseal zxcrypt device",);
            let ignore_paths = &mut *self.matcher_lock.lock().await;
            self.attach_driver(device, ZXCRYPT_DRIVER_PATH).await?;
            let mut new_device = match ZxcryptDevice::unseal(device).await? {
                UnsealOutcome::Unsealed(device) => device,
                UnsealOutcome::FormatRequired => {
                    tracing::warn!("failed to unseal zxcrypt, format required");
                    return Ok(ServeFilesystemStatus::FormatRequired);
                }
            };
            // If we are using content sniffing to identify the filesystem, we have to do it again
            // after unsealing zxcrypt.
            if self.config.use_disk_migration {
                format = new_device.content_format().await?;
                tracing::info!(format = format.as_str(), "detected zxcrypt wrapped format");
            }
            ignore_paths.insert(new_device.topological_path().to_string());
            zxcrypt_device = Some(Box::new(new_device));
            zxcrypt_device.as_mut().unwrap().as_mut()
        } else {
            device
        };

        // Set the max partition size for data
        self.apply_data_partition_limits(device).await;

        let filesystem = match format {
            DiskFormat::Fxfs => {
                let config =
                    Fxfs { component_type: ComponentType::StaticChild, ..Default::default() };
                self.launcher.serve_data(device, config).await
            }
            DiskFormat::F2fs => {
                let config =
                    F2fs { component_type: ComponentType::StaticChild, ..Default::default() };
                self.launcher.serve_data(device, config).await
            }
            DiskFormat::Minfs => {
                let config =
                    Minfs { component_type: ComponentType::StaticChild, ..Default::default() };
                self.launcher.serve_data(device, config).await
            }
            format => {
                tracing::warn!(format = format.as_str(), "Unsupported filesystem");
                Ok(ServeFilesystemStatus::FormatRequired)
            }
        }?;

        if let ServeFilesystemStatus::FormatRequired = filesystem {
            if let Some(device) = zxcrypt_device {
                tracing::info!(path = device.path(), "Resealing zxcrypt device due to error.");
                device.seal().await?;
            }
        }

        Ok(filesystem)
    }
}

#[async_trait]
impl Environment for FshostEnvironment {
    async fn attach_driver(&self, device: &mut dyn Device, driver_path: &str) -> Result<(), Error> {
        self.launcher.attach_driver(device, driver_path).await
    }

    async fn bind_and_enumerate_fvm(
        &mut self,
        device: &mut dyn Device,
    ) -> Result<Vec<String>, Error> {
        // Attach the FVM driver and connect to the VolumeManager.
        self.attach_driver(device, FVM_DRIVER_PATH).await?;
        let fvm_dir = fuchsia_fs::directory::open_in_namespace(
            &device.topological_path(),
            fuchsia_fs::OpenFlags::RIGHT_READABLE,
        )?;
        let fvm_volume_manager_proxy =
            recursive_wait_and_open::<VolumeManagerMarker>(&fvm_dir, "/fvm")
                .await
                .context("failed to connect to the VolumeManager")?;

        // **NOTE**: We must call VolumeManager::GetInfo() to ensure all partitions are visible when
        // we enumerate them below. See https://fxbug.dev/42077585 for more information.
        zx::ok(fvm_volume_manager_proxy.get_info().await.context("transport error on get_info")?.0)
            .context("get_info failed")?;

        let fvm_topo_path = format!("{}/fvm", device.topological_path());
        let fvm_dir = fuchsia_fs::directory::open_in_namespace(
            &fvm_topo_path,
            fuchsia_fs::OpenFlags::RIGHT_READABLE,
        )?;
        let dir_entries = fuchsia_fs::directory::readdir(&fvm_dir).await?;

        self.fvm = Some((fvm_topo_path, fvm_dir));
        Ok(dir_entries.into_iter().map(|entry| entry.name).collect())
    }

    async fn mount_fxblob(&mut self, device: &mut dyn Device) -> Result<(), Error> {
        tracing::info!(
            path = %device.path(),
            expected_format = "fxfs",
            "Mounting fxblob"
        );
        let serving_fs = self.launcher.serve_fxblob(device).await?;
        self.fxblob = Some(serving_fs);
        Ok(())
    }

    async fn mount_blob_volume(&mut self) -> Result<(), Error> {
        let _ = self.blobfs.queue().ok_or_else(|| anyhow!("blobfs partition already mounted"))?;

        let multi_vol_fs =
            self.fxblob.as_mut().ok_or_else(|| anyhow!("ServingMultiVolumeFilesystem is None"))?;
        let () = multi_vol_fs
            .check_volume("blob", None)
            .await
            .context("Failed to verify the blob volume")?;
        let blobfs = multi_vol_fs
            .open_volume("blob", MountOptions { crypt: None, as_blob: true })
            .await
            .context("Failed to open the blob volume")?;
        let exposed_dir = blobfs.exposed_dir();
        let queue = self.blobfs.queue().ok_or(anyhow!("blobfs already mounted"))?;
        for server in queue.drain(..) {
            exposed_dir.clone(fio::OpenFlags::CLONE_SAME_RIGHTS, server.into_channel().into())?;
        }
        self.blobfs = Filesystem::ServingVolumeInFxblob(None, "blob".to_string());
        if let Err(e) = multi_vol_fs.set_byte_limit("blob", self.config.blobfs_max_bytes).await {
            tracing::warn!("Failed to set byte limit for the blob volume: {:?}", e);
        }
        Ok(())
    }

    async fn mount_data_volume(&mut self) -> Result<(), Error> {
        let _ = self.data.queue().ok_or_else(|| anyhow!("data partition already mounted"))?;

        let multi_vol_fs =
            self.fxblob.as_mut().ok_or_else(|| anyhow!("ServingMultiVolumeFilesystem is None"))?;
        let mut filesystem = self.launcher.serve_data_fxblob(multi_vol_fs).await?;
        if let Err(e) = multi_vol_fs.set_byte_limit("data", self.config.data_max_bytes).await {
            tracing::warn!("Failed to set byte limit for the data volume: {:?}", e);
        }
        let queue = self.data.queue().unwrap();
        let exposed_dir = filesystem.exposed_dir(self.fxblob.as_mut())?;
        for server in queue.drain(..) {
            exposed_dir.clone(fio::OpenFlags::CLONE_SAME_RIGHTS, server.into_channel().into())?;
        }
        self.data = filesystem;
        Ok(())
    }

    async fn mount_blobfs_on(&mut self, blobfs_partition_name: &str) -> Result<(), Error> {
        let (fvm_topo_path, fvm_dir) = self.get_fvm()?;
        let blobfs_topo_path = format!("{}/{blobfs_partition_name}/block", fvm_topo_path);
        recursive_wait(fvm_dir, &format!("{blobfs_partition_name}/block"))
            .await
            .context("failed to bind block driver to blobfs device")?;
        let mut device = BlockDevice::new(blobfs_topo_path)
            .await
            .context("failed to create blobfs block device")?;
        let (label, type_guid) =
            (device.partition_label().await?.to_string(), *device.partition_type().await?);
        if !(label == BLOBFS_PARTITION_LABEL && type_guid == BLOBFS_TYPE_GUID) {
            tracing::error!(
                "incorrect parameters for blobfs partition: label = {}, type = {:?}",
                label,
                type_guid
            );
            bail!("blobfs partition has incorrect label/guid");
        }
        self.mount_blobfs(&mut device).await
    }

    async fn mount_data_on(&mut self, data_partition_name: &str) -> Result<(), Error> {
        let (fvm_topo_path, fvm_dir) = self.get_fvm()?;
        let data_topo_path = format!("{}/{data_partition_name}/block", fvm_topo_path);
        recursive_wait(fvm_dir, &format!("{data_partition_name}/block"))
            .await
            .context("failed to bind block driver to the data device")?;
        let mut device = BlockDevice::new(data_topo_path)
            .await
            .context("failed to create blobfs block device")?;
        let (label, type_guid) =
            (device.partition_label().await?.to_string(), *device.partition_type().await?);
        if !((label == DATA_PARTITION_LABEL || label == LEGACY_DATA_PARTITION_LABEL)
            && type_guid == DATA_TYPE_GUID)
        {
            tracing::error!(
                "incorrect parameters for data partition: label = {}, type = {:?}",
                label,
                type_guid
            );
            bail!("data partition has incorrect label/guid");
        }

        let fs = match self.launch_data(&mut device).await? {
            ServeFilesystemStatus::Serving(mut filesystem) => {
                // If this build supports migrating data partition, try now, failing back to
                // just using `filesystem` in the case of any error. Non-migration builds
                // should return Ok(None).
                match self.try_migrate_data(&mut device, &mut filesystem).await {
                    Ok(Some(new_filesystem)) => {
                        // Migration successful.
                        filesystem.shutdown(None).await.unwrap_or_else(|error| {
                            tracing::error!(
                                ?error,
                                "Failed to shutdown original filesystem after migration"
                            );
                        });
                        new_filesystem
                    }
                    Ok(None) => filesystem, // Migration not requested.
                    Err(error) => {
                        // Migration failed.
                        tracing::error!(?error, "Failed to migrate filesystem");
                        // TODO: Log migration failure metrics.
                        // Continue with the original (unmigrated) filesystem.
                        filesystem
                    }
                }
            }
            ServeFilesystemStatus::FormatRequired => {
                self.format_data(&device.fvm_path().ok_or(anyhow!("Not an fvm device"))?).await?
            }
        };
        self.bind_data(fs)
    }

    async fn format_data(&mut self, fvm_topo_path: &str) -> Result<Filesystem, Error> {
        // Reset FVM partition first, ensuring we blow away any existing zxcrypt volume.
        let mut device = self
            .launcher
            .reset_fvm_partition(fvm_topo_path, &mut *self.matcher_lock.lock().await)
            .await
            .with_context(|| {
                format!("Failed to reset non-blob FVM partitions on {}", fvm_topo_path)
            })?;
        let device = device.as_mut();

        // Default to minfs if we don't match expected filesystems.
        let format: DiskFormat = match self.config.data_filesystem_format.as_str().into() {
            DiskFormat::Fxfs => DiskFormat::Fxfs,
            DiskFormat::F2fs => DiskFormat::F2fs,
            _ => DiskFormat::Minfs,
        };

        // Rotate hardware derived key before formatting if we follow a Tee policy
        if get_policy().await? != Policy::Null {
            tracing::info!("Rotate hardware derived key before formatting");
            // Hardware derived keys are not rotatable on certain devices.
            // TODO(b/271166111): Assert hard fail when we know rotating the key should work.
            match kms_stateless::rotate_hardware_derived_key(kms_stateless::KeyInfo::new("zxcrypt"))
                .await
            {
                Ok(()) => {}
                Err(kms_stateless::Error::TeeCommandNotSupported(
                    kms_stateless::TaKeysafeCommand::RotateHardwareDerivedKey,
                )) => {
                    tracing::warn!("The device does not support rotatable hardware keys.")
                }
                Err(e) => {
                    tracing::warn!("Rotate hardware key failed with error {:?}.", e)
                }
            }
        }

        self.format_data_with_disk_format(format, device).await
    }

    async fn try_migrate_data(
        &mut self,
        device: &mut dyn Device,
        filesystem: &mut Filesystem,
    ) -> Result<Option<Filesystem>, Error> {
        if !self.config.use_disk_migration {
            return Ok(None);
        }

        let res = self.try_migrate_data_internal(device, filesystem).await;
        if let Err(error) = &res {
            tracing::warn!(%error, "migration failed");
            if let Some(status) = error.downcast_ref::<zx::Status>().clone() {
                register_migration_status(self.inspector.root(), *status).await;
            } else {
                register_migration_status(self.inspector.root(), zx::Status::INTERNAL).await;
            }
        } else {
            register_migration_status(self.inspector.root(), zx::Status::OK).await;
        }
        res
    }

    fn bind_data(&mut self, mut filesystem: Filesystem) -> Result<(), Error> {
        let _ = self.data.queue().ok_or_else(|| anyhow!("data partition already mounted"))?;

        let queue = self.data.queue().unwrap();
        let exposed_dir = filesystem.exposed_dir(None)?;
        for server in queue.drain(..) {
            exposed_dir.clone(fio::OpenFlags::CLONE_SAME_RIGHTS, server.into_channel().into())?;
        }
        self.data = filesystem;
        Ok(())
    }

    async fn shred_data(&mut self) -> Result<(), Error> {
        if self.config.data_filesystem_format != "fxfs" {
            return Err(anyhow!("Can't shred data; not fxfs"));
        }
        if !self.data.is_serving() {
            return Err(anyhow!("Can't shred data; not already mounted"));
        }
        // Erase the keybag.
        let unencrypted = if let Some(fxblob) = &mut self.fxblob {
            fxblob.volume_mut("unencrypted")
        } else {
            self.data.volume("unencrypted")
        }
        .context("Failed to find unencrypted volume")?;
        let dir = fuchsia_fs::directory::open_directory(
            unencrypted.root(),
            "keys",
            fio::OpenFlags::RIGHT_WRITABLE,
        )
        .await
        .context("Failed to open keys dir")?;
        dir.unlink("fxfs-data", &fio::UnlinkOptions::default())
            .await?
            .map_err(|e| anyhow!(zx::Status::from_raw(e)))
            .context("Failed to remove keybag")?;
        Ok(())
    }

    async fn shutdown(&mut self) -> Result<(), Error> {
        // If we encounter an error, log it, but continue trying to shut down the remaining
        // filesystems.
        self.blobfs.shutdown(self.fxblob.as_mut()).await.unwrap_or_else(|error| {
            tracing::error!(?error, "failed to shut down blobfs");
        });
        self.data.shutdown(self.fxblob.as_mut()).await.unwrap_or_else(|error| {
            tracing::error!(?error, "failed to shut down data");
        });
        if let Some(fxfs) = self.fxblob.take() {
            fxfs.shutdown().await.unwrap_or_else(|error| {
                tracing::error!(?error, "failed to shut down fxfs");
            })
        }
        Ok(())
    }
}

#[allow(dead_code)] // TODO(https://fxbug.dev/318827209)
#[derive(Debug)]
struct ReformatRequired(Error);
impl std::error::Error for ReformatRequired {}
impl std::fmt::Display for ReformatRequired {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
        write!(f, "{:?}", self)
    }
}

pub struct FilesystemLauncher {
    config: Arc<fshost_config::Config>,
    boot_args: BootArgs,
    ramdisk_prefix: Option<String>,
}

impl FilesystemLauncher {
    pub async fn attach_driver(
        &self,
        device: &mut dyn Device,
        driver_path: &str,
    ) -> Result<(), Error> {
        tracing::info!(path = %device.path(), %driver_path, "Binding driver to device");
        match device.controller().bind(driver_path).await?.map_err(zx::Status::from_raw) {
            Err(e) if e == zx::Status::ALREADY_BOUND => {
                // It's fine if we get an ALREADY_BOUND error.
                tracing::info!(path = %device.path(), %driver_path,
                    "Ignoring ALREADY_BOUND error.");
                Ok(())
            }
            Err(e) => Err(e.into()),
            Ok(()) => Ok(()),
        }
    }

    /// This helper method returns true if the given device is a ramdisk.
    /// We want to enforce partition limits and use zxcrypt only on non-ramdisk devices.
    pub fn is_ramdisk_device(&self, device: &dyn Device) -> bool {
        self.ramdisk_prefix
            .as_ref()
            .map_or(false, |prefix| device.topological_path().starts_with(prefix))
    }

    pub fn requires_zxcrypt(&self, format: DiskFormat, device: &dyn Device) -> bool {
        match format {
            // Fxfs never has zxcrypt underneath
            DiskFormat::Fxfs => false,
            _ if self.config.no_zxcrypt => false,
            // No point using zxcrypt for ramdisk devices.
            _ if self.is_ramdisk_device(device) => false,
            _ => true,
        }
    }

    pub fn get_blobfs_config(&self) -> Blobfs {
        Blobfs {
            write_compression_algorithm: self.boot_args.blobfs_write_compression_algorithm(),
            cache_eviction_policy_override: self.boot_args.blobfs_eviction_policy(),
            ..Default::default()
        }
    }

    pub async fn serve_blobfs(&self, device: &mut dyn Device) -> Result<Filesystem, Error> {
        tracing::info!(path = %device.path(), "Mounting /blob");

        // Setting max partition size for blobfs
        if !self.is_ramdisk_device(device) {
            if let Err(e) = device.set_partition_max_bytes(self.config.blobfs_max_bytes).await {
                tracing::warn!("Failed to set max partition size for blobfs: {:?}", e);
            };
        }

        let config = Blobfs {
            component_type: fs_management::ComponentType::StaticChild,
            ..self.get_blobfs_config()
        };
        let fs = fs_management::filesystem::Filesystem::new(device.reopen_controller()?, config)
            .serve()
            .await
            .context("serving blobfs")?;

        Ok(Filesystem::Serving(fs))
    }

    pub async fn serve_data<FSC: FSConfig>(
        &self,
        device: &mut dyn Device,
        config: FSC,
    ) -> Result<ServeFilesystemStatus, Error> {
        let fs = fs_management::filesystem::Filesystem::new(device.reopen_controller()?, config);
        self.serve_data_from(device, fs).await
    }

    // NB: keep these larger functions monomorphized, otherwise they cause significant code size
    // increases.
    async fn serve_data_from(
        &self,
        device: &mut dyn Device,
        mut fs: fs_management::filesystem::Filesystem,
    ) -> Result<ServeFilesystemStatus, Error> {
        let format = fs.config().disk_format();
        tracing::info!(
            path = %device.path(),
            expected_format = ?format,
            "Mounting /data"
        );

        let detected_format = device.content_format().await?;
        if detected_format != format {
            tracing::info!(
                ?detected_format,
                expected_format = ?format,
                "Expected format not detected. Reformatting.",
            );
            return Ok(ServeFilesystemStatus::FormatRequired);
        }

        if self.config.check_filesystems {
            tracing::info!(?format, "fsck started");
            if let Err(error) = fs.fsck().await {
                self.report_corruption(format, &error);
                if self.config.format_data_on_corruption {
                    tracing::info!("Reformatting filesystem, expect data loss...");
                    return Ok(ServeFilesystemStatus::FormatRequired);
                } else {
                    tracing::error!(?format, "format on corruption is disabled, not continuing");
                    return Err(error);
                }
            } else {
                tracing::info!(?format, "fsck completed OK");
            }
        }

        // Wrap the serving in an async block so we can catch all errors.
        let serve_fut = async {
            match format {
                DiskFormat::Fxfs => {
                    let mut serving_multi_vol_fs = fs.serve_multi_volume().await?;
                    match fxfs::unlock_data_volume(&mut serving_multi_vol_fs, &self.config).await? {
                        Some((crypt_service, volume_name, _)) => {
                            Ok(ServeFilesystemStatus::Serving(Filesystem::ServingMultiVolume(
                                crypt_service,
                                serving_multi_vol_fs,
                                volume_name,
                            )))
                        }
                        // If unlocking returns none, the keybag got deleted by something.
                        None => {
                            tracing::warn!(
                                "keybag not found. Perhaps the keys were shredded? \
                                Reformatting the data volume."
                            );
                            Ok(ServeFilesystemStatus::FormatRequired)
                        }
                    }
                }
                _ => Ok(ServeFilesystemStatus::Serving(Filesystem::Serving(fs.serve().await?))),
            }
        };
        match serve_fut.await {
            Ok(fs) => Ok(fs),
            Err(error) => {
                self.report_corruption(format, &error);
                if self.config.format_data_on_corruption {
                    tracing::info!("Reformatting filesystem, expect data loss...");
                    Ok(ServeFilesystemStatus::FormatRequired)
                } else {
                    tracing::error!(?format, "format on corruption is disabled, not continuing");
                    Err(error)
                }
            }
        }
    }

    // Destroy all non-blob fvm partitions and reallocate only the data partition. Called on the
    // reformatting codepath. Takes the topological path of an fvm device with the fvm driver
    // bound.
    async fn reset_fvm_partition(
        &self,
        fvm_topo_path: &str,
        ignore_paths: &mut HashSet<String>,
    ) -> Result<Box<dyn Device>, Error> {
        tracing::info!(path = fvm_topo_path, "Resetting fvm partitions");
        let fvm_directory_proxy = fuchsia_fs::directory::open_in_namespace(
            &fvm_topo_path,
            fio::OpenFlags::RIGHT_READABLE,
        )?;
        let fvm_volume_manager_proxy =
            connect_to_protocol_at_path::<VolumeManagerMarker>(&fvm_topo_path)
                .context("Failed to connect to the fvm VolumeManagerProxy")?;

        // **NOTE**: We must call VolumeManager::GetInfo() to ensure all partitions are visible when
        // we enumerate them below. See https://fxbug.dev/42077585 for more information.
        zx::ok(fvm_volume_manager_proxy.get_info().await.context("transport error on get_info")?.0)
            .context("get_info failed")?;

        let dir_entries = fuchsia_fs::directory::readdir(&fvm_directory_proxy).await?;
        for entry in dir_entries {
            // Destroy all fvm partitions aside from blobfs
            if !entry.name.contains("blobfs") && !entry.name.contains("device") {
                let entry_volume_proxy = recursive_wait_and_open::<VolumeMarker>(
                    &fvm_directory_proxy,
                    &format!("{}/block", entry.name),
                )
                .await
                .with_context(|| format!("Failed to open partition {}", entry.name))?;
                ignore_paths.insert(format!("{fvm_topo_path}/{}/block", entry.name));
                let status = entry_volume_proxy
                    .destroy()
                    .await
                    .with_context(|| format!("Failed to destroy partition {}", entry.name))?;
                zx::Status::ok(status).context("destroy() returned an error")?;
                tracing::info!(partition = %entry.name, "Destroyed partition");
            }
        }

        // Recreate the data partition
        let data_partition_controller = fvm_allocate_partition(
            &fvm_volume_manager_proxy,
            DATA_TYPE_GUID,
            *Uuid::new_v4().as_bytes(),
            DATA_PARTITION_LABEL,
            0,
            INITIAL_SLICE_COUNT,
        )
        .await
        .context("Failed to allocate fvm data partition")?;

        let device_path = data_partition_controller
            .get_topological_path()
            .await?
            .map_err(zx::Status::from_raw)?;

        ignore_paths.insert(device_path.to_string());
        Ok(Box::new(BlockDevice::from_proxy(data_partition_controller, device_path).await?))
    }

    /// Starts serving Fxblob without opening any volumes.
    pub async fn serve_fxblob(
        &self,
        device: &mut dyn Device,
    ) -> Result<ServingMultiVolumeFilesystem, Error> {
        let mut fs = fs_management::filesystem::Filesystem::new(
            device.reopen_controller()?,
            Fxfs {
                component_type: ComponentType::StaticChild,
                startup_profiling_seconds: Some(60),
                ..Default::default()
            },
        );
        if self.config.check_filesystems {
            tracing::info!("fsck started for fxblob");
            if let Err(error) = fs.fsck().await {
                self.report_corruption(DiskFormat::Fxfs, &error);
                return Err(error);
            } else {
                tracing::info!("fsck completed OK for fxblob");
            }
        }
        fs.serve_multi_volume().await
    }

    /// Serves the data volume from Fxblob, formatting any non-blob volumes as needed.
    pub async fn serve_data_fxblob(
        &self,
        serving_multi_vol_fs: &mut ServingMultiVolumeFilesystem,
    ) -> Result<Filesystem, Error> {
        let mut format_needed = false;
        tracing::info!(expected_format = "fxfs", "Mounting /data");

        // We expect the startup protocol to work with fxblob. There are no options for
        // reformatting the entire fxfs partition now that blobfs is one of the volumes.
        let volumes_dir = fuchsia_fs::directory::open_directory(
            serving_multi_vol_fs.exposed_dir(),
            "volumes",
            fuchsia_fs::OpenFlags::empty(),
        )
        .await
        .context("opening volumes directory")?;
        let volumes = fuchsia_fs::directory::readdir(&volumes_dir)
            .await
            .context("reading volumes directory")?;
        let needed =
            HashSet::from(["blob".to_string(), "data".to_string(), "unencrypted".to_string()]);
        let mut found = HashSet::new();
        for volume in volumes {
            found.insert(volume.name);
        }

        if found != needed {
            format_needed = true;
        }

        if format_needed {
            Ok(self.format_data_in_fxblob(serving_multi_vol_fs).await?)
        } else {
            match fxfs::unlock_data_volume(serving_multi_vol_fs, &self.config).await {
                Ok(Some((crypt_service, volume_name, _))) => {
                    Ok(Filesystem::ServingVolumeInFxblob(Some(crypt_service), volume_name))
                }
                Ok(None) => {
                    tracing::warn!(
                        "could not find keybag. Perhaps the keys were shredded? \
                        Reformatting the data and unencrypted volumes."
                    );
                    self.format_data_in_fxblob(serving_multi_vol_fs).await
                }
                Err(error) => {
                    self.report_corruption(DiskFormat::Fxfs, &error);
                    tracing::error!(
                        ?error,
                        "unlock_data_volume failed. Reformatting the data and unencrypted volumes."
                    );
                    Ok(self.format_data_in_fxblob(serving_multi_vol_fs).await?)
                }
            }
        }
    }

    async fn format_data_in_fxblob(
        &self,
        serving_multi_vol_fs: &mut ServingMultiVolumeFilesystem,
    ) -> Result<Filesystem, Error> {
        // Reset fxfs volumes before reinitializing.
        let volumes_dir = fuchsia_fs::directory::open_directory_no_describe(
            serving_multi_vol_fs.exposed_dir(),
            "volumes",
            fuchsia_fs::OpenFlags::empty(),
        )?;
        let volumes = fuchsia_fs::directory::readdir(&volumes_dir).await?;
        for volume in volumes {
            if volume.name != "blob".to_string() {
                // Unmount mounted non-blob volumes.
                if serving_multi_vol_fs.volume(&volume.name).is_some() {
                    serving_multi_vol_fs.shutdown_volume(&volume.name).await?;
                }
                // Remove any non-blob volumes.
                serving_multi_vol_fs
                    .remove_volume(&volume.name)
                    .await
                    .with_context(|| format!("failed to remove volume: {:?}", volume.name))?;
            }
        }

        let (crypt_service, volume_name, _) =
            fxfs::init_data_volume(serving_multi_vol_fs, &self.config)
                .await
                .context("initializing data volume encryption")?;
        let filesystem = Filesystem::ServingVolumeInFxblob(Some(crypt_service), volume_name);

        Ok(filesystem)
    }

    pub async fn format_data<FSC: FSConfig>(
        &self,
        device: &mut dyn Device,
        config: FSC,
    ) -> Result<Filesystem, Error> {
        let fs = fs_management::filesystem::Filesystem::new(device.reopen_controller()?, config);
        self.format_data_from(device, fs).await
    }

    async fn format_data_from(
        &self,
        device: &mut dyn Device,
        mut fs: fs_management::filesystem::Filesystem,
    ) -> Result<Filesystem, Error> {
        let format = fs.config().disk_format();
        tracing::info!(path = device.path(), format = format.as_str(), "Formatting");
        match format {
            DiskFormat::Fxfs => {
                let target_bytes = self.config.data_max_bytes;
                tracing::info!(target_bytes, "Resizing data volume");
                let allocated_bytes =
                    device.resize(target_bytes).await.context("format volume resize")?;
                if allocated_bytes < target_bytes {
                    tracing::warn!(
                        target_bytes,
                        allocated_bytes,
                        "Allocated less space than desired"
                    );
                }
            }
            DiskFormat::F2fs => {
                let target_bytes =
                    std::cmp::max(self.config.data_max_bytes, DEFAULT_F2FS_MIN_BYTES);
                tracing::info!(target_bytes, "Resizing data volume");
                let allocated_bytes =
                    device.resize(target_bytes).await.context("format volume resize")?;
                if allocated_bytes < DEFAULT_F2FS_MIN_BYTES {
                    tracing::error!(
                        minimum_bytes = DEFAULT_F2FS_MIN_BYTES,
                        allocated_bytes,
                        "Not enough space for f2fs"
                    )
                }
                if allocated_bytes < target_bytes {
                    tracing::warn!(
                        target_bytes,
                        allocated_bytes,
                        "Allocated less space than desired"
                    );
                }
            }
            _ => (),
        }

        fs.format().await.context("formatting data partition")?;

        tracing::info!(path = device.path(), format = format.as_str(), "Serving");
        let filesystem = if let DiskFormat::Fxfs = format {
            let mut serving_multi_vol_fs =
                fs.serve_multi_volume().await.context("serving multi volume data partition")?;
            let (crypt_service, volume_name, _) =
                fxfs::init_data_volume(&mut serving_multi_vol_fs, &self.config)
                    .await
                    .context("initializing data volume encryption")?;
            Filesystem::ServingMultiVolume(crypt_service, serving_multi_vol_fs, volume_name)
        } else {
            Filesystem::Serving(fs.serve().await.context("serving single volume data partition")?)
        };

        Ok(filesystem)
    }

    fn report_corruption(&self, format: DiskFormat, error: &Error) {
        tracing::error!(?format, ?error, "FILESYSTEM CORRUPTION DETECTED!");
        tracing::error!(
            "Please file a bug to the Storage component in http://fxbug.dev, including a \
            device snapshot collected with `ffx target snapshot` if possible.",
        );

        fasync::Task::spawn(async move {
            let proxy = if let Ok(proxy) =
                connect_to_protocol::<fidl_fuchsia_feedback::CrashReporterMarker>()
            {
                proxy
            } else {
                tracing::error!("Failed to connect to crash report service");
                return;
            };
            let report = fidl_fuchsia_feedback::CrashReport {
                program_name: Some(format.as_str().to_owned()),
                crash_signature: Some(format!("fuchsia-{}-corruption", format.as_str())),
                is_fatal: Some(false),
                ..Default::default()
            };
            if let Err(e) = proxy.file_report(report).await {
                tracing::error!(?e, "Failed to file crash report");
            }
        })
        .detach();
    }
}
