diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-02-26 21:38:12 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-02-27 21:45:42 -0500 |
commit | e0e06d95f899e5e83d66e94600928156a5eb3a4b (patch) | |
tree | 5de00419aeed9689125493ce6894ab90b5ea57a0 /rust-src/bch_bindgen | |
parent | 30cca2e94d0dfa8c3151daf1393f402d32bb9407 (diff) |
Rust: Start of cmd_list rewrite
This is a _very_ preliminary rewrite of the cmd_list tool in rust, which
is intended to be a testing ground for a safe interface in Rust to the
core btree interface. This adds rust wrappers for:
bch_fs: provides bch2_fs_open(), bch2_fs_stop
btree_trans: provides bch2_trans_init(), bch2_trans_exit()
btree_iter: provides peek, peek_and_restart, advance
bch_errcode: implements Display (wraps bch2_err_str())
bpos: implements Ord (wraps bpos_cmp())
bkey_s_c: implements Display (wraps bch2_bkey_val_to_text())
and other assorted types.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'rust-src/bch_bindgen')
-rw-r--r-- | rust-src/bch_bindgen/Cargo.lock | 195 | ||||
-rw-r--r-- | rust-src/bch_bindgen/Cargo.toml | 2 | ||||
-rw-r--r-- | rust-src/bch_bindgen/build.rs | 16 | ||||
-rw-r--r-- | rust-src/bch_bindgen/src/btree.rs | 80 | ||||
-rw-r--r-- | rust-src/bch_bindgen/src/errcode.rs | 40 | ||||
-rw-r--r-- | rust-src/bch_bindgen/src/fs.rs | 30 | ||||
-rw-r--r-- | rust-src/bch_bindgen/src/lib.rs | 172 | ||||
-rw-r--r-- | rust-src/bch_bindgen/src/libbcachefs_wrapper.h | 1 | ||||
-rw-r--r-- | rust-src/bch_bindgen/src/rs.rs | 10 |
9 files changed, 497 insertions, 49 deletions
diff --git a/rust-src/bch_bindgen/Cargo.lock b/rust-src/bch_bindgen/Cargo.lock index dca947aa..3d17e2f4 100644 --- a/rust-src/bch_bindgen/Cargo.lock +++ b/rust-src/bch_bindgen/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "atty" @@ -54,9 +54,8 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.63.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36d860121800b2a9a94f9b5604b332d5cffb234ce17609ea479d723dbc9d3885" +version = "0.64.0" +source = "git+file:///home/kent/rust-src/rust-bindgen#f773267b090bf16b9e8375fcbdcd8ba5e88806a8" dependencies = [ "bitflags", "cexpr", @@ -134,9 +133,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3" +checksum = "77ed9a53e5d4d9c573ae844bfac6872b159cb1d1585a83b29e7a64b7eef7332a" dependencies = [ "glob", "libc", @@ -171,9 +170,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "cxx" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc831ee6a32dd495436e317595e639a587aa9907bef96fe6e6abc290ab6204e9" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" dependencies = [ "cc", "cxxbridge-flags", @@ -183,9 +182,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94331d54f1b1a8895cd81049f7eaaaef9d05a7dcb4d1fd08bf3ff0806246789d" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" dependencies = [ "cc", "codespan-reporting", @@ -198,15 +197,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48dcd35ba14ca9b40d6e4b4b39961f23d835dbb8eed74565ded361d93e1feb8a" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" [[package]] name = "cxxbridge-macro" -version = "1.0.89" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bbeb29798b407ccd82a3324ade1a7286e0d29851475990b612670f6f5124d2" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" dependencies = [ "proc-macro2", "quote", @@ -214,10 +213,31 @@ dependencies = [ ] [[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] @@ -292,6 +312,16 @@ dependencies = [ ] [[package]] +name = "io-lifetimes" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" +dependencies = [ + "libc", + "windows-sys 0.45.0", +] + +[[package]] name = "js-sys" version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -338,6 +368,12 @@ dependencies = [ ] [[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -398,9 +434,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "peeking_take_while" @@ -416,9 +452,9 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -457,21 +493,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - -[[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] +name = "rustix" +version = "0.36.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + +[[package]] name = "scratch" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -485,9 +526,9 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "syn" -version = "1.0.107" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -496,16 +537,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" dependencies = [ "cfg-if", "fastrand", - "libc", "redox_syscall", - "remove_dir_all", - "winapi", + "rustix", + "windows-sys 0.42.0", ] [[package]] @@ -667,3 +707,84 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" diff --git a/rust-src/bch_bindgen/Cargo.toml b/rust-src/bch_bindgen/Cargo.toml index ce15fe0a..0590c61a 100644 --- a/rust-src/bch_bindgen/Cargo.toml +++ b/rust-src/bch_bindgen/Cargo.toml @@ -23,4 +23,4 @@ gag = "1.0.0" [build-dependencies] pkg-config = "0.3" -bindgen = { version = "0.63", default-features = false } +bindgen = { git = "https://evilpiepirate.org/git/rust-bindgen.git", default-features = false } diff --git a/rust-src/bch_bindgen/build.rs b/rust-src/bch_bindgen/build.rs index c5f19ff0..22c9777a 100644 --- a/rust-src/bch_bindgen/build.rs +++ b/rust-src/bch_bindgen/build.rs @@ -27,6 +27,7 @@ fn main() { .clang_arg("-DZSTD_STATIC_LINKING_ONLY") .clang_arg("-DNO_BCACHEFS_FS") .clang_arg("-D_GNU_SOURCE") + .clang_arg("-fkeep-inline-functions") .derive_debug(true) .derive_default(true) .derive_eq(true) @@ -36,11 +37,12 @@ fn main() { }) .allowlist_function(".*bch2_.*") .allowlist_function("bio_.*") - .allowlist_function("bch2_super_write_fd") .allowlist_function("derive_passphrase") .allowlist_function("request_key") .allowlist_function("add_key") .allowlist_function("keyctl_search") + .allowlist_function("match_string") + .allowlist_function("printbuf.*") .blocklist_type("bch_extent_ptr") .blocklist_type("btree_node") .blocklist_type("bch_extent_crc32") @@ -48,6 +50,11 @@ fn main() { .blocklist_type("srcu_struct") .allowlist_var("BCH_.*") .allowlist_var("KEY_SPEC_.*") + .allowlist_var("bch.*") + .allowlist_var("POS_MIN") + .allowlist_var("POS_MAX") + .allowlist_var("SPOS_MAX") + .blocklist_item("bch2_bkey_ops") .allowlist_type("bch_kdf_types") .allowlist_type("bch_sb_field_.*") .allowlist_type("bch_encrypted_key") @@ -56,9 +63,14 @@ fn main() { .allowlist_function("bch2_err_str") .newtype_enum("bch_kdf_types") .opaque_type("gendisk") - .opaque_type("bkey") .opaque_type("gc_stripe") .opaque_type("open_bucket.*") + .opaque_type("replicas_delta_list") + .no_copy("btree_trans") + .no_copy("printbuf") + .no_partialeq("bkey") + .no_partialeq("bpos") + .generate_inline_functions(true) .generate() .expect("BindGen Generation Failiure: [libbcachefs_wrapper]"); bindings diff --git a/rust-src/bch_bindgen/src/btree.rs b/rust-src/bch_bindgen/src/btree.rs new file mode 100644 index 00000000..da9dbca6 --- /dev/null +++ b/rust-src/bch_bindgen/src/btree.rs @@ -0,0 +1,80 @@ +use crate::SPOS_MAX; +use crate::c; +use crate::fs::Fs; +use crate::errcode::{bch_errcode, errptr_to_result_c}; +use std::mem::MaybeUninit; +use std::ptr; + +pub struct BtreeTrans { + raw: c::btree_trans, +} + +impl BtreeTrans { + pub fn new<'a>(fs: &'a Fs) -> BtreeTrans { + unsafe { + let mut trans: MaybeUninit<BtreeTrans> = MaybeUninit::uninit(); + + c::__bch2_trans_init(&mut (*trans.as_mut_ptr()).raw, fs.raw, 0); + trans.assume_init() + } + } +} + +impl Drop for BtreeTrans { + fn drop(&mut self) { + unsafe { c::bch2_trans_exit(&mut self.raw) } + } +} + +pub struct BtreeIter { + raw: c::btree_iter, +} + +impl BtreeIter { + pub fn new<'a>(trans: &'a BtreeTrans, btree: c::btree_id, pos: c::bpos, flags: u32) -> BtreeIter { + unsafe { + let mut iter: MaybeUninit<BtreeIter> = MaybeUninit::uninit(); + + c::bch2_trans_iter_init_outlined( + ptr::addr_of!(trans.raw).cast_mut(), + &mut (*iter.as_mut_ptr()).raw, + btree as u32, + pos, + flags); + iter.assume_init() + } + } + + pub fn peek_upto(&mut self, end: c::bpos) -> Result<c::bkey_s_c, bch_errcode> { + unsafe { + let k = c::bch2_btree_iter_peek_upto(&mut self.raw, end); + errptr_to_result_c(k.k).map(|_| k) + } + } + + pub fn peek(&mut self) -> Result<c::bkey_s_c, bch_errcode> { + self.peek_upto(SPOS_MAX) + } + + pub fn peek_and_restart(&mut self) -> Result<Option<c::bkey_s_c>, bch_errcode> { + unsafe { + let k = c::bch2_btree_iter_peek_and_restart_outlined(&mut self.raw); + + errptr_to_result_c(k.k) + .map(|_| if !k.k.is_null() { Some(k) } else { None } ) + } + } + + pub fn advance(&mut self) { + unsafe { + c::bch2_btree_iter_advance(&mut self.raw); + } + + } +} + +impl Drop for BtreeIter { + fn drop(&mut self) { + unsafe { c::bch2_trans_iter_exit(self.raw.trans, &mut self.raw) } + } +} diff --git a/rust-src/bch_bindgen/src/errcode.rs b/rust-src/bch_bindgen/src/errcode.rs new file mode 100644 index 00000000..4d75f1d2 --- /dev/null +++ b/rust-src/bch_bindgen/src/errcode.rs @@ -0,0 +1,40 @@ +use crate::bcachefs; +use std::ffi::CStr; +use std::fmt; + +pub use crate::c::bch_errcode; + +impl fmt::Display for bch_errcode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s = unsafe { CStr::from_ptr(bcachefs::bch2_err_str(*self as i32)) }; + write!(f, "{:?}", s) + } +} + +/* Can we make a function generic over ptr constness? */ + +pub fn errptr_to_result<T>(p: *mut T) -> Result<*mut T, bch_errcode> { + let addr = p as usize; + let max_err: isize = -4096; + if addr > max_err as usize { + let addr = addr as i32; + let err: bch_errcode = unsafe { std::mem::transmute(-addr) }; + Err(err) + } else { + Ok(p) + } +} + +pub fn errptr_to_result_c<T>(p: *const T) -> Result<*const T, bch_errcode> { + let addr = p as usize; + let max_err: isize = -4096; + if addr > max_err as usize { + let addr = addr as i32; + let err: bch_errcode = unsafe { std::mem::transmute(-addr) }; + Err(err) + } else { + Ok(p) + } +} + +impl std::error::Error for bch_errcode {} diff --git a/rust-src/bch_bindgen/src/fs.rs b/rust-src/bch_bindgen/src/fs.rs new file mode 100644 index 00000000..1176846d --- /dev/null +++ b/rust-src/bch_bindgen/src/fs.rs @@ -0,0 +1,30 @@ +use std::ffi::CString; +use std::os::unix::ffi::OsStrExt; +use std::path::PathBuf; +use crate::c; +use crate::errcode::{bch_errcode, errptr_to_result}; + +pub struct Fs { + pub raw: *mut c::bch_fs, +} + +impl Fs { + pub fn open(devices: &Vec<PathBuf>, opts: c::bch_opts) -> Result<Fs, bch_errcode> { + let devices: Vec<_> = devices.iter() + .map(|i| CString::new(i.as_os_str().as_bytes()).unwrap()).collect(); + let dev_c_strs: Vec<_> = devices.iter() + .map(|i| { let p: *const i8 = i.as_ptr(); p }) + .collect(); + let dev_c_strarray: *const *mut i8 = dev_c_strs[..].as_ptr() as *const *mut i8; + + let ret = unsafe { c::bch2_fs_open(dev_c_strarray, dev_c_strs.len() as u32, opts) }; + + errptr_to_result(ret).map(|fs| Fs { raw: fs}) + } +} + +impl Drop for Fs { + fn drop(&mut self) { + unsafe { c::bch2_fs_stop(self.raw) } + } +} diff --git a/rust-src/bch_bindgen/src/lib.rs b/rust-src/bch_bindgen/src/lib.rs index c54786aa..a5f5a0d5 100644 --- a/rust-src/bch_bindgen/src/lib.rs +++ b/rust-src/bch_bindgen/src/lib.rs @@ -1,7 +1,179 @@ pub mod bcachefs; +pub mod btree; +pub mod errcode; pub mod keyutils; pub mod log; pub mod rs; +pub mod fs; + pub mod c { pub use crate::bcachefs::*; } + +use c::bpos as Bpos; + +pub const fn spos(inode: u64, offset: u64, snapshot: u32) -> Bpos { + Bpos { inode, offset, snapshot } +} + +pub const fn pos(inode: u64, offset: u64) -> Bpos { + spos(inode, offset, 0) +} + +pub const POS_MIN: Bpos = spos(0, 0, 0); +pub const POS_MAX: Bpos = spos(u64::MAX, u64::MAX, 0); +pub const SPOS_MAX: Bpos = spos(u64::MAX, u64::MAX, u32::MAX); + +use std::cmp::Ordering; + +impl PartialEq for Bpos { + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == Ordering::Equal + } +} + +impl Eq for Bpos {} + +impl PartialOrd for Bpos { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Ord for Bpos { + fn cmp(&self, other: &Self) -> Ordering { + let l_inode = self.inode; + let r_inode = other.inode; + let l_offset = self.offset; + let r_offset = other.offset; + let l_snapshot = self.snapshot; + let r_snapshot = other.snapshot; + + l_inode.cmp(&r_inode) + .then(l_offset.cmp(&r_offset)) + .then(l_snapshot.cmp(&r_snapshot)) + } +} + +use std::ffi::CStr; +use std::fmt; + +impl fmt::Display for c::btree_id { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s = unsafe { CStr::from_ptr(*c::bch2_btree_ids.get_unchecked(*self as usize)) }; + let s = s.to_str().unwrap(); + write!(f, "{}", s) + } +} + +use std::str::FromStr; +use std::ffi::CString; + +use std::error::Error; + +#[derive(Debug)] +pub struct InvalidBtreeId; + +impl fmt::Display for InvalidBtreeId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "invalid btree id") + } +} + +impl Error for InvalidBtreeId { +} + +impl FromStr for c::btree_id { + type Err = InvalidBtreeId; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + let s = CString::new(s).unwrap(); + let p: *const i8 = s.as_ptr(); + + let v = unsafe {c::match_string(c::bch2_btree_ids[..].as_ptr(), (-(1 as isize)) as usize, p)}; + if v >= 0 { + Ok(unsafe { std::mem::transmute(v) }) + } else { + Err(InvalidBtreeId) + } + } +} + +impl c::printbuf { + fn new() -> c::printbuf { + let mut buf: c::printbuf = Default::default(); + + buf.set_heap_allocated(true); + buf + } +} + +impl Drop for c::printbuf { + fn drop(&mut self) { + unsafe { c::bch2_printbuf_exit(self) } + } +} + +impl fmt::Display for Bpos { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut buf = c::printbuf::new(); + + unsafe { c::bch2_bpos_to_text(&mut buf, *self) }; + + let s = unsafe { CStr::from_ptr(buf.buf) }; + let s = s.to_str().unwrap(); + write!(f, "{}", s) + } +} + +impl FromStr for c::bpos { + type Err = InvalidBtreeId; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + if s == "POS_MIN" { + return Ok(c::bpos { inode: 0, offset: 0, snapshot: 0 }); + } + + if s == "POS_MAX" { + return Ok(c::bpos { inode: u64::MAX, offset: u64::MAX, snapshot: 0 }); + } + + if s == "SPOS_MAX" { + return Ok(c::bpos { inode: u64::MAX, offset: u64::MAX, snapshot: u32::MAX }); + } + + let mut fields = s.split(':'); + let ino_str = fields.next().ok_or(InvalidBtreeId)?; + let off_str = fields.next().ok_or(InvalidBtreeId)?; + let snp_str = fields.next(); + + let ino: u64 = ino_str.parse().map_err(|_| InvalidBtreeId)?; + let off: u64 = off_str.parse().map_err(|_| InvalidBtreeId)?; + let snp: u32 = snp_str.map(|s| s.parse().ok()).flatten().unwrap_or(0); + + Ok(c::bpos { inode: ino, offset: off, snapshot: snp }) + } +} + +pub struct BkeySCToText<'a, 'b> { + k: &'a c::bkey_s_c, + fs: &'b fs::Fs, +} + +impl<'a, 'b> fmt::Display for BkeySCToText<'a, 'b> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut buf = c::printbuf::new(); + + unsafe { c::bch2_bkey_val_to_text(&mut buf, self.fs.raw, *self.k) }; + + let s = unsafe { CStr::from_ptr(buf.buf) }; + let s = s.to_str().unwrap(); + write!(f, "{}", s) + } +} + +impl c::bkey_s_c { + pub fn to_text<'a, 'b>(&'a self, fs: &'b fs::Fs) -> BkeySCToText<'a, 'b> { + BkeySCToText { k: self, fs } + } +} diff --git a/rust-src/bch_bindgen/src/libbcachefs_wrapper.h b/rust-src/bch_bindgen/src/libbcachefs_wrapper.h index ec2b5850..6332d957 100644 --- a/rust-src/bch_bindgen/src/libbcachefs_wrapper.h +++ b/rust-src/bch_bindgen/src/libbcachefs_wrapper.h @@ -1,6 +1,7 @@ #include "../libbcachefs/super-io.h" #include "../libbcachefs/checksum.h" #include "../libbcachefs/bcachefs_format.h" +#include "../libbcachefs/btree_iter.h" #include "../libbcachefs/errcode.h" #include "../libbcachefs/opts.h" #include "../libbcachefs.h" diff --git a/rust-src/bch_bindgen/src/rs.rs b/rust-src/bch_bindgen/src/rs.rs index 17610f3a..24594ae1 100644 --- a/rust-src/bch_bindgen/src/rs.rs +++ b/rust-src/bch_bindgen/src/rs.rs @@ -1,15 +1,7 @@ use anyhow::anyhow; use crate::bcachefs; use crate::bcachefs::*; -use std::ffi::CStr; -use std::fmt; - -impl fmt::Display for bch_errcode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let s = unsafe { CStr::from_ptr(bch2_err_str(*self as i32)) }; - write!(f, "{:?}", s) - } -} +use crate::errcode::bch_errcode; pub fn read_super_opts( path: &std::path::Path, |