diff options
author | Thomas Bertschinger <tahbertschinger@gmail.com> | 2024-01-07 18:36:33 -0700 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2024-01-07 21:38:31 -0500 |
commit | 9a9af6e9e6560407326b37345ebe434a0839420f (patch) | |
tree | e105d7ed49fb20988e9e9c6c1a94fc2d6bb63475 /rust-src/src | |
parent | b90031efaa4500b8ce5ffc55e9d1ed716196b814 (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.rs | 8 | ||||
-rw-r--r-- | rust-src/src/cmd_list.rs | 11 | ||||
-rw-r--r-- | rust-src/src/cmd_main.rs | 34 | ||||
-rw-r--r-- | rust-src/src/cmd_mount.rs | 12 | ||||
-rw-r--r-- | rust-src/src/lib.rs | 1 |
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; |