summaryrefslogtreecommitdiff
path: root/rust-src/src/cmd_mount.rs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-01-03 22:31:36 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-02-21 01:03:08 -0500
commit28f703cc256fb6ae209aba1d1fe509d603de1735 (patch)
tree220fc0e14cd29a3b56fe18dc8594d7bb4fe66718 /rust-src/src/cmd_mount.rs
parentda6a35689518599b381c285cd9505ab8d58f7c73 (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.rs99
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);
+ }
+}