summaryrefslogtreecommitdiff
path: root/rust-src/src
diff options
context:
space:
mode:
authorThomas Bertschinger <tahbertschinger@gmail.com>2024-01-07 18:36:33 -0700
committerKent Overstreet <kent.overstreet@linux.dev>2024-01-07 21:38:31 -0500
commit9a9af6e9e6560407326b37345ebe434a0839420f (patch)
treee105d7ed49fb20988e9e9c6c1a94fc2d6bb63475 /rust-src/src
parentb90031efaa4500b8ce5ffc55e9d1ed716196b814 (diff)
create common entry point for Rust commands
The bcachefs sub-commands that are implemented in Rust (completions, list, and mount) had separate entrypoints and thus had some differences in behavior. This introduces a common entry point for the Rust sub-commands. This reduces duplicate boilerplate code like parsing argv and setting up logging, and will facilitate converting more sub-commands to Rust in the future. An immediate benefit is that this fixes an issue with `bcachefs list` not reporting errors: before: $ bcachefs list /dev/typo $ echo $? 0 after: $ bcachefs list /dev/typo ERROR - bcachefs_rust::cmd_list: Fatal error: "No such file or directory" $ echo $? 1 Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'rust-src/src')
-rw-r--r--rust-src/src/cmd_completions.rs8
-rw-r--r--rust-src/src/cmd_list.rs11
-rw-r--r--rust-src/src/cmd_main.rs34
-rw-r--r--rust-src/src/cmd_mount.rs12
-rw-r--r--rust-src/src/lib.rs1
5 files changed, 45 insertions, 21 deletions
diff --git a/rust-src/src/cmd_completions.rs b/rust-src/src/cmd_completions.rs
index 51859696..3e839fe8 100644
--- a/rust-src/src/cmd_completions.rs
+++ b/rust-src/src/cmd_completions.rs
@@ -1,7 +1,6 @@
-use crate::transform_c_args;
use clap::{Command, CommandFactory, Parser};
use clap_complete::{generate, Generator, Shell};
-use std::ffi::{c_char, c_int};
+use std::ffi::{c_int, OsStr};
use std::io;
/// Generate shell completions
@@ -14,10 +13,7 @@ fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
}
-#[no_mangle]
-#[allow(clippy::not_unsafe_ptr_arg_deref)]
-pub extern "C" fn cmd_completions(argc: c_int, argv: *const *const c_char) -> c_int {
- transform_c_args!(argv, argc, argv);
+pub fn cmd_completions(argv: Vec<&OsStr>) -> c_int {
let cli = Cli::parse_from(argv);
print_completions(cli.shell, &mut super::Cli::command());
0
diff --git a/rust-src/src/cmd_list.rs b/rust-src/src/cmd_list.rs
index 5540514e..fa9c2f2f 100644
--- a/rust-src/src/cmd_list.rs
+++ b/rust-src/src/cmd_list.rs
@@ -9,8 +9,7 @@ use bch_bindgen::btree::BtreeIter;
use bch_bindgen::btree::BtreeNodeIter;
use bch_bindgen::btree::BtreeIterFlags;
use clap::{Parser};
-use std::ffi::{c_int, c_char};
-use crate::transform_c_args;
+use std::ffi::{c_int, OsStr};
fn list_keys(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
let trans = BtreeTrans::new(fs);
@@ -158,13 +157,13 @@ fn cmd_list_inner(opt: Cli) -> anyhow::Result<()> {
}
}
-#[no_mangle]
-#[allow(clippy::not_unsafe_ptr_arg_deref)]
-pub extern "C" fn cmd_list(argc: c_int, argv: *const *const c_char) {
- transform_c_args!(argv, argc, argv);
+pub fn cmd_list(argv: Vec<&OsStr>) -> c_int {
let opt = Cli::parse_from(argv);
colored::control::set_override(opt.colorize);
if let Err(e) = cmd_list_inner(opt) {
error!("Fatal error: {}", e);
+ 1
+ } else {
+ 0
}
}
diff --git a/rust-src/src/cmd_main.rs b/rust-src/src/cmd_main.rs
new file mode 100644
index 00000000..baedc851
--- /dev/null
+++ b/rust-src/src/cmd_main.rs
@@ -0,0 +1,34 @@
+use log::{error, LevelFilter};
+use std::ffi::{CStr, c_int, c_char};
+use crate::transform_c_args;
+use crate::logger::SimpleLogger;
+use crate::cmd_completions::cmd_completions;
+use crate::cmd_list::cmd_list;
+use crate::cmd_mount::cmd_mount;
+
+#[no_mangle]
+pub extern "C" fn rust_main(argc: c_int, argv: *const *const c_char, cmd: *const c_char) -> c_int {
+ transform_c_args!(argv, argc, argv);
+
+ log::set_boxed_logger(Box::new(SimpleLogger)).unwrap();
+ log::set_max_level(LevelFilter::Warn);
+
+ let cmd: &CStr = unsafe { CStr::from_ptr(cmd) };
+ let cmd = match cmd.to_str() {
+ Ok(c) => c,
+ Err(e) => {
+ error!("could not parse command: {}", e);
+ return 1;
+ }
+ };
+
+ match cmd {
+ "completions" => cmd_completions(argv),
+ "list" => cmd_list(argv),
+ "mount" => cmd_mount(argv),
+ _ => {
+ error!("unknown command: {}", cmd);
+ 1
+ }
+ }
+}
diff --git a/rust-src/src/cmd_mount.rs b/rust-src/src/cmd_mount.rs
index a75dd21f..3f8253f5 100644
--- a/rust-src/src/cmd_mount.rs
+++ b/rust-src/src/cmd_mount.rs
@@ -4,10 +4,9 @@ use log::{info, debug, error, LevelFilter};
use clap::{Parser};
use uuid::Uuid;
use std::path::PathBuf;
-use crate::{key, transform_c_args};
+use crate::key;
use crate::key::KeyLocation;
-use crate::logger::SimpleLogger;
-use std::ffi::{CString, c_int, c_char, c_void};
+use std::ffi::{CString, c_int, c_char, c_void, OsStr};
use std::os::unix::ffi::OsStrExt;
fn mount_inner(
@@ -222,14 +221,9 @@ fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> {
Ok(())
}
-#[no_mangle]
-#[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);
+pub fn cmd_mount(argv: Vec<&OsStr>) -> c_int {
let opt = Cli::parse_from(argv);
- log::set_boxed_logger(Box::new(SimpleLogger)).unwrap();
-
// @TODO : more granular log levels via mount option
log::set_max_level(match opt.verbose {
0 => LevelFilter::Warn,
diff --git a/rust-src/src/lib.rs b/rust-src/src/lib.rs
index 64297b41..026cca49 100644
--- a/rust-src/src/lib.rs
+++ b/rust-src/src/lib.rs
@@ -2,6 +2,7 @@ use clap::Subcommand;
pub mod key;
pub mod logger;
+pub mod cmd_main;
pub mod cmd_mount;
pub mod cmd_list;
pub mod cmd_completions;