summaryrefslogtreecommitdiff
path: root/rust-src
diff options
context:
space:
mode:
Diffstat (limited to 'rust-src')
-rw-r--r--rust-src/Cargo.lock2
-rw-r--r--rust-src/Cargo.toml8
-rw-r--r--rust-src/bch_bindgen/build.rs6
-rw-r--r--rust-src/bch_bindgen/src/libbcachefs_wrapper.h2
-rw-r--r--rust-src/build.rs21
-rw-r--r--rust-src/src/bcachefs.rs107
-rw-r--r--rust-src/src/cmd_completions.rs3
-rw-r--r--rust-src/src/cmd_list.rs3
-rw-r--r--rust-src/src/cmd_main.rs34
-rw-r--r--rust-src/src/cmd_mount.rs11
-rw-r--r--rust-src/src/lib.rs13
11 files changed, 154 insertions, 56 deletions
diff --git a/rust-src/Cargo.lock b/rust-src/Cargo.lock
index 2fb68716..3e7eea92 100644
--- a/rust-src/Cargo.lock
+++ b/rust-src/Cargo.lock
@@ -84,7 +84,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
-name = "bcachefs-rust"
+name = "bcachefs-tools"
version = "0.3.1"
dependencies = [
"anyhow",
diff --git a/rust-src/Cargo.toml b/rust-src/Cargo.toml
index 061d0641..2786fc76 100644
--- a/rust-src/Cargo.toml
+++ b/rust-src/Cargo.toml
@@ -1,12 +1,16 @@
[package]
-name = "bcachefs-rust"
+name = "bcachefs-tools"
version = "0.3.1"
authors = ["Yuxuan Shui <yshuiv7@gmail.com>", "Kayla Firestack <dev@kaylafire.me>", "Kent Overstreet <kent.overstreet@linux.dev>" ]
edition = "2021"
rust-version = "1.65"
+[[bin]]
+name = "bcachefs"
+path = "src/bcachefs.rs"
+
[lib]
-crate-type = ["staticlib"]
+name = "bcachefs"
[dependencies]
atty = "0.2.14"
diff --git a/rust-src/bch_bindgen/build.rs b/rust-src/bch_bindgen/build.rs
index 79337a0f..d9805a8d 100644
--- a/rust-src/bch_bindgen/build.rs
+++ b/rust-src/bch_bindgen/build.rs
@@ -10,6 +10,8 @@ impl bindgen::callbacks::ParseCallbacks for Fix753 {
fn main() {
use std::path::PathBuf;
+ println!("cargo:rerun-if-changed=src/libbcachefs_wrapper.h");
+
let out_dir: PathBuf = std::env::var_os("OUT_DIR")
.expect("ENV Var 'OUT_DIR' Expected")
.into();
@@ -44,6 +46,10 @@ fn main() {
.default_enum_style(bindgen::EnumVariation::Rust {
non_exhaustive: true,
})
+ .allowlist_function("bcachefs_usage")
+ .allowlist_function("raid_init")
+ .allowlist_function("cmd_.*")
+ .allowlist_function(".*_cmds")
.allowlist_function(".*bch2_.*")
.allowlist_function("bio_.*")
.allowlist_function("derive_passphrase")
diff --git a/rust-src/bch_bindgen/src/libbcachefs_wrapper.h b/rust-src/bch_bindgen/src/libbcachefs_wrapper.h
index e68de664..5fb42613 100644
--- a/rust-src/bch_bindgen/src/libbcachefs_wrapper.h
+++ b/rust-src/bch_bindgen/src/libbcachefs_wrapper.h
@@ -11,6 +11,8 @@
#include "../crypto.h"
#include "../include/linux/bio.h"
#include "../include/linux/blkdev.h"
+#include "../cmds.h"
+#include "../raid/raid.h"
#define MARK_FIX_753(req_name) const blk_mode_t Fix753_##req_name = req_name;
diff --git a/rust-src/build.rs b/rust-src/build.rs
new file mode 100644
index 00000000..e4662bd7
--- /dev/null
+++ b/rust-src/build.rs
@@ -0,0 +1,21 @@
+fn main() {
+ println!("cargo:rustc-link-search=..");
+ println!("cargo:rerun-if-changed=../libbcachefs.a");
+ println!("cargo:rustc-link-lib=static:+whole-archive=bcachefs");
+
+ println!("cargo:rustc-link-lib=urcu");
+ println!("cargo:rustc-link-lib=zstd");
+ println!("cargo:rustc-link-lib=blkid");
+ println!("cargo:rustc-link-lib=uuid");
+ println!("cargo:rustc-link-lib=sodium");
+ println!("cargo:rustc-link-lib=z");
+ println!("cargo:rustc-link-lib=lz4");
+ println!("cargo:rustc-link-lib=zstd");
+ println!("cargo:rustc-link-lib=udev");
+ println!("cargo:rustc-link-lib=keyutils");
+ println!("cargo:rustc-link-lib=aio");
+
+ if std::env::var("BCACHEFS_FUSE").is_ok() {
+ println!("cargo:rustc-link-lib=fuse3");
+ }
+}
diff --git a/rust-src/src/bcachefs.rs b/rust-src/src/bcachefs.rs
new file mode 100644
index 00000000..3d7af3d4
--- /dev/null
+++ b/rust-src/src/bcachefs.rs
@@ -0,0 +1,107 @@
+use std::ffi::CString;
+
+use bcachefs::cmd_completions::cmd_completions;
+use bcachefs::cmd_list::cmd_list;
+use bcachefs::cmd_mount::cmd_mount;
+use bcachefs::logger::SimpleLogger;
+use bch_bindgen::c;
+
+fn handle_c_command(args: Vec<String>, symlink_cmd: Option<&str>) -> i32 {
+ let mut argv: Vec<_> = args.clone();
+
+ let cmd = match symlink_cmd {
+ Some(s) => s.to_string(),
+ None => argv.remove(1),
+ };
+
+ let argc: i32 = argv.len().try_into().unwrap();
+
+ let argv: Vec<_> = argv
+ .iter()
+ .map(|s| CString::new(s.as_str()).unwrap())
+ .collect();
+ let argv: Vec<_> = argv.iter().map(|s| s.as_ptr()).collect();
+ let argv = argv.as_ptr() as *mut *mut i8;
+
+ // The C functions will mutate argv. It shouldn't be used after this block.
+ unsafe {
+ match cmd.as_str() {
+ "--help" => {
+ c::bcachefs_usage();
+ 0
+ },
+ "data" => c::data_cmds(argc, argv),
+ "device" => c::device_cmds(argc, argv),
+ "dump" => c::cmd_dump(argc, argv),
+ "format" => c::cmd_format(argc, argv),
+ "fs" => c::fs_cmds(argc, argv),
+ "fsck" => c::cmd_fsck(argc, argv),
+ "list_journal" => c::cmd_list_journal(argc, argv),
+ "kill_btree_node" => c::cmd_kill_btree_node(argc, argv),
+ "migrate" => c::cmd_migrate(argc, argv),
+ "migrate-superblock" => c::cmd_migrate_superblock(argc, argv),
+ "mkfs" => c::cmd_format(argc, argv),
+ "remove-passphrase" => c::cmd_remove_passphrase(argc, argv),
+ "reset-counters" => c::cmd_reset_counters(argc, argv),
+ "set-option" => c::cmd_set_option(argc, argv),
+ "set-passphrase" => c::cmd_set_passphrase(argc, argv),
+ "setattr" => c::cmd_setattr(argc, argv),
+ "show-super" => c::cmd_show_super(argc, argv),
+ "subvolume" => c::subvolume_cmds(argc, argv),
+ "unlock" => c::cmd_unlock(argc, argv),
+ "version" => c::cmd_version(argc, argv),
+
+ #[cfg(fuse)]
+ "fusemount" => c::cmd_fusemount(argc, argv),
+
+ _ => {
+ println!("Unknown command {}", cmd);
+ c::bcachefs_usage();
+ 1
+ }
+ }
+ }
+}
+
+fn main() {
+ let args: Vec<String> = std::env::args().collect();
+
+ let symlink_cmd: Option<&str> = if args[0].contains("mkfs") {
+ Some("mkfs")
+ } else if args[0].contains("fsck") {
+ Some("fsck")
+ } else if args[0].contains("mount.fuse") {
+ Some("fusemount")
+ } else if args[0].contains("mount") {
+ Some("mount")
+ } else {
+ None
+ };
+
+ if symlink_cmd.is_none() && args.len() < 2 {
+ println!("missing command");
+ unsafe { c::bcachefs_usage() };
+ std::process::exit(1);
+ }
+
+ unsafe { c::raid_init() };
+
+ log::set_boxed_logger(Box::new(SimpleLogger)).unwrap();
+ log::set_max_level(log::LevelFilter::Warn);
+
+ let cmd = match symlink_cmd {
+ Some(s) => s,
+ None => args[1].as_str(),
+ };
+
+ let ret = match cmd {
+ "completions" => cmd_completions(args[1..].to_vec()),
+ "list" => cmd_list(args[1..].to_vec()),
+ "mount" => cmd_mount(args, symlink_cmd),
+ _ => handle_c_command(args, symlink_cmd),
+ };
+
+ if ret != 0 {
+ std::process::exit(1);
+ }
+}
diff --git a/rust-src/src/cmd_completions.rs b/rust-src/src/cmd_completions.rs
index 3e839fe8..53cdd643 100644
--- a/rust-src/src/cmd_completions.rs
+++ b/rust-src/src/cmd_completions.rs
@@ -1,6 +1,5 @@
use clap::{Command, CommandFactory, Parser};
use clap_complete::{generate, Generator, Shell};
-use std::ffi::{c_int, OsStr};
use std::io;
/// Generate shell completions
@@ -13,7 +12,7 @@ fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
}
-pub fn cmd_completions(argv: Vec<&OsStr>) -> c_int {
+pub fn cmd_completions(argv: Vec<String>) -> i32 {
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 fa9c2f2f..cb352916 100644
--- a/rust-src/src/cmd_list.rs
+++ b/rust-src/src/cmd_list.rs
@@ -9,7 +9,6 @@ use bch_bindgen::btree::BtreeIter;
use bch_bindgen::btree::BtreeNodeIter;
use bch_bindgen::btree::BtreeIterFlags;
use clap::{Parser};
-use std::ffi::{c_int, OsStr};
fn list_keys(fs: &Fs, opt: Cli) -> anyhow::Result<()> {
let trans = BtreeTrans::new(fs);
@@ -157,7 +156,7 @@ fn cmd_list_inner(opt: Cli) -> anyhow::Result<()> {
}
}
-pub fn cmd_list(argv: Vec<&OsStr>) -> c_int {
+pub fn cmd_list(argv: Vec<String>) -> i32 {
let opt = Cli::parse_from(argv);
colored::control::set_override(opt.colorize);
if let Err(e) = cmd_list_inner(opt) {
diff --git a/rust-src/src/cmd_main.rs b/rust-src/src/cmd_main.rs
deleted file mode 100644
index baedc851..00000000
--- a/rust-src/src/cmd_main.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-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 eccfe6d0..b120c91e 100644
--- a/rust-src/src/cmd_mount.rs
+++ b/rust-src/src/cmd_mount.rs
@@ -6,7 +6,7 @@ use uuid::Uuid;
use std::path::PathBuf;
use crate::key;
use crate::key::KeyLocation;
-use std::ffi::{CString, c_int, c_char, c_void, OsStr};
+use std::ffi::{CString, c_char, c_void};
use std::os::unix::ffi::OsStrExt;
fn mount_inner(
@@ -223,7 +223,14 @@ fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> {
Ok(())
}
-pub fn cmd_mount(argv: Vec<&OsStr>) -> c_int {
+pub fn cmd_mount(mut argv: Vec<String>, symlink_cmd: Option<&str>) -> i32 {
+ // If the bcachefs tool is being called as "bcachefs mount dev ..." (as opposed to via a
+ // symlink like "/usr/sbin/mount.bcachefs dev ...", then we need to pop the 0th argument
+ // ("bcachefs") since the CLI parser here expects the device at position 1.
+ if symlink_cmd.is_none() {
+ argv.remove(0);
+ }
+
let opt = Cli::parse_from(argv);
// @TODO : more granular log levels via mount option
diff --git a/rust-src/src/lib.rs b/rust-src/src/lib.rs
index 026cca49..f8b508dc 100644
--- a/rust-src/src/lib.rs
+++ b/rust-src/src/lib.rs
@@ -2,7 +2,6 @@ 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;
@@ -32,18 +31,6 @@ macro_rules! c_str {
};
}
-#[macro_export]
-macro_rules! transform_c_args {
- ($var:ident, $argc:expr, $argv:expr) => {
- // TODO: `OsStr::from_bytes` only exists on *nix
- use ::std::os::unix::ffi::OsStrExt;
- let $var: Vec<_> = (0..$argc)
- .map(|i| unsafe { ::std::ffi::CStr::from_ptr(*$argv.add(i as usize)) })
- .map(|i| ::std::ffi::OsStr::from_bytes(i.to_bytes()))
- .collect();
- };
-}
-
#[derive(Debug)]
struct ErrnoError(errno::Errno);
impl std::fmt::Display for ErrnoError {