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

//! Library for filesystem management in rust.
//!
//! This library is analogous to the fs-management library in zircon. It provides support for
//! formatting, mounting, unmounting, and fsck-ing. It is implemented in a similar way to the C++
//! version - it uses the blobfs command line tool present in the base image. In order to use this
//! library inside of a sandbox, the following must be added to the relevant component manifest
//! file -
//!
//! ```
//! "sandbox": {
//!     "services": [
//!         "fuchsia.process.Launcher",
//!         "fuchsia.tracing.provider.Registry"
//!     ]
//! }
//! ```
//!
//! and the projects BUILD.gn file must contain
//!
//! ```
//! package("foo") {
//!     deps = [
//!         "//src/storage/bin/blobfs",
//!         "//src/storage/bin/minfs",
//!         ...
//!     ]
//!     binaries = [
//!         { name = "blobfs" },
//!         { name = "minfs" },
//!         ...
//!     ]
//!     ...
//! }
//! ```
//!
//! for components v1. For components v2, add `/svc/fuchsia.process.Launcher` to `use` and add the
//! binaries as dependencies to your component.
//!
//! This library currently doesn't work outside of a component (the filesystem utility binary paths
//! are hard-coded strings).

pub mod asynchronous;
mod error;

use {
    anyhow::{bail, format_err, Context as _, Error},
    cstr::cstr,
    fdio::{service_connect_at, spawn_etc, Namespace, SpawnAction, SpawnOptions},
    fidl::endpoints::DiscoverableProtocolMarker,
    fidl_fuchsia_fs::AdminSynchronousProxy,
    fidl_fuchsia_io as fio,
    fuchsia_runtime::{HandleInfo, HandleType},
    fuchsia_zircon::{self as zx, AsHandleRef, Task},
    fuchsia_zircon_status as zx_status,
    std::{ffi::CStr, sync::Arc},
};

// Re-export errors as public.
pub use error::{
    BindError, CommandError, KillError, LaunchProcessError, QueryError, ServeError, ShutdownError,
};

/// Constants for fuchsia.io/FilesystemInfo.fs_type
/// Keep in sync with VFS_TYPE_* types in //zircon/system/public/zircon/device/vfs.h
pub mod vfs_type {
    pub const BLOBFS: u32 = 0x9e694d21;
    pub const FATFS: u32 = 0xce694d21;
    pub const MINFS: u32 = 0x6e694d21;
    pub const MEMFS: u32 = 0x3e694d21;
    pub const FACTORYFS: u32 = 0x1e694d21;
    pub const FXFS: u32 = 0x73667866;
    pub const F2FS: u32 = 0xfe694d21;
}

/// Stores state of the mounted filesystem instance
struct FSInstance {
    process: zx::Process,
    mount_point: String,
    export_root: zx::Channel,
}

impl FSInstance {
    /// Mount the filesystem partition that exists on the provided block device, allowing it to
    /// receive requests on the root channel. In order to be mounted in the traditional sense, the
    /// client side of the provided root channel needs to be bound to a path in a namespace
    /// somewhere.
    fn mount(
        block_device: zx::Channel,
        args: Vec<&CStr>,
        mount_point: &str,
        crypt_client: Option<zx::Channel>,
    ) -> Result<Self, Error> {
        let (export_root, server_end) = fidl::endpoints::create_endpoints::<fio::NodeMarker>()?;
        let export_root = fio::DirectorySynchronousProxy::new(export_root.into_channel());

        let mut actions = vec![
            // export root handle is passed in as a PA_DIRECTORY_REQUEST handle at argument 0
            SpawnAction::add_handle(
                HandleInfo::new(HandleType::DirectoryRequest, 0),
                server_end.into(),
            ),
            // device handle is passed in as a PA_USER0 handle at argument 1
            SpawnAction::add_handle(HandleInfo::new(HandleType::User0, 1), block_device.into()),
        ];
        if let Some(crypt_client) = crypt_client {
            actions.push(SpawnAction::add_handle(
                HandleInfo::new(HandleType::User0, 2),
                crypt_client.into(),
            ));
        }
        let process = launch_process(&args, actions)?;

        // Wait until the filesystem is ready to take incoming requests. We want
        // mount errors to show before we bind to the namespace.
        let (root_dir, server_end) = fidl::endpoints::create_endpoints::<fio::NodeMarker>()?;
        export_root.open(
            fio::OpenFlags::RIGHT_READABLE
                | fio::OpenFlags::POSIX_EXECUTABLE
                | fio::OpenFlags::POSIX_WRITABLE,
            0,
            "root",
            server_end.into(),
        )?;
        let root_dir = fio::DirectorySynchronousProxy::new(root_dir.into_channel());
        let _: fio::NodeInfo = root_dir.describe(zx::Time::INFINITE).context("failed to mount")?;

        let namespace = Namespace::installed().context("failed to get installed namespace")?;
        namespace
            .bind(mount_point, root_dir.into_channel())
            .context("failed to bind client channel into default namespace")?;

        Ok(Self {
            process,
            mount_point: mount_point.to_string(),
            export_root: export_root.into_channel(),
        })
    }

    /// Unmount the filesystem partition. The partition must already be mounted.
    fn unmount(self) -> Result<(), Error> {
        let (client_chan, server_chan) = zx::Channel::create()?;

        service_connect_at(
            &self.export_root,
            fidl_fuchsia_fs::AdminMarker::PROTOCOL_NAME,
            server_chan,
        )?;
        let admin_proxy = AdminSynchronousProxy::new(client_chan);
        admin_proxy.shutdown(zx::Time::INFINITE)?;

        let namespace = Namespace::installed().context("failed to get installed namespace")?;
        namespace
            .unbind(&self.mount_point)
            .context("failed to unbind filesystem from default namespace")
    }

    /// Get `FileSystemInfo` struct from which one can find out things like
    /// free space, used space, block size, etc.
    fn query_filesystem(&self) -> Result<Box<fio::FilesystemInfo>, Error> {
        let (client_chan, server_chan) = zx::Channel::create()?;

        let namespace = Namespace::installed().context("failed to get installed namespace")?;
        namespace
            .connect(&self.mount_point, fio::OpenFlags::RIGHT_READABLE, server_chan)
            .context("failed to connect to filesystem")?;

        let proxy = fio::DirectorySynchronousProxy::new(client_chan);

        let (status, result) = proxy
            .query_filesystem(zx::Time::INFINITE)
            .context("failed to query filesystem info")?;
        zx_status::Status::ok(status).context("failed to query filesystem info")?;
        result.ok_or(format_err!("querying filesystem info got empty result"))
    }

    /// Terminate the filesystem process and force unmount the mount point
    fn kill(self) -> Result<(), Error> {
        let namespace = Namespace::installed().context("failed to get installed namespace")?;
        namespace
            .unbind(&self.mount_point)
            .context("failed to unbind filesystem from default namespace")?;

        self.process.kill().context("Could not kill filesystem process")
    }
}

fn launch_process(
    args: &[&CStr],
    mut actions: Vec<SpawnAction<'_>>,
) -> Result<zx::Process, LaunchProcessError> {
    match spawn_etc(
        &zx::Handle::invalid().into(),
        SpawnOptions::CLONE_ALL,
        args[0],
        args,
        None,
        &mut actions,
    ) {
        Ok(process) => Ok(process),
        Err((status, message)) => Err(LaunchProcessError {
            args: args.iter().map(|&a| a.to_owned()).collect(),
            status,
            message,
        }),
    }
}

fn run_command_and_wait_for_clean_exit(
    args: Vec<&CStr>,
    block_device: zx::Channel,
    crypt_client: Option<zx::Channel>,
) -> Result<(), Error> {
    let mut actions = vec![
        // device handle is passed in as a PA_USER0 handle at argument 1
        SpawnAction::add_handle(HandleInfo::new(HandleType::User0, 1), block_device.into()),
    ];
    if let Some(crypt_client) = crypt_client {
        actions.push(SpawnAction::add_handle(
            HandleInfo::new(HandleType::User0, 2),
            crypt_client.into(),
        ));
    }

    let process = launch_process(&args, actions)?;

    let _signals = process
        .wait_handle(zx::Signals::PROCESS_TERMINATED, zx::Time::INFINITE)
        .context(format!("failed to wait for process to complete"))?;

    let info = process.info().context("failed to get process info")?;
    if !zx::ProcessInfoFlags::from_bits(info.flags).unwrap().contains(zx::ProcessInfoFlags::EXITED)
        || info.return_code != 0
    {
        bail!("process returned non-zero exit code ({})", info.return_code);
    }

    Ok(())
}

/// Describes the configuration for a particular native filesystem.
pub trait FSConfig {
    /// If the filesystem runs as a component, Returns the component name in which case the
    /// binary_path, and the _args methods are not relevant.
    fn component_name(&self) -> Option<&str> {
        None
    }

    /// Path to the filesystem binary
    fn binary_path(&self) -> &CStr;

    /// Arguments passed to the binary for all subcommands
    fn generic_args(&self) -> Vec<&CStr> {
        vec![]
    }

    /// Arguments passed to the binary for formatting
    fn format_args(&self) -> Vec<&CStr> {
        vec![]
    }

    /// Arguments passed to the binary for mounting
    fn mount_args(&self) -> Vec<&CStr> {
        vec![]
    }

    /// Returns a handle for the crypt service (if any).
    fn crypt_client(&self) -> Option<zx::Channel> {
        // By default, filesystems don't need a crypt service.
        None
    }
}

/// Manages a block device for filesystem operations
pub struct Filesystem<FSC: FSConfig> {
    device: fio::NodeSynchronousProxy,
    config: FSC,
    instance: Option<FSInstance>,
}

impl<FSC: FSConfig> Filesystem<FSC> {
    /// Manage a filesystem on a device at the given path. The device is not formatted, mounted, or
    /// modified at this point.
    pub fn from_path(device_path: &str, config: FSC) -> Result<Self, Error> {
        let (client_end, server_end) = zx::Channel::create()?;
        fdio::service_connect(device_path, server_end)
            .context("could not connect to block device")?;
        Self::from_channel(client_end, config)
    }

    /// Manage a filesystem on a device at the given channel. The device is not formatted, mounted,
    /// or modified at this point.
    pub fn from_channel(client_end: zx::Channel, config: FSC) -> Result<Self, Error> {
        let device = fio::NodeSynchronousProxy::new(client_end);
        Ok(Self { device, config, instance: None })
    }

    /// Returns a channel to the block device.
    fn get_channel(&mut self) -> Result<zx::Channel, Error> {
        let (channel, server) = zx::Channel::create()?;
        let () = self
            .device
            .clone(fio::OpenFlags::CLONE_SAME_RIGHTS, fidl::endpoints::ServerEnd::new(server))?;
        Ok(channel)
    }

    /// Mount the provided block device and bind it to the provided mount_point in the default
    /// namespace. The filesystem can't already be mounted, and the mount will fail if the provided
    /// mount path doesn't already exist. The path is relative to the root of the default namespace,
    /// and can't contain any '.' or '..' entries.
    pub fn mount(&mut self, mount_point: &str) -> Result<(), Error> {
        if self.instance.is_some() {
            bail!("cannot mount. filesystem is already mounted");
        }
        if self.config.component_name().is_some() {
            bail!("Not supported");
        }

        let block_device = self.get_channel()?;

        let mut args = vec![self.config.binary_path()];
        args.append(&mut self.config.generic_args());
        args.push(cstr!("mount"));
        args.append(&mut self.config.mount_args());

        self.instance =
            Some(FSInstance::mount(block_device, args, mount_point, self.config.crypt_client())?);

        Ok(())
    }

    /// Format the associated device with a fresh filesystem. It must not be mounted.
    pub fn format(&mut self) -> Result<(), Error> {
        if self.instance.is_some() {
            bail!("cannot format! filesystem is mounted");
        }
        if self.config.component_name().is_some() {
            bail!("Not supported");
        }

        let block_device = self.get_channel()?;

        let mut args = vec![self.config.binary_path()];
        args.append(&mut self.config.generic_args());
        args.push(cstr!("mkfs"));
        args.append(&mut self.config.format_args());

        run_command_and_wait_for_clean_exit(args, block_device, self.config.crypt_client())
            .context("failed to format device")
    }

    /// Run fsck on the filesystem partition. Returns Ok(()) if fsck succeeds, or the associated
    /// error if it doesn't. Will fail if run on a mounted partition.
    pub fn fsck(&mut self) -> Result<(), Error> {
        if self.instance.is_some() {
            bail!("cannot fsck! filesystem is mounted");
        }
        if self.config.component_name().is_some() {
            bail!("Not supported");
        }

        let block_device = self.get_channel()?;

        let mut args = vec![self.config.binary_path()];
        args.append(&mut self.config.generic_args());
        args.push(cstr!("fsck"));

        run_command_and_wait_for_clean_exit(args, block_device, self.config.crypt_client())
            .context("failed to fsck device")
    }

    /// Unmount the filesystem partition. The partition must already be mounted.
    pub fn unmount(&mut self) -> Result<(), Error> {
        if let Some(instance) = self.instance.take() {
            instance.unmount()
        } else {
            Err(format_err!("cannot unmount. filesystem is not mounted"))
        }
    }

    /// Get `FileSystemInfo` struct from which one can find out things like
    /// free space, used space, block size, etc.
    pub fn query_filesystem(&self) -> Result<Box<fio::FilesystemInfo>, Error> {
        if let Some(instance) = &self.instance {
            instance.query_filesystem()
        } else {
            Err(format_err!("cannot query filesystem. filesystem is not mounted"))
        }
    }

    /// Terminate the filesystem process and force unmount the mount point
    pub fn kill(&mut self) -> Result<(), Error> {
        if let Some(instance) = self.instance.take() {
            instance.kill()
        } else {
            Err(format_err!("cannot kill. filesystem is not mounted"))
        }
    }
}

impl<FSC: FSConfig> Drop for Filesystem<FSC> {
    fn drop(&mut self) {
        if self.instance.is_some() {
            // Unmount if possible.
            let _ = self.unmount();
        }
    }
}

///
/// FILESYSTEMS
///

/// Layout of blobs in blobfs
#[derive(Clone)]
pub enum BlobLayout {
    /// Merkle tree is stored in a separate block. This is deprecated and used only on Astro
    /// devices (it takes more space).
    DeprecatedPadded,

    /// Merkle tree is appended to the last block of data
    Compact,
}

/// Compression used for blobs in blobfs
#[derive(Clone)]
pub enum BlobCompression {
    ZSTD,
    ZSTDSeekable,
    ZSTDChunked,
    Uncompressed,
}

/// Eviction policy used for blobs in blobfs
#[derive(Clone)]
pub enum BlobEvictionPolicy {
    NeverEvict,
    EvictImmediately,
}

/// Blobfs Filesystem Configuration
/// If fields are None or false, they will not be set in arguments.
#[derive(Clone, Default)]
pub struct Blobfs {
    pub verbose: bool,
    pub readonly: bool,
    pub blob_deprecated_padded_format: bool,
    pub blob_compression: Option<BlobCompression>,
    pub blob_eviction_policy: Option<BlobEvictionPolicy>,
}

impl Blobfs {
    /// Manages a block device at a given path using
    /// the default configuration.
    pub fn new(path: &str) -> Result<Filesystem<Self>, Error> {
        Filesystem::from_path(path, Self::default())
    }

    /// Manages a block device at a given channel using
    /// the default configuration.
    pub fn from_channel(channel: zx::Channel) -> Result<Filesystem<Self>, Error> {
        Filesystem::from_channel(channel, Self::default())
    }
}

impl FSConfig for Blobfs {
    fn binary_path(&self) -> &CStr {
        cstr!("/pkg/bin/blobfs")
    }
    fn generic_args(&self) -> Vec<&CStr> {
        let mut args = vec![];
        if self.verbose {
            args.push(cstr!("--verbose"));
        }
        args
    }
    fn format_args(&self) -> Vec<&CStr> {
        let mut args = vec![];
        if self.blob_deprecated_padded_format {
            args.push(cstr!("--deprecated_padded_format"));
        }
        args
    }
    fn mount_args(&self) -> Vec<&CStr> {
        let mut args = vec![];
        if self.readonly {
            args.push(cstr!("--readonly"));
        }
        if let Some(compression) = &self.blob_compression {
            args.push(cstr!("--compression"));
            args.push(match compression {
                BlobCompression::ZSTD => cstr!("ZSTD"),
                BlobCompression::ZSTDSeekable => cstr!("ZSTD_SEEKABLE"),
                BlobCompression::ZSTDChunked => cstr!("ZSTD_CHUNKED"),
                BlobCompression::Uncompressed => cstr!("UNCOMPRESSED"),
            });
        }
        if let Some(eviction_policy) = &self.blob_eviction_policy {
            args.push(cstr!("--eviction_policy"));
            args.push(match eviction_policy {
                BlobEvictionPolicy::NeverEvict => cstr!("NEVER_EVICT"),
                BlobEvictionPolicy::EvictImmediately => cstr!("EVICT_IMMEDIATELY"),
            })
        }
        args
    }
}

/// Minfs Filesystem Configuration
/// If fields are None or false, they will not be set in arguments.
#[derive(Clone, Default)]
pub struct Minfs {
    // TODO(xbhatnag): Add support for fvm_data_slices
    pub verbose: bool,
    pub readonly: bool,
    pub fsck_after_every_transaction: bool,
}

impl Minfs {
    /// Manages a block device at a given path using
    /// the default configuration.
    pub fn new(path: &str) -> Result<Filesystem<Self>, Error> {
        Filesystem::from_path(path, Self::default())
    }

    /// Manages a block device at a given channel using
    /// the default configuration.
    pub fn from_channel(channel: zx::Channel) -> Result<Filesystem<Self>, Error> {
        Filesystem::from_channel(channel, Self::default())
    }
}

impl FSConfig for Minfs {
    fn binary_path(&self) -> &CStr {
        cstr!("/pkg/bin/minfs")
    }
    fn generic_args(&self) -> Vec<&CStr> {
        let mut args = vec![];
        if self.verbose {
            args.push(cstr!("--verbose"));
        }
        args
    }
    fn mount_args(&self) -> Vec<&CStr> {
        let mut args = vec![];
        if self.readonly {
            args.push(cstr!("--readonly"));
        }
        if self.fsck_after_every_transaction {
            args.push(cstr!("--fsck_after_every_transaction"));
        }
        args
    }
}

type CryptClientFn = Arc<dyn Fn() -> zx::Channel + Send + Sync>;

/// Fxfs Filesystem Configuration
/// If fields are None or false, they will not be set in arguments.
#[derive(Clone)]
pub struct Fxfs {
    pub verbose: bool,
    pub readonly: bool,
    pub crypt_client_fn: CryptClientFn,
}

impl Fxfs {
    pub fn with_crypt_client(crypt_client_fn: CryptClientFn) -> Self {
        Fxfs { verbose: false, readonly: false, crypt_client_fn }
    }

    /// Manages a block device at a given path using
    /// the default configuration.
    pub fn new(path: &str, crypt_client_fn: CryptClientFn) -> Result<Filesystem<Self>, Error> {
        Filesystem::from_path(path, Self::with_crypt_client(crypt_client_fn))
    }

    /// Manages a block device at a given channel using
    /// the default configuration.
    pub fn from_channel(
        channel: zx::Channel,
        crypt_client_fn: CryptClientFn,
    ) -> Result<Filesystem<Self>, Error> {
        Filesystem::from_channel(channel, Self::with_crypt_client(crypt_client_fn))
    }
}

impl FSConfig for Fxfs {
    fn component_name(&self) -> Option<&str> {
        Some("fxfs")
    }
    fn binary_path(&self) -> &CStr {
        cstr!("")
    }
    fn crypt_client(&self) -> Option<zx::Channel> {
        Some((self.crypt_client_fn)())
    }
}

/// Factoryfs Filesystem Configuration
/// If fields are None or false, they will not be set in arguments.
#[derive(Clone, Default)]
pub struct Factoryfs {
    pub verbose: bool,
}

impl Factoryfs {
    /// Manages a block device at a given path using
    /// the default configuration.
    pub fn new(path: &str) -> Result<Filesystem<Self>, Error> {
        Filesystem::from_path(path, Self::default())
    }

    /// Manages a block device at a given channel using
    /// the default configuration.
    pub fn from_channel(channel: zx::Channel) -> Result<Filesystem<Self>, Error> {
        Filesystem::from_channel(channel, Self::default())
    }
}

impl FSConfig for Factoryfs {
    fn binary_path(&self) -> &CStr {
        cstr!("/pkg/bin/factoryfs")
    }
    fn generic_args(&self) -> Vec<&CStr> {
        let mut args = vec![];
        if self.verbose {
            args.push(cstr!("--verbose"));
        }
        args
    }
}

#[cfg(test)]
mod tests {
    use {
        super::{BlobCompression, BlobEvictionPolicy, Blobfs, Factoryfs, Filesystem, Minfs},
        fuchsia_zircon::HandleBased,
        ramdevice_client::RamdiskClient,
        std::io::{Read, Seek, Write},
    };

    fn ramdisk(block_size: u64) -> RamdiskClient {
        ramdevice_client::wait_for_device(
            "/dev/sys/platform/00:00:2d/ramctl",
            std::time::Duration::from_secs(60),
        )
        .unwrap();
        RamdiskClient::create(block_size, 1 << 16).unwrap()
    }

    fn blobfs(ramdisk: &RamdiskClient) -> Filesystem<Blobfs> {
        let device = ramdisk.open().unwrap();
        Blobfs::from_channel(device).unwrap()
    }

    #[test]
    fn blobfs_custom_config() {
        let block_size = 512;
        let mount_point = "/test-fs-root";

        let ramdisk = ramdisk(block_size);
        let device = ramdisk.open().unwrap();
        let config = Blobfs {
            verbose: true,
            readonly: true,
            blob_deprecated_padded_format: false,
            blob_compression: Some(BlobCompression::Uncompressed),
            blob_eviction_policy: Some(BlobEvictionPolicy::EvictImmediately),
        };
        let mut blobfs = Filesystem::from_channel(device, config).unwrap();

        blobfs.format().expect("failed to format blobfs");
        blobfs.fsck().expect("failed to fsck blobfs");
        blobfs.mount(mount_point).expect("failed to mount blobfs");

        ramdisk.destroy().expect("failed to destroy ramdisk");
    }

    #[test]
    fn blobfs_format_fsck_success() {
        let block_size = 512;
        let ramdisk = ramdisk(block_size);
        let mut blobfs = blobfs(&ramdisk);

        blobfs.format().expect("failed to format blobfs");
        blobfs.fsck().expect("failed to fsck blobfs");

        ramdisk.destroy().expect("failed to destroy ramdisk");
    }

    #[test]
    fn blobfs_format_fsck_error() {
        let block_size = 512;
        let ramdisk = ramdisk(block_size);
        let mut blobfs = blobfs(&ramdisk);

        blobfs.format().expect("failed to format blobfs");

        // force fsck to fail by stomping all over one of blobfs's metadata blocks after formatting
        // TODO(fxbug.dev/35860): corrupt something other than the superblock
        let device_channel = ramdisk.open().expect("failed to get channel to device");
        let mut file = fdio::create_fd::<std::fs::File>(device_channel.into_handle())
            .expect("failed to convert to file descriptor");
        let mut bytes: Vec<u8> = std::iter::repeat(0xff).take(block_size as usize).collect();
        file.write_all(&mut bytes).expect("failed to write to device");

        blobfs.fsck().expect_err("fsck succeeded when it shouldn't have");

        ramdisk.destroy().expect("failed to destroy ramdisk");
    }

    #[test]
    fn blobfs_format_mount_write_query_remount_read_unmount() {
        let block_size = 512;
        let mount_point = "/test-fs-root";
        let ramdisk = ramdisk(block_size);
        let mut blobfs = blobfs(&ramdisk);

        blobfs.format().expect("failed to format blobfs");
        blobfs.mount(mount_point).expect("failed to mount blobfs the first time");

        // snapshot of FilesystemInfo
        let fs_info1 =
            blobfs.query_filesystem().expect("failed to query filesystem info after first mount");

        // pre-generated merkle test fixture data
        let merkle = "be901a14ec42ee0a8ee220eb119294cdd40d26d573139ee3d51e4430e7d08c28";
        let content = String::from("test content").into_bytes();
        let path = format!("{}/{}", mount_point, merkle);

        {
            let mut test_file = std::fs::File::create(&path).expect("failed to create test file");
            test_file.set_len(content.len() as u64).expect("failed to truncate file");
            test_file.write_all(&content).expect("failed to write to test file");
        }

        // check against the snapshot FilesystemInfo
        let fs_info2 =
            blobfs.query_filesystem().expect("failed to query filesystem info after write");
        assert_eq!(
            fs_info2.used_bytes - fs_info1.used_bytes,
            fs_info2.block_size as u64 // assuming content < 8K
        );

        blobfs.unmount().expect("failed to unmount blobfs the first time");

        blobfs
            .query_filesystem()
            .expect_err("filesystem query on an unmounted filesystem didn't fail");

        blobfs.mount(mount_point).expect("failed to mount blobfs the second time");

        {
            let mut test_file = std::fs::File::open(&path).expect("failed to open test file");
            let mut read_content = Vec::new();
            test_file.read_to_end(&mut read_content).expect("failed to read from test file");
            assert_eq!(content, read_content);
        }

        // once more check against the snapshot FilesystemInfo
        let fs_info3 =
            blobfs.query_filesystem().expect("failed to query filesystem info after read");
        assert_eq!(
            fs_info3.used_bytes - fs_info1.used_bytes,
            fs_info3.block_size as u64 // assuming content < 8K
        );

        blobfs.unmount().expect("failed to unmount blobfs the second time");

        ramdisk.destroy().expect("failed to destroy ramdisk");
    }

    fn minfs(ramdisk: &RamdiskClient) -> Filesystem<Minfs> {
        let device = ramdisk.open().unwrap();
        Minfs::from_channel(device).unwrap()
    }

    #[test]
    fn minfs_custom_config() {
        let block_size = 512;
        let mount_point = "/test-fs-root";

        let ramdisk = ramdisk(block_size);
        let device = ramdisk.open().unwrap();
        let config = Minfs { verbose: true, readonly: true, fsck_after_every_transaction: true };
        let mut minfs = Filesystem::from_channel(device, config).unwrap();

        minfs.format().expect("failed to format minfs");
        minfs.fsck().expect("failed to fsck minfs");
        minfs.mount(mount_point).expect("failed to mount minfs");

        ramdisk.destroy().expect("failed to destroy ramdisk");
    }

    #[test]
    fn minfs_format_fsck_success() {
        let block_size = 8192;
        let ramdisk = ramdisk(block_size);
        let mut minfs = minfs(&ramdisk);

        minfs.format().expect("failed to format minfs");
        minfs.fsck().expect("failed to fsck minfs");

        ramdisk.destroy().expect("failed to destroy ramdisk");
    }

    #[test]
    fn minfs_format_fsck_error() {
        let block_size = 8192;
        let ramdisk = ramdisk(block_size);
        let mut minfs = minfs(&ramdisk);

        minfs.format().expect("failed to format minfs");

        // force fsck to fail by stomping all over one of minfs's metadata blocks after formatting
        let device_channel = ramdisk.open().expect("failed to get channel to device");
        let mut file = fdio::create_fd::<std::fs::File>(device_channel.into_handle())
            .expect("failed to convert to file descriptor");

        // when minfs isn't on an fvm, the location for it's bitmap offset is the 8th block.
        // TODO(fxbug.dev/35861): parse the superblock for this offset and the block size.
        let bitmap_block_offset = 8;
        let bitmap_offset = block_size * bitmap_block_offset;

        let mut stomping_bytes: Vec<u8> =
            std::iter::repeat(0xff).take(block_size as usize).collect();
        let actual_offset =
            file.seek(std::io::SeekFrom::Start(bitmap_offset)).expect("failed to seek to bitmap");
        assert_eq!(actual_offset, bitmap_offset);
        file.write_all(&mut stomping_bytes).expect("failed to write to device");

        minfs.fsck().expect_err("fsck succeeded when it shouldn't have");

        ramdisk.destroy().expect("failed to destroy ramdisk");
    }

    #[test]
    fn minfs_format_mount_write_query_remount_read_unmount() {
        let block_size = 8192;
        let mount_point = "/test-fs-root";
        let ramdisk = ramdisk(block_size);
        let mut minfs = minfs(&ramdisk);

        minfs.format().expect("failed to format minfs");
        minfs.mount(mount_point).expect("failed to mount minfs the first time");

        // snapshot of FilesystemInfo
        let fs_info1 =
            minfs.query_filesystem().expect("failed to query filesystem info after first mount");

        let filename = "test_file";
        let content = String::from("test content").into_bytes();
        let path = format!("{}/{}", mount_point, filename);

        {
            let mut test_file = std::fs::File::create(&path).expect("failed to create test file");
            test_file.write_all(&content).expect("failed to write to test file");
        }

        // check against the snapshot FilesystemInfo
        let fs_info2 =
            minfs.query_filesystem().expect("failed to query filesystem info after write");
        assert_eq!(
            fs_info2.used_bytes - fs_info1.used_bytes,
            fs_info2.block_size as u64 // assuming content < 8K
        );

        minfs.unmount().expect("failed to unmount minfs the first time");

        minfs
            .query_filesystem()
            .expect_err("filesystem query on an unmounted filesystem didn't fail");

        minfs.mount(mount_point).expect("failed to mount minfs the second time");

        {
            let mut test_file = std::fs::File::open(&path).expect("failed to open test file");
            let mut read_content = Vec::new();
            test_file.read_to_end(&mut read_content).expect("failed to read from test file");
            assert_eq!(content, read_content);
        }

        // once more check against the snapshot FilesystemInfo
        let fs_info3 =
            minfs.query_filesystem().expect("failed to query filesystem info after read");
        assert_eq!(
            fs_info3.used_bytes - fs_info1.used_bytes,
            fs_info3.block_size as u64 // assuming content < 8K
        );

        minfs.unmount().expect("failed to unmount minfs the second time");

        ramdisk.destroy().expect("failed to destroy ramdisk");
    }

    fn factoryfs(ramdisk: &RamdiskClient) -> Filesystem<Factoryfs> {
        let device = ramdisk.open().unwrap();
        Factoryfs::from_channel(device).unwrap()
    }

    #[test]
    fn factoryfs_custom_config() {
        let block_size = 512;
        let mount_point = "/test-fs-root";

        let ramdisk = ramdisk(block_size);
        let device = ramdisk.open().unwrap();
        let config = Factoryfs { verbose: true };
        let mut factoryfs = Filesystem::from_channel(device, config).unwrap();

        factoryfs.format().expect("failed to format factoryfs");
        factoryfs.fsck().expect("failed to fsck factoryfs");
        factoryfs.mount(mount_point).expect("failed to mount factoryfs");

        ramdisk.destroy().expect("failed to destroy ramdisk");
    }

    #[test]
    fn factoryfs_format_fsck_success() {
        let block_size = 512;
        let ramdisk = ramdisk(block_size);
        let mut factoryfs = factoryfs(&ramdisk);

        factoryfs.format().expect("failed to format factoryfs");
        factoryfs.fsck().expect("failed to fsck factoryfs");

        ramdisk.destroy().expect("failed to destroy ramdisk");
    }

    #[test]
    fn factoryfs_format_mount_unmount() {
        let block_size = 512;
        let mount_point = "/test-fs-root";
        let ramdisk = ramdisk(block_size);
        let mut factoryfs = factoryfs(&ramdisk);

        factoryfs.format().expect("failed to format factoryfs");
        factoryfs.mount(mount_point).expect("failed to mount factoryfs");
        factoryfs.unmount().expect("failed to unmount factoryfs");

        ramdisk.destroy().expect("failed to destroy ramdisk");
    }
}
