]> git.sesse.net Git - bcachefs-tools-debian/blobdiff - rust-src/src/cmd_mount.rs
New upstream release
[bcachefs-tools-debian] / rust-src / src / cmd_mount.rs
index 0150ffd5ab1bf9581a03f6ae138c684681493a3f..17a289ca98c8eb866db4e195ff4e77263cbb54a6 100644 (file)
@@ -1,11 +1,11 @@
 use atty::Stream;
 use bch_bindgen::{bcachefs, bcachefs::bch_sb_handle};
 use log::{info, debug, error, LevelFilter};
-use clap::Parser;
+use clap::{Parser, Subcommand};
 use uuid::Uuid;
 use std::path::PathBuf;
-use crate::key;
-use crate::key::KeyLoc;
+use crate::{key, transform_c_args};
+use crate::key::KeyLocation;
 use crate::logger::SimpleLogger;
 use std::ffi::{CStr, CString, OsStr, c_int, c_char, c_void};
 use std::os::unix::ffi::OsStrExt;
@@ -14,7 +14,7 @@ fn mount_inner(
     src: String,
     target: impl AsRef<std::path::Path>,
     fstype: &str,
-    mountflags: u64,
+    mountflags: libc::c_ulong,
     data: Option<String>,
 ) -> anyhow::Result<()> {
 
@@ -45,7 +45,7 @@ fn mount_inner(
 
 /// Parse a comma-separated mount options and split out mountflags and filesystem
 /// specific options.
-fn parse_mount_options(options: impl AsRef<str>) -> (Option<String>, u64) {
+fn parse_mount_options(options: impl AsRef<str>) -> (Option<String>, libc::c_ulong) {
     use either::Either::*;
     debug!("parsing mount options: {}", options.as_ref());
     let (opts, flags) = options
@@ -129,7 +129,7 @@ fn get_devices_by_uuid(uuid: Uuid) -> anyhow::Result<Vec<(PathBuf, bch_sb_handle
 /// Mount a bcachefs filesystem by its UUID.
 #[derive(Parser, Debug)]
 #[command(author, version, about, long_about = None)]
-struct Cli {
+pub struct Cli {
     /// Where the password would be loaded from.
     ///
     /// Possible values are:
@@ -137,7 +137,7 @@ struct Cli {
     /// "wait" - wait for password to become available before mounting;
     /// "ask" -  prompt the user for password;
     #[arg(short, long, default_value = "ask", verbatim_doc_comment)]
-    key_location:   KeyLoc,
+    key_location:   KeyLocation,
 
     /// Device, or UUID=<UUID>
     dev:            String,
@@ -145,7 +145,7 @@ struct Cli {
     /// 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.
-    mountpoint:     std::path::PathBuf,
+    mountpoint:     Option<std::path::PathBuf>,
 
     /// Mount options
     #[arg(short, default_value = "")]
@@ -199,34 +199,35 @@ fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> {
     if sbs.len() == 0 {
         Err(anyhow::anyhow!("No device found from specified parameters"))?;
     } else if unsafe { bcachefs::bch2_sb_is_encrypted(sbs[0].sb) } {
-        let key = opt
-            .key_location
-            .0
-            .ok_or_else(|| anyhow::anyhow!("no keyoption specified for locked filesystem"))?;
-
-        key::prepare_key(&sbs[0], key)?;
+        key::prepare_key(&sbs[0], opt.key_location)?;
     }
 
-    info!(
-        "mounting with params: device: {}, target: {}, options: {}",
-        devs,
-        &opt.mountpoint.to_string_lossy(),
-        &opt.options
-    );
+    if let Some(mountpoint) = opt.mountpoint {
+        info!(
+            "mounting with params: device: {}, target: {}, options: {}",
+            devs,
+            mountpoint.to_string_lossy(),
+            &opt.options
+        );
+
+        mount(devs, mountpoint, &opt.options)?;
+    } else {
+        info!(
+            "would mount with params: device: {}, options: {}",
+            devs,
+            &opt.options
+        );
+    }
 
-    mount(devs, &opt.mountpoint, &opt.options)?;
     Ok(())
 }
 
 #[no_mangle]
-pub extern "C" fn cmd_mount(argc: c_int, argv: *const *const c_char) {
-    let argv: Vec<_> = (0..argc)
-        .map(|i| unsafe { CStr::from_ptr(*argv.add(i as usize)) })
-        .map(|i| OsStr::from_bytes(i.to_bytes()))
-        .collect();
-
+#[allow(clippy::not_unsafe_ptr_arg_deref)]
+pub extern "C" fn cmd_mount(argc: c_int, argv: *const *const c_char) -> c_int {
+    transform_c_args!(argv, argc, argv);
     let opt = Cli::parse_from(argv);
-    
+
     log::set_boxed_logger(Box::new(SimpleLogger)).unwrap();
 
     // @TODO : more granular log levels via mount option
@@ -239,7 +240,9 @@ pub extern "C" fn cmd_mount(argc: c_int, argv: *const *const c_char) {
     colored::control::set_override(opt.colorize);
     if let Err(e) = cmd_mount_inner(opt) {
         error!("Fatal error: {}", e);
+        1
     } else {
         info!("Successfully mounted");
+        0
     }
 }