diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-01-03 22:31:36 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-02-21 01:03:08 -0500 |
commit | 28f703cc256fb6ae209aba1d1fe509d603de1735 (patch) | |
tree | 220fc0e14cd29a3b56fe18dc8594d7bb4fe66718 /rust-src/src/cmd_mount.rs | |
parent | da6a35689518599b381c285cd9505ab8d58f7c73 (diff) |
Rust now integrated into bcachefs binary
Rust is now required for building the bcachefs tool, and rust code is
now fully integrated with the C codebase - meaning it is possible to
call back and forth.
The mount helper is now a subcommand, 'mount.bcachefs' is now a small
shell wrapper that invokes 'bcachefs mount'.
This will make it easier to start rewriting other subcommands in rust,
and eventually the whole command line interface.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'rust-src/src/cmd_mount.rs')
-rw-r--r-- | rust-src/src/cmd_mount.rs | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/rust-src/src/cmd_mount.rs b/rust-src/src/cmd_mount.rs new file mode 100644 index 00000000..7748b199 --- /dev/null +++ b/rust-src/src/cmd_mount.rs @@ -0,0 +1,99 @@ +use bch_bindgen::{error, info}; +use clap::Parser; +use colored::Colorize; +use atty::Stream; +use uuid::Uuid; +use crate::filesystem; +use crate::key; +use crate::key::KeyLoc; + +fn parse_fstab_uuid(uuid_raw: &str) -> Result<Uuid, uuid::Error> { + let mut uuid = String::from(uuid_raw); + if uuid.starts_with("UUID=") { + uuid = uuid.replacen("UUID=", "", 1); + } + return Uuid::parse_str(&uuid); +} + +fn stdout_isatty() -> &'static str { + if atty::is(Stream::Stdout) { + "true" + } else { + "false" + } +} + +/// Mount a bcachefs filesystem by its UUID. +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +pub struct Cli { + /// Where the password would be loaded from. + /// + /// Possible values are: + /// "fail" - don't ask for password, fail if filesystem is encrypted; + /// "wait" - wait for password to become available before mounting; + /// "ask" - prompt the user for password; + #[arg(short, long, default_value = "", verbatim_doc_comment)] + pub key_location: KeyLoc, + + /// External UUID of the bcachefs filesystem + /// + /// Accepts the UUID as is or as fstab style UUID=<UUID> + #[arg(value_parser = parse_fstab_uuid)] + pub uuid: uuid::Uuid, + + /// Where the filesystem should be mounted. If not set, then the filesystem + /// won't actually be mounted. But all steps preceeding mounting the + /// filesystem (e.g. asking for passphrase) will still be performed. + pub mountpoint: Option<std::path::PathBuf>, + + /// Mount options + #[arg(short, default_value = "")] + pub options: String, + + /// Force color on/off. Default: autodetect tty + #[arg(short, long, action = clap::ArgAction::Set, default_value=stdout_isatty())] + pub colorize: bool, + + #[arg(short = 'v', long, action = clap::ArgAction::Count)] + pub verbose: u8, +} + +pub fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> { + unsafe { + libc::setvbuf(filesystem::stdout, std::ptr::null_mut(), libc::_IONBF, 0); + } + + let fss = filesystem::probe_filesystems()?; + let fs = fss + .get(&opt.uuid) + .ok_or_else(|| anyhow::anyhow!("filesystem was not found"))?; + + info!("found filesystem {}", fs); + if fs.encrypted() { + let key = opt + .key_location + .0 + .ok_or_else(|| anyhow::anyhow!("no keyoption specified for locked filesystem"))?; + + key::prepare_key(&fs, key)?; + } + + let mountpoint = opt + .mountpoint + .ok_or_else(|| anyhow::anyhow!("mountpoint option was not specified"))?; + + fs.mount(&mountpoint, &opt.options)?; + + Ok(()) +} + +#[no_mangle] +pub extern "C" fn cmd_mount() { + let opt = Cli::parse(); + bch_bindgen::log::set_verbose_level(opt.verbose + bch_bindgen::log::ERROR); + colored::control::set_override(opt.colorize); + if let Err(e) = cmd_mount_inner(opt) { + error!("Fatal error: {}", e); + } +} |