// 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, 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()?;

        service_connect(&self.mount_point, 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()?;
        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");
    }
}
