liteboxfs 0.2.0

A modern POSIX filesystem in a SQLite database
Documentation
use std::{convert::Infallible, str::FromStr};

/// A mount option accepted when mounting a FUSE file system.
///
/// You can mount a litebox as a FUSE file system with [`Connection::mount`].
///
/// See `man mount.fuse` for details.
///
/// [`Connection::mount`]: crate::Connection::mount
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum MountOption {
    /// Set the name of the source in mtab.
    FsName(String),

    /// Set the filesystem subtype in mtab.
    Subtype(String),

    /// Enforce file permissions.
    DefaultPermissions,

    /// Allow all users to access files on this filesystem. By default access is restricted to the
    /// user who mounted it.
    AllowOther,

    /// Allow the root user to access this filesystem in addition to the user who mounted it.
    AllowRoot,

    /// Automatically unmount when the mounting process exits.
    ///
    /// `AutoUnmount` requires `AllowOther` or `AllowRoot`. If `AutoUnmount` is set and neither of
    /// those is set, the FUSE configuration must permit `allow_other`, otherwise mounting will
    /// fail.
    AutoUnmount,

    /// Enable special character and block devices.
    Dev,

    /// Disable special character and block devices.
    NoDev,

    /// Honor set-user-id and set-group-id bits on files.
    Suid,

    /// Don't honor set-user-id and set-groupd-id bits on files.
    NoSuid,

    /// Mount the filesystem read-only.
    Ro,

    /// Mount the filesystem read-write.
    Rw,

    /// Allow execution of binaries.
    Exec,

    /// Don't allow execution of binaries.
    NoExec,

    /// Support inode access time.
    Atime,

    /// Don't update inode access time.
    NoAtime,

    /// All modifications to directories will be done synchronously.
    DirSync,

    /// All I/O will be done synchronously.
    Sync,

    /// All I/O will be done asynchronously.
    Async,

    /// Pass an option which is not otherwise supported in this enum.
    Custom(String),
}

impl FromStr for MountOption {
    type Err = Infallible;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(match s {
            "default_permissions" => Self::DefaultPermissions,
            "allow_other" => Self::AllowOther,
            "allow_root" => Self::AllowRoot,
            "auto_unmount" => Self::AutoUnmount,
            "dev" => Self::Dev,
            "nodev" => Self::NoDev,
            "suid" => Self::Suid,
            "nosuid" => Self::NoSuid,
            "ro" => Self::Ro,
            "rw" => Self::Rw,
            "exec" => Self::Exec,
            "noexec" => Self::NoExec,
            "atime" => Self::Atime,
            "noatime" => Self::NoAtime,
            "dirsync" => Self::DirSync,
            "sync" => Self::Sync,
            "async" => Self::Async,
            _ if s.starts_with("fsname=") => {
                let name = s.trim_start_matches("fsname=").to_owned();
                Self::FsName(name)
            }
            _ if s.starts_with("subtype=") => {
                let subtype = s.trim_start_matches("subtype=").to_owned();
                Self::Subtype(subtype)
            }
            _ => Self::Custom(s.to_owned()),
        })
    }
}

impl MountOption {
    pub(crate) fn into_fuser(self) -> fuser::MountOption {
        match self {
            Self::FsName(name) => fuser::MountOption::FSName(name),
            Self::Subtype(subtype) => fuser::MountOption::Subtype(subtype),
            Self::DefaultPermissions => fuser::MountOption::DefaultPermissions,
            Self::AllowOther => unreachable!(),
            Self::AllowRoot => unreachable!(),
            Self::AutoUnmount => fuser::MountOption::AutoUnmount,
            Self::Dev => fuser::MountOption::Dev,
            Self::NoDev => fuser::MountOption::NoDev,
            Self::Suid => fuser::MountOption::Suid,
            Self::NoSuid => fuser::MountOption::NoSuid,
            Self::Ro => fuser::MountOption::RO,
            Self::Rw => fuser::MountOption::RW,
            Self::Exec => fuser::MountOption::Exec,
            Self::NoExec => fuser::MountOption::NoExec,
            Self::Atime => fuser::MountOption::Atime,
            Self::NoAtime => fuser::MountOption::NoAtime,
            Self::DirSync => fuser::MountOption::DirSync,
            Self::Sync => fuser::MountOption::Sync,
            Self::Async => fuser::MountOption::Async,
            Self::Custom(option) => fuser::MountOption::CUSTOM(option),
        }
    }
}