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;
src: String,
target: impl AsRef<std::path::Path>,
fstype: &str,
- mountflags: u64,
+ mountflags: libc::c_ulong,
data: Option<String>,
) -> anyhow::Result<()> {
/// 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
/// 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:
/// "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,
/// 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 = "")]
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
colored::control::set_override(opt.colorize);
if let Err(e) = cmd_mount_inner(opt) {
error!("Fatal error: {}", e);
+ 1
} else {
info!("Successfully mounted");
+ 0
}
}