summaryrefslogtreecommitdiff
path: root/rust-src/bch_bindgen/src
diff options
context:
space:
mode:
Diffstat (limited to 'rust-src/bch_bindgen/src')
-rw-r--r--rust-src/bch_bindgen/src/bcachefs.rs124
-rw-r--r--rust-src/bch_bindgen/src/keyutils.rs6
-rw-r--r--rust-src/bch_bindgen/src/keyutils_wrapper.h1
-rw-r--r--rust-src/bch_bindgen/src/lib.rs7
-rw-r--r--rust-src/bch_bindgen/src/libbcachefs_wrapper.h8
-rw-r--r--rust-src/bch_bindgen/src/rs.rs58
6 files changed, 204 insertions, 0 deletions
diff --git a/rust-src/bch_bindgen/src/bcachefs.rs b/rust-src/bch_bindgen/src/bcachefs.rs
new file mode 100644
index 00000000..cc98ffc1
--- /dev/null
+++ b/rust-src/bch_bindgen/src/bcachefs.rs
@@ -0,0 +1,124 @@
+#![allow(non_upper_case_globals)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(unused)]
+
+include!(concat!(env!("OUT_DIR"), "/bcachefs.rs"));
+
+use bitfield::bitfield;
+bitfield! {
+ pub struct bch_scrypt_flags(u64);
+ pub N, _: 15, 0;
+ pub R, _: 31, 16;
+ pub P, _: 47, 32;
+}
+bitfield! {
+ pub struct bch_crypt_flags(u64);
+ pub TYPE, _: 4, 0;
+}
+use memoffset::offset_of;
+impl bch_sb_field_crypt {
+ pub fn scrypt_flags(&self) -> Option<bch_scrypt_flags> {
+ use std::convert::TryInto;
+ match bch_kdf_types(bch_crypt_flags(self.flags).TYPE().try_into().ok()?) {
+ bch_kdf_types::BCH_KDF_SCRYPT => Some(bch_scrypt_flags(self.kdf_flags)),
+ _ => None,
+ }
+ }
+ pub fn key(&self) -> &bch_encrypted_key {
+ &self.key
+ }
+}
+impl PartialEq for bch_sb {
+ fn eq(&self, other: &Self) -> bool {
+ self.magic.b == other.magic.b
+ && self.user_uuid.b == other.user_uuid.b
+ && self.block_size == other.block_size
+ && self.version == other.version
+ && self.uuid.b == other.uuid.b
+ && self.seq == other.seq
+ }
+}
+
+impl std::fmt::Debug for bch_sb {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("bch_sb")
+ .field("uuid", &self.uuid())
+ .field("version", &(self.version, self.version_min))
+ .field("block_size", &self.block_size)
+ .field("device_idx", &self.dev_idx)
+ .field("seq", &self.seq)
+ .field("csum", &(self.csum.lo, self.csum.hi))
+ .field("offset", &self.offset)
+ .finish_non_exhaustive()
+ }
+}
+
+
+impl bch_sb {
+ pub fn crypt(&self) -> Option<&bch_sb_field_crypt> {
+ unsafe {
+ let ptr = bch2_sb_field_get(self as *const _ as *mut _, bch_sb_field_type::BCH_SB_FIELD_crypt) as *const u8;
+ if ptr.is_null() {
+ None
+ } else {
+ let offset = offset_of!(bch_sb_field_crypt, field);
+ Some(&*((ptr.sub(offset)) as *const _))
+ }
+ }
+ }
+ pub fn uuid(&self) -> uuid::Uuid {
+ uuid::Uuid::from_bytes(self.user_uuid.b)
+ }
+
+ /// Get the nonce used to encrypt the superblock
+ pub fn nonce(&self) -> nonce {
+ use byteorder::{LittleEndian, ReadBytesExt};
+ let mut internal_uuid = &self.uuid.b[..];
+ let dword1 = internal_uuid.read_u32::<LittleEndian>().unwrap();
+ let dword2 = internal_uuid.read_u32::<LittleEndian>().unwrap();
+ nonce {
+ d: [0, 0, dword1, dword2],
+ }
+ }
+}
+impl bch_sb_handle {
+ pub fn sb(&self) -> &bch_sb {
+ unsafe { &*self.sb }
+ }
+
+ pub fn bdev(&self) -> &block_device {
+ unsafe { &*self.bdev }
+ }
+}
+
+#[repr(C)]
+// #[repr(align(8))]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct bch_extent_ptr {
+ pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>,
+}
+
+#[repr(C, packed(8))]
+pub struct btree_node {
+ pub csum: bch_csum,
+ pub magic: __le64,
+ pub flags: __le64,
+ pub min_key: bpos,
+ pub max_key: bpos,
+ pub _ptr: bch_extent_ptr,
+ pub format: bkey_format,
+ pub __bindgen_anon_1: btree_node__bindgen_ty_1,
+}
+
+#[repr(C, packed(8))]
+// #[repr(align(8))]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct bch_extent_crc32 {
+ pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>,
+ pub csum: __u32,
+}
+
+// #[repr(u8)]
+pub enum rhash_lock_head {}
+pub enum srcu_struct {}
diff --git a/rust-src/bch_bindgen/src/keyutils.rs b/rust-src/bch_bindgen/src/keyutils.rs
new file mode 100644
index 00000000..30fc56f9
--- /dev/null
+++ b/rust-src/bch_bindgen/src/keyutils.rs
@@ -0,0 +1,6 @@
+#![allow(non_upper_case_globals)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(unused)]
+
+include!(concat!(env!("OUT_DIR"), "/keyutils.rs"));
diff --git a/rust-src/bch_bindgen/src/keyutils_wrapper.h b/rust-src/bch_bindgen/src/keyutils_wrapper.h
new file mode 100644
index 00000000..857cee2e
--- /dev/null
+++ b/rust-src/bch_bindgen/src/keyutils_wrapper.h
@@ -0,0 +1 @@
+#include <keyutils.h>
diff --git a/rust-src/bch_bindgen/src/lib.rs b/rust-src/bch_bindgen/src/lib.rs
new file mode 100644
index 00000000..c19b5a2f
--- /dev/null
+++ b/rust-src/bch_bindgen/src/lib.rs
@@ -0,0 +1,7 @@
+pub mod bcachefs;
+pub mod keyutils;
+pub mod rs;
+
+pub mod c {
+ pub use crate::bcachefs::*;
+}
diff --git a/rust-src/bch_bindgen/src/libbcachefs_wrapper.h b/rust-src/bch_bindgen/src/libbcachefs_wrapper.h
new file mode 100644
index 00000000..2a0e7026
--- /dev/null
+++ b/rust-src/bch_bindgen/src/libbcachefs_wrapper.h
@@ -0,0 +1,8 @@
+#include "../libbcachefs/super-io.h"
+#include "../libbcachefs/checksum.h"
+#include "../libbcachefs/bcachefs_format.h"
+#include "../libbcachefs/opts.h"
+#include "../libbcachefs.h"
+#include "../crypto.h"
+#include "../include/linux/bio.h"
+
diff --git a/rust-src/bch_bindgen/src/rs.rs b/rust-src/bch_bindgen/src/rs.rs
new file mode 100644
index 00000000..4452f0b2
--- /dev/null
+++ b/rust-src/bch_bindgen/src/rs.rs
@@ -0,0 +1,58 @@
+use crate::bcachefs;
+
+pub const SUPERBLOCK_MAGIC: uuid::Uuid = uuid::Uuid::from_u128(
+ 0x_c68573f6_4e1a_45ca_8265_f57f48ba6d81
+);
+
+extern "C" {
+ pub static stdout: *mut libc::FILE;
+}
+
+pub enum ReadSuperErr {
+ Io(std::io::Error),
+}
+
+type RResult<T> = std::io::Result<std::io::Result<T>>;
+
+#[tracing_attributes::instrument(skip(opts))]
+pub fn read_super_opts(path: &std::path::Path, mut opts: bcachefs::bch_opts) -> RResult<bcachefs::bch_sb_handle> {
+ // let devp = camino::Utf8Path::from_path(devp).unwrap();
+
+ use std::os::unix::ffi::OsStrExt;
+ let path = std::ffi::CString::new(path.as_os_str().as_bytes())?;
+
+ let mut sb = std::mem::MaybeUninit::zeroed();
+
+ // use gag::{BufferRedirect};
+ // // Stop libbcachefs from spamming the output
+ // let gag = BufferRedirect::stderr().unwrap();
+ // tracing::trace!("entering libbcachefs");
+
+ let ret = unsafe { crate::bcachefs::bch2_read_super(path.as_ptr(), &mut opts, sb.as_mut_ptr()) };
+ tracing::trace!(%ret);
+
+ match -ret {
+ libc::EACCES => Err(std::io::Error::new(
+ std::io::ErrorKind::PermissionDenied,
+ "Access Permission Denied",
+ )),
+ 0 => Ok(Ok(unsafe { sb.assume_init() })),
+ 22 => Ok(Err(std::io::Error::new(
+ std::io::ErrorKind::InvalidData,
+ "Not a BCacheFS SuperBlock",
+ ))),
+ code => {
+ tracing::debug!(msg = "BCacheFS return error code", ?code);
+ Ok(Err(std::io::Error::new(
+ std::io::ErrorKind::Other,
+ "Failed to Read SuperBlock",
+ )))
+ }
+ }
+}
+
+#[tracing_attributes::instrument]
+pub fn read_super(path: &std::path::Path) -> RResult<bcachefs::bch_sb_handle> {
+ let opts = bcachefs::bch_opts::default(); //unsafe {std::mem::MaybeUninit::zeroed().assume_init()};
+ read_super_opts(path, opts)
+}