split mount into a library crate for rust reuse

update makefile to output shared library and rust build
fix default.nix to properly get the binary name for `ln`ing - move binary to main.rs
add rustfmt and gitignore files
move build.rs file into bch_bindgen for reuse between projects
add outputs to nix flake and checks
add mount.toml to makefile
This commit is contained in:
Kayla Firestack 2021-10-18 13:27:51 -04:00
parent 7e97ef59bd
commit 1f8fc31ddc
25 changed files with 1552 additions and 397 deletions

View File

@ -19,7 +19,13 @@ CFLAGS+=-std=gnu89 -O2 -g -MMD -Wall \
-DVERSION_STRING='"$(VERSION)"' \
$(EXTRA_CFLAGS)
LDFLAGS+=$(CFLAGS) $(EXTRA_LDFLAGS)
CARGO_ARGS=
CARGO=cargo $(CARGO_ARGS)
CARGO_PROFILE=release
# CARGO_PROFILE=debug
CARGO_BUILD_ARGS=--$(CARGO_PROFILE)
CARGO_BUILD=$(CARGO) build $(CARGO_BUILD_ARGS)
VERSION?=$(shell git describe --dirty=+ 2>/dev/null || echo v0.1-nogit)
include Makefile.compiler
@ -49,7 +55,6 @@ endif
CFLAGS+=$(PKGCONFIG_CFLAGS)
LDLIBS+=$(PKGCONFIG_LDLIBS)
LDLIBS+=-lm -lpthread -lrt -lscrypt -lkeyutils -laio -ldl
LDLIBS+=$(EXTRA_LDLIBS)
@ -72,7 +77,10 @@ ifeq ($(STATUS),0)
endif
.PHONY: all
all: bcachefs bcachefs.5
all: bcachefs bcachefs.5 lib
.PHONY: lib
lib: libbcachefs.so
.PHONY: tests
tests: tests/test_helper
@ -107,19 +115,25 @@ DEPS=$(SRCS:.c=.d)
OBJS=$(SRCS:.c=.o)
bcachefs: $(filter-out ./tests/%.o, $(OBJS))
MOUNT_SRCS=$(shell find mount/src -type f -iname '*.rs') \
mount/Cargo.toml mount/Cargo.lock mount/build.rs
RUST_SRCS=$(shell find rust-src/ -type f -iname '*.rs')
MOUNT_SRCS=$(filter %mount, $(RUST_SRCS))
debug: CFLAGS+=-Werror -DCONFIG_BCACHEFS_DEBUG=y -DCONFIG_VALGRIND=y
debug: bcachefs
libbcachefs_mount.a: $(MOUNT_SRCS)
LIBBCACHEFS_INCLUDE=$(CURDIR) cargo build --manifest-path mount/Cargo.toml --release
cp mount/target/release/libbcachefs_mount.a $@
MOUNT_OBJ=$(filter-out ./bcachefs.o ./tests/%.o ./cmd_%.o , $(OBJS))
mount.bcachefs: libbcachefs_mount.a $(MOUNT_OBJ)
$(CC) -Wl,--gc-sections libbcachefs_mount.a $(MOUNT_OBJ) -o $@ $(LDLIBS)
libbcachefs.so: LDFLAGS+=-shared
libbcachefs.so: $(MOUNT_OBJ)
$(CC) $(LDFLAGS) $+ -o $@ $(LDLIBS)
MOUNT_TOML=rust-src/mount/Cargo.toml
mount.bcachefs: lib $(MOUNT_SRCS)
LIBBCACHEFS_LIB=$(CURDIR) \
LIBBCACHEFS_INCLUDE=$(CURDIR) \
$(CARGO_BUILD) --manifest-path $(MOUNT_TOML)
ln -f rust-src/mount/target/$(CARGO_PROFILE)/bcachefs-mount $@
tests/test_helper: $(filter ./tests/%.o, $(OBJS))
@ -136,7 +150,7 @@ cmd_version.o : .version
.PHONY: install
install: INITRAMFS_HOOK=$(INITRAMFS_DIR)/hooks/bcachefs
install: INITRAMFS_SCRIPT=$(INITRAMFS_DIR)/scripts/local-premount/bcachefs
install: bcachefs
install: bcachefs lib
$(INSTALL) -m0755 -D bcachefs -t $(DESTDIR)$(ROOT_SBINDIR)
$(INSTALL) -m0755 fsck.bcachefs $(DESTDIR)$(ROOT_SBINDIR)
$(INSTALL) -m0755 mkfs.bcachefs $(DESTDIR)$(ROOT_SBINDIR)
@ -144,13 +158,15 @@ install: bcachefs
$(INSTALL) -m0755 -D initramfs/script $(DESTDIR)$(INITRAMFS_SCRIPT)
$(INSTALL) -m0755 -D initramfs/hook $(DESTDIR)$(INITRAMFS_HOOK)
$(INSTALL) -m0755 -D mount.bcachefs.sh $(DESTDIR)$(ROOT_SBINDIR)
$(INSTALL) -m0755 -D libbcachefs.so -t $(PREFIX)/lib/
sed -i '/^# Note: make install replaces/,$$d' $(DESTDIR)$(INITRAMFS_HOOK)
echo "copy_exec $(ROOT_SBINDIR)/bcachefs /sbin/bcachefs" >> $(DESTDIR)$(INITRAMFS_HOOK)
.PHONY: clean
clean:
$(RM) bcachefs mount.bcachefs libbcachefs_mount.a tests/test_helper .version $(OBJS) $(DEPS) $(DOCGENERATED)
$(RM) -rf mount/target
$(RM) -rf rust-src/*/target
.PHONY: deb
deb: all

View File

@ -32,15 +32,19 @@
tools
toolsValgrind
toolsDebug
mount
bch_bindgen
kernel;
musl-tools = pkgs.pkgsMusl.bcachefs.tools;
musl-mount = pkgs.pkgsMusl.bcachefs.mount;
tools-musl = pkgs.pkgsMusl.bcachefs.tools;
mount-musl = pkgs.pkgsMusl.bcachefs.mount;
};
checks = {
kernelSrc = packages.kernel.src;
inherit (packages)
mount
bch_bindgen
toolsValgrind;
};

15
rust-src/bch_bindgen/.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
# Required By Nix
# Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

484
rust-src/bch_bindgen/Cargo.lock generated Normal file
View File

@ -0,0 +1,484 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bch_bindgen"
version = "0.1.0"
dependencies = [
"anyhow",
"bindgen",
"bitfield",
"byteorder",
"gag",
"libc",
"memoffset",
"pkg-config",
"tracing",
"tracing-attributes",
"udev",
"uuid",
]
[[package]]
name = "bindgen"
version = "0.59.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453c49e5950bb0eb63bb3df640e31618846c89d5b7faa54040d76e98e0134375"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"lazy_static",
"lazycell",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
]
[[package]]
name = "bitfield"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitvec"
version = "0.19.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cexpr"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clang-sys"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10612c0ec0e0a1ff0e97980647cb058a6e7aedb913d01d009c406b8b7d0b26ee"
dependencies = [
"glob",
"libc",
]
[[package]]
name = "filedescriptor"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed3d8a5e20435ff00469e51a0d82049bae66504b5c429920dadf9bb54d47b3f"
dependencies = [
"libc",
"thiserror",
"winapi",
]
[[package]]
name = "funty"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
[[package]]
name = "gag"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a713bee13966e9fbffdf7193af71d54a6b35a0bb34997cd6c9519ebeb5005972"
dependencies = [
"filedescriptor",
"tempfile",
]
[[package]]
name = "getrandom"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
[[package]]
name = "libudev-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324"
dependencies = [
"libc",
"pkg-config",
]
[[package]]
name = "memchr"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
[[package]]
name = "memoffset"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa"
dependencies = [
"autocfg",
]
[[package]]
name = "nom"
version = "6.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6"
dependencies = [
"bitvec",
"funty",
"memchr",
"version_check",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "pin-project-lite"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
[[package]]
name = "pkg-config"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb"
[[package]]
name = "ppv-lite86"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "proc-macro2"
version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "radium"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
[[package]]
name = "rand"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core",
]
[[package]]
name = "redox_syscall"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[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 = "shlex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]]
name = "syn"
version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tempfile"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if",
"libc",
"rand",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "thiserror"
version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8"
dependencies = [
"cfg-if",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98863d0dd09fa59a1b79c6750ad80dbda6b75f4e71c437a6a1a8cb91a8bcbd77"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46125608c26121c81b0c6d693eab5a420e416da7e43c426d2e8f7df8da8a3acf"
dependencies = [
"lazy_static",
]
[[package]]
name = "udev"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24953d50a3bce0f5f5a9a2766567072dc9af8096f8c40ea81815da651066bc9f"
dependencies = [
"libc",
"libudev-sys",
]
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "uuid"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
[[package]]
name = "version_check"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
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 = "wyz"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"

View File

@ -0,0 +1,26 @@
[package]
name = "bch_bindgen"
version = "0.1.0"
authors = [ "Kayla Firestack <dev@kaylafire.me>", "Yuxuan Shui <yshuiv7@gmail.com>" ]
edition = "2018"
[lib]
crate-type = ["lib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tracing = "0.1.26"
anyhow = "1.0"
udev = "0.4"
uuid = "0.8"
bitfield = "0.13"
memoffset = "0.5"
byteorder = "1.3"
tracing-attributes = "0.1.15"
libc = "0.2.69"
gag = "1.0.0"
[build-dependencies]
pkg-config = "0.3"
bindgen = { version = "0.59.1", default-features = false }

View File

@ -0,0 +1,74 @@
fn main() {
use std::path::PathBuf;
// use std::process::Command;
let out_dir: PathBuf = std::env::var_os("OUT_DIR").expect("ENV Var 'OUT_DIR' Expected").into();
let top_dir: PathBuf = std::env::var_os("CARGO_MANIFEST_DIR")
.expect("ENV Var 'CARGO_MANIFEST_DIR' Expected")
.into();
let libbcachefs_inc_dir =
std::env::var("LIBBCACHEFS_INCLUDE").unwrap_or_else(|_| top_dir.join("libbcachefs").display().to_string());
let libbcachefs_inc_dir = std::path::Path::new(&libbcachefs_inc_dir);
println!("{}", libbcachefs_inc_dir.display());
println!("cargo:rustc-link-lib=dylib=bcachefs");
println!("cargo:rustc-link-search={}", env!("LIBBCACHEFS_LIB"));
let _libbcachefs_dir = top_dir.join("libbcachefs").join("libbcachefs");
let bindings = bindgen::builder()
.header(top_dir.join("src").join("libbcachefs_wrapper.h").display().to_string())
.clang_arg(format!("-I{}", libbcachefs_inc_dir.join("include").display()))
.clang_arg(format!("-I{}", libbcachefs_inc_dir.display()))
.clang_arg("-DZSTD_STATIC_LINKING_ONLY")
.clang_arg("-DNO_BCACHEFS_FS")
.clang_arg("-D_GNU_SOURCE")
.derive_debug(true)
.derive_default(true)
.derive_eq(true)
.layout_tests(true)
.default_enum_style(bindgen::EnumVariation::Rust { non_exhaustive: true })
.allowlist_function(".*bch2_.*")
// .allowlist_function("bch2_read_super")
// .allowlist_function("bch2_sb_field_.*")
// .allowlist_function("bch2_super_write")
// .allowlist_function("bch2_chacha_encrypt_key")
// .allowlist_function("__bch2_super_read")
.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")
.blocklist_type("bch_extent_ptr")
.blocklist_type("btree_node")
.blocklist_type("bch_extent_crc32")
.blocklist_type("rhash_lock_head")
.blocklist_type("srcu_struct")
.allowlist_var("BCH_.*")
.allowlist_var("KEY_SPEC_.*")
.allowlist_type("bch_kdf_types")
.allowlist_type("bch_sb_field_.*")
.allowlist_type("bch_encrypted_key")
.allowlist_type("nonce")
.newtype_enum("bch_kdf_types")
.opaque_type("gendisk")
.opaque_type("bkey")
// .opaque_type("bch_extent_ptr")
// .opaque_type("bch_extent_crc32")
.opaque_type("open_bucket.*")
.generate()
.expect("BindGen Generation Failiure: [libbcachefs_wrapper]");
bindings
.write_to_file(out_dir.join("bcachefs.rs"))
.expect("Writing to output file failed for: `bcachefs.rs`");
let keyutils = pkg_config::probe_library("libkeyutils").expect("Failed to find keyutils lib");
let bindings = bindgen::builder()
.header(top_dir.join("src").join("keyutils_wrapper.h").display().to_string())
.clang_args(keyutils.include_paths.iter().map(|p| format!("-I{}", p.display())))
.generate()
.expect("BindGen Generation Failiure: [Keyutils]");
bindings
.write_to_file(out_dir.join("keyutils.rs"))
.expect("Writing to output file failed for: `keyutils.rs`");
}

View File

@ -0,0 +1,2 @@
max_width=120
hard_tabs = true

View File

@ -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 {}

View File

@ -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"));

View File

@ -0,0 +1,7 @@
pub mod bcachefs;
pub mod keyutils;
pub mod rs;
pub mod c {
pub use crate::bcachefs::*;
}

View File

@ -1,4 +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"

View File

@ -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)
}

15
rust-src/mount/.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
# Needed by nix
# Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

View File

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.10"
@ -18,6 +20,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "anyhow"
version = "1.0.28"
@ -43,39 +54,56 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]]
name = "bcachefs-mount"
version = "0.3.1"
dependencies = [
"anyhow",
"bch_bindgen",
"byteorder",
"camino",
"clap",
"either",
"errno",
"gag",
"getset",
"itertools",
"libc",
"parse-display",
"rpassword",
"structopt",
"tracing",
"tracing-attributes",
"tracing-log",
"tracing-subscriber",
"udev",
"uuid",
]
[[package]]
name = "bch_bindgen"
version = "0.1.0"
dependencies = [
"anyhow",
"bindgen",
"bitfield",
"byteorder",
"clap",
"either",
"env_logger",
"errno",
"gag",
"getset",
"itertools",
"libc",
"log",
"memoffset",
"parse-display",
"pkg-config",
"rpassword",
"structopt",
"tracing",
"tracing-attributes",
"udev",
"uuid",
]
[[package]]
name = "bindgen"
version = "0.53.2"
version = "0.59.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bb26d6a69a335b8cb0e7c7e9775cd5666611dc50a37177c3f2cedcfc040e8c8"
checksum = "453c49e5950bb0eb63bb3df640e31618846c89d5b7faa54040d76e98e0134375"
dependencies = [
"bitflags",
"cexpr",
"cfg-if",
"clang-sys",
"lazy_static",
"lazycell",
@ -99,6 +127,18 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bitvec"
version = "0.19.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "byteorder"
version = "1.3.4"
@ -106,10 +146,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]]
name = "cexpr"
version = "0.4.0"
name = "camino"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b"
[[package]]
name = "cexpr"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89"
dependencies = [
"nom",
]
@ -121,10 +167,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "clang-sys"
version = "0.29.3"
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
dependencies = [
"libc",
"num-integer",
"num-traits",
"winapi",
]
[[package]]
name = "clang-sys"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10612c0ec0e0a1ff0e97980647cb058a6e7aedb913d01d009c406b8b7d0b26ee"
dependencies = [
"glob",
"libc",
@ -136,7 +200,7 @@ version = "2.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
dependencies = [
"ansi_term",
"ansi_term 0.11.0",
"atty",
"bitflags",
"strsim",
@ -152,15 +216,6 @@ version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"log",
]
[[package]]
name = "errno"
version = "0.2.5"
@ -183,12 +238,29 @@ dependencies = [
]
[[package]]
name = "gag"
version = "0.1.10"
name = "filedescriptor"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cc0b9f53275dc5fada808f1d2f82e3688a6c14d735633d1590b7be8eb2307b5"
checksum = "9ed3d8a5e20435ff00469e51a0d82049bae66504b5c429920dadf9bb54d47b3f"
dependencies = [
"libc",
"thiserror",
"winapi",
]
[[package]]
name = "funty"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
[[package]]
name = "gag"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a713bee13966e9fbffdf7193af71d54a6b35a0bb34997cd6c9519ebeb5005972"
dependencies = [
"filedescriptor",
"tempfile",
]
@ -204,7 +276,7 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
"libc",
"wasi",
]
@ -254,6 +326,12 @@ dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -288,7 +366,16 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
]
[[package]]
name = "matchers"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
dependencies = [
"regex-automata",
]
[[package]]
@ -308,14 +395,35 @@ dependencies = [
[[package]]
name = "nom"
version = "5.1.1"
version = "6.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6"
checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6"
dependencies = [
"bitvec",
"funty",
"memchr",
"version_check",
]
[[package]]
name = "num-integer"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "parse-display"
version = "0.1.1"
@ -347,6 +455,12 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "pin-project-lite"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
[[package]]
name = "pkg-config"
version = "0.3.17"
@ -429,6 +543,12 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "radium"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
[[package]]
name = "rand"
version = "0.7.3"
@ -488,6 +608,15 @@ dependencies = [
"thread_local",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.17"
@ -520,10 +649,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "shlex"
version = "0.1.1"
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "serde"
version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
[[package]]
name = "serde_json"
version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7f9e390c27c3c0ce8bc5d725f6e4d30a29d26659494aa4b17535f7522c5c950"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sharded-slab"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "740223c51853f3145fe7c90360d2d4232f2b62e3449489c207eccde818979982"
dependencies = [
"lazy_static",
]
[[package]]
name = "shlex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"
[[package]]
name = "smallvec"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]]
name = "strsim"
@ -533,9 +700,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "structopt"
version = "0.3.14"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef"
checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa"
dependencies = [
"clap",
"lazy_static",
@ -544,9 +711,9 @@ dependencies = [
[[package]]
name = "structopt-derive"
version = "0.4.7"
version = "0.4.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a"
checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba"
dependencies = [
"heck",
"proc-macro-error 1.0.2",
@ -577,13 +744,19 @@ dependencies = [
"syn",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tempfile"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
dependencies = [
"cfg-if",
"cfg-if 0.1.10",
"libc",
"rand",
"redox_syscall",
@ -611,6 +784,26 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thread_local"
version = "1.0.1"
@ -620,6 +813,81 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "tracing"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d"
dependencies = [
"cfg-if 1.0.0",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ca517f43f0fb96e0c3072ed5c275fe5eece87e8cb52f4a77b69226d3b1c9df8"
dependencies = [
"lazy_static",
]
[[package]]
name = "tracing-log"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3"
dependencies = [
"lazy_static",
"log",
"tracing-core",
]
[[package]]
name = "tracing-serde"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b"
dependencies = [
"serde",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9cbe87a2fa7e35900ce5de20220a582a9483a7063811defce79d7cbd59d4cfe"
dependencies = [
"ansi_term 0.12.1",
"chrono",
"lazy_static",
"matchers",
"regex",
"serde",
"serde_json",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
"tracing-serde",
]
[[package]]
name = "udev"
version = "0.4.0"
@ -693,3 +961,9 @@ 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 = "wyz"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"

View File

@ -1,34 +1,30 @@
[package]
name = "bcachefs-mount"
version = "0.1.0"
authors = ["Yuxuan Shui <yshuiv7@gmail.com>"]
version = "0.3.1"
authors = ["Yuxuan Shui <yshuiv7@gmail.com>", "Kayla Firestack <dev@kaylafire.me>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "0.4"
tracing = "0.1.26"
tracing-log = "0.1.2"
tracing-subscriber = "0.2.20"
tracing-attributes = "0.1.15"
clap = { version = "2.33", features = [ "wrap_help" ] }
env_logger = { version = "0.7", default-features = false }
anyhow = "1.0"
udev = "0.4"
uuid = "0.8"
libc = "0.2.69"
gag = "0.1"
bitfield = "0.13"
memoffset = "0.5"
uuid = "0.8"
udev = "0.4"
gag = "1.0.0"
getset = "0.1"
itertools = "0.9"
structopt = "0.3"
structopt = "0.3.23"
parse-display = "0.1"
errno = "0.2"
either = "1.5"
rpassword = "4"
camino = "1.0.5"
bch_bindgen = { path = "../bch_bindgen" }
byteorder = "1.3"
[lib]
crate-type = ["staticlib"]
[build-dependencies]
pkg-config = "0.3"
bindgen = { version = "0.53", default-features = false }

62
rust-src/mount/README.md Normal file
View File

@ -0,0 +1,62 @@
Usage
=====
```
bcachefs-mount 0.1.0
Mount a bcachefs filesystem by its UUID
USAGE:
bcachefs-mount [OPTIONS] <uuid> <mountpoint>
FLAGS:
-h, --help
Prints help information
-V, --version
Prints version information
OPTIONS:
-o <options>
Mount options [default: ]
-p, --password <password>
Where the password would be loaded from.
Possible values are: "fail" - don't ask for password, fail if filesystem is encrypted; "wait" - wait for
password to become available before mounting; "ask" - prompt the user for password; [default: fail]
ARGS:
<uuid>
External UUID of the bcachefs filesystem
<mountpoint>
Where the filesystem should be mounted
```
Caveats
=======
* `--password ask` is not yet implemented, but you can use `--password wait`, and load the key with `bcachefs unlock`.
Build
=====
```sh
$ git submodule update --init --recursive
$ cargo build --release
```
Binary will be built in `target/release/bcachefs-mount`
Dependencies:
* rust
* blkid
* uuid
* liburcu
* libsodium
* zlib
* liblz4
* libzstd
* libkeyutils

View File

@ -1,67 +0,0 @@
fn main() {
use std::path::PathBuf;
use std::process::Command;
let out_dir: PathBuf = std::env::var_os("OUT_DIR").unwrap().into();
let top_dir: PathBuf = std::env::var_os("CARGO_MANIFEST_DIR").unwrap().into();
let libbcachefs_inc_dir = std::env::var("LIBBCACHEFS_INCLUDE")
.unwrap_or_else(|_| top_dir.join("libbcachefs").display().to_string());
let libbcachefs_inc_dir = std::path::Path::new(&libbcachefs_inc_dir);
println!("{}", libbcachefs_inc_dir.display());
let libbcachefs_dir = top_dir.join("libbcachefs").join("libbcachefs");
let bindings = bindgen::builder()
.header(top_dir
.join("src")
.join("libbcachefs_wrapper.h")
.display()
.to_string())
.clang_arg(format!(
"-I{}",
libbcachefs_inc_dir.join("include").display()
))
.clang_arg(format!("-I{}", libbcachefs_inc_dir.display()))
.clang_arg("-DZSTD_STATIC_LINKING_ONLY")
.clang_arg("-DNO_BCACHEFS_FS")
.clang_arg("-D_GNU_SOURCE")
.derive_debug(false)
.derive_default(true)
.default_enum_style(bindgen::EnumVariation::Rust {
non_exhaustive: true,
})
.whitelist_function("bch2_read_super")
.whitelist_function("bch2_sb_field_.*")
.whitelist_function("bch2_chacha_encrypt_key")
.whitelist_function("derive_passphrase")
.whitelist_function("request_key")
.whitelist_function("add_key")
.whitelist_function("keyctl_search")
.whitelist_var("BCH_.*")
.whitelist_var("KEY_SPEC_.*")
.whitelist_type("bch_kdf_types")
.whitelist_type("bch_sb_field_.*")
.whitelist_type("bch_encrypted_key")
.whitelist_type("nonce")
.rustified_enum("bch_kdf_types")
.opaque_type("gendisk")
.opaque_type("bkey")
.generate()
.unwrap();
bindings.write_to_file(out_dir.join("bcachefs.rs")).unwrap();
let keyutils = pkg_config::probe_library("libkeyutils").unwrap();
let bindings = bindgen::builder()
.header(top_dir
.join("src")
.join("keyutils_wrapper.h")
.display()
.to_string())
.clang_args(
keyutils.include_paths
.iter()
.map(|p| format!("-I{}", p.display())),
)
.generate()
.unwrap();
bindings.write_to_file(out_dir.join("keyutils.rs")).unwrap();
}

View File

@ -27,8 +27,8 @@ in {
LIBCLANG_PATH
BINDGEN_EXTRA_CLANG_ARGS;
preFixup = ''
ln $out/bin/mount-bcachefs $out/bin/mount.bcachefs
postInstall = ''
ln $out/bin/${cargo.package.name} $out/bin/mount.bcachefs
ln -s $out/bin $out/sbin
'';
# -isystem ${llvmPackages.libclang.lib}/lib/clang/${lib.getVersion llvmPackages.libclang}/include";

54
rust-src/mount/module.nix Normal file
View File

@ -0,0 +1,54 @@
## Mirrors: https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/tasks/filesystems/bcachefs.nix
## with changes to use flakes and import mount.bcachefs
{ config, lib, pkgs, utils, ... }:
with lib;
let
bootFs = filterAttrs (n: fs: (fs.fsType == "bcachefs") && (utils.fsNeededForBoot fs)) config.fileSystems;
cfg = config.filesystems.bcachefs;
in
{
options.filesystems.bcachefs.packages.tools = lib.mkOption {
description = "Which package to use to link in the bcachefs tools package";
default = pkgs.bcachefs.tools;
type = lib.types.package;
};
options.filesystems.bcachefs.packages.mount = lib.mkOption {
description = "Which package to use to link in the bcachefs mount package";
default = pkgs.bcachefs.mount;
type = lib.types.package;
};
options.filesystems.bcachefs.packages.kernelPackages = lib.mkOption {
description = "Which package to use to link in the kernel package to use";
default = pkgs.bcachefs.kernelPackages;
type = lib.types.attrs;
};
config = mkIf (elem "bcachefs" config.boot.supportedFilesystems) (mkMerge [
{
system.fsPackages = [ cfg.packages.tools cfg.packages.mount ];
# use kernel package with bcachefs support until it's in mainline
boot.kernelPackages = cfg.packages.kernelPackages;
}
(mkIf ((elem "bcachefs" config.boot.initrd.supportedFilesystems) || (bootFs != {})) {
# chacha20 and poly1305 are required only for decryption attempts
boot.initrd.availableKernelModules = [ "sha256" "chacha20" "poly1305" ];
boot.initrd.kernelModules = [ "bcachefs" ];
boot.initrd.extraUtilsCommands = ''
copy_bin_and_libs ${cfg.packages.tools}/bin/bcachefs
copy_bin_and_libs ${cfg.packages.mount}/bin/mount.bcachefs
'';
boot.initrd.extraUtilsCommandsTest = ''
$out/bin/bcachefs version
$out/bin/mount.bcachefs --version
'';
})
]);
}

View File

@ -0,0 +1,2 @@
max_width=120
hard_tabs = true

View File

@ -19,11 +19,103 @@ pub struct FileSystem {
#[getset(get = "pub")]
devices: Vec<PathBuf>,
}
impl std::fmt::Debug for FileSystem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FileSystem")
.field("uuid", &self.uuid)
.field("encrypted", &self.encrypted)
.field("devices", &self.device_string())
.finish()
}
}
use std::fmt;
impl std::fmt::Display for FileSystem {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let devs = self.device_string();
write!(
f,
"{:?}: locked?={lock} ({}) ",
self.uuid,
devs,
lock = self.encrypted
)
}
}
impl FileSystem {
pub(crate) fn new(sb: bcachefs::bch_sb_handle) -> Self {
Self {
uuid: sb.sb().uuid(),
encrypted: sb.sb().crypt().is_some(),
sb: sb,
devices: Vec::new(),
}
}
pub fn device_string(&self) -> String {
use itertools::Itertools;
self.devices.iter().map(|d| d.display()).join(":")
}
pub fn mount(
&self,
target: impl AsRef<std::path::Path>,
options: impl AsRef<str>,
) -> anyhow::Result<()> {
tracing::info_span!("mount").in_scope(|| {
let src = self.device_string();
let (data, mountflags) = parse_mount_options(options);
// let fstype = c_str!("bcachefs");
tracing::info!(msg="mounting bcachefs filesystem", target=%target.as_ref().display());
mount_inner(src, target, "bcachefs", mountflags, data)
})
}
}
fn mount_inner(
src: String,
target: impl AsRef<std::path::Path>,
fstype: &str,
mountflags: u64,
data: Option<String>,
) -> anyhow::Result<()> {
use std::{
ffi::{c_void, CString},
os::{raw::c_char, unix::ffi::OsStrExt},
};
// bind the CStrings to keep them alive
let src = CString::new(src)?;
let target = CString::new(target.as_ref().as_os_str().as_bytes())?;
let data = data.map(CString::new).transpose()?;
let fstype = CString::new(fstype)?;
// convert to pointers for ffi
let src = src.as_c_str().to_bytes_with_nul().as_ptr() as *const c_char;
let target = target.as_c_str().to_bytes_with_nul().as_ptr() as *const c_char;
let data = data.as_ref().map_or(std::ptr::null(), |data| {
data.as_c_str().to_bytes_with_nul().as_ptr() as *const c_void
});
let fstype = fstype.as_c_str().to_bytes_with_nul().as_ptr() as *const c_char;
let ret = {let _entered = tracing::info_span!("libc::mount").entered();
tracing::info!("mounting filesystem");
// REQUIRES: CAP_SYS_ADMIN
unsafe { libc::mount(src, target, fstype, mountflags, data) }
};
match ret {
0 => Ok(()),
_ => Err(crate::ErrnoError(errno::errno()).into()),
}
}
/// Parse a comma-separated mount options and split out mountflags and filesystem
/// specific options.
#[tracing_attributes::instrument(skip(options))]
fn parse_mount_options(options: impl AsRef<str>) -> (Option<String>, u64) {
use either::Either::*;
tracing::debug!(msg="parsing mount options", options=?options.as_ref());
let (opts, flags) = options
.as_ref()
.split(",")
@ -63,112 +155,54 @@ fn parse_mount_options(options: impl AsRef<str>) -> (Option<String>, u64) {
)
}
impl FileSystem {
pub(crate) fn new(sb: bcachefs::bch_sb_handle) -> Self {
Self {
uuid: sb.sb().uuid(),
encrypted: sb.sb().crypt().is_some(),
sb: sb,
devices: vec![],
}
}
pub fn mount(
&self,
target: impl AsRef<std::path::Path>,
options: impl AsRef<str>,
) -> anyhow::Result<()> {
use itertools::Itertools;
use std::ffi::c_void;
use std::os::raw::c_char;
use std::os::unix::ffi::OsStrExt;
let src = self.devices.iter().map(|d| d.display()).join(":");
let (data, mountflags) = parse_mount_options(options);
let fstype = c_str!("bcachefs");
let src = std::ffi::CString::new(src)?; // bind the CString to keep it alive
let target = std::ffi::CString::new(target.as_ref().as_os_str().as_bytes())?; // ditto
let data = data.map(|data| std::ffi::CString::new(data)).transpose()?; // ditto
let src = src.as_c_str().to_bytes_with_nul().as_ptr() as *const c_char;
let target = target.as_c_str().to_bytes_with_nul().as_ptr() as *const c_char;
let data = data.as_ref().map_or(std::ptr::null(), |data| {
data.as_c_str().to_bytes_with_nul().as_ptr() as *const c_void
});
let ret = unsafe { libc::mount(src, target, fstype, mountflags, data) };
if ret == 0 {
Ok(())
} else {
Err(crate::ErrnoError(errno::errno()).into())
}
}
}
use crate::bcachefs;
use bch_bindgen::bcachefs;
use std::collections::HashMap;
use uuid::Uuid;
pub fn probe_filesystems() -> anyhow::Result<HashMap<Uuid, FileSystem>> {
use std::os::unix::ffi::OsStrExt;
let mut udev = udev::Enumerator::new()?;
let mut fss = HashMap::new();
udev.match_subsystem("block")?;
{
// Stop libbcachefs from spamming the output
let _gag = gag::Gag::stdout().unwrap();
for dev in udev.scan_devices()? {
if let Some(p) = dev.devnode() {
let path =
std::ffi::CString::new(p.as_os_str().as_bytes()).unwrap();
let result = unsafe {
let mut opts = std::mem::MaybeUninit::zeroed();
let mut sb = std::mem::MaybeUninit::zeroed();
let ret = bcachefs::bch2_read_super(
path.as_ptr(),
opts.as_mut_ptr(),
sb.as_mut_ptr(),
);
if ret == -libc::EACCES {
Err(std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
"no permission",
))
} else if ret != 0 {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"failed to read super",
))
} else {
Ok((opts.assume_init(), sb.assume_init()))
}
};
match result {
Ok((_, sb)) => match fss.get_mut(&sb.sb().uuid()) {
None => {
let mut fs = FileSystem::new(sb);
fs.devices.push(p.to_owned());
fss.insert(fs.uuid, fs);
}
Some(fs) => {
fs.devices.push(p.to_owned());
}
},
Err(e) if e.kind()
!= std::io::ErrorKind::PermissionDenied =>
{
()
}
e @ Err(_) => {
e?;
}
}
}
}
// Flush stdout so buffered output don't get printed after we remove the gag
unsafe {
libc::fflush(stdout);
#[tracing_attributes::instrument]
pub fn probe_filesystems() -> anyhow::Result<HashMap<Uuid, FileSystem>> {
tracing::trace!("enumerating udev devices");
let mut udev = udev::Enumerator::new()?;
udev.match_subsystem("block")?; // find kernel block devices
let mut fs_map = HashMap::new();
let devresults =
udev.scan_devices()?
.into_iter()
.filter_map(|dev| dev.devnode().map(ToOwned::to_owned));
for pathbuf in devresults {
match get_super_block_uuid(&pathbuf)? {
Ok((uuid_key, superblock)) => {
let fs = fs_map.entry(uuid_key).or_insert_with(|| {
tracing::info!(msg="found bcachefs pool", uuid=?uuid_key);
FileSystem::new(superblock)
});
fs.devices.push(pathbuf);
},
Err(e) => { tracing::debug!(inner2_error=?e);}
}
}
Ok(fss)
tracing::info!(msg = "found filesystems", count = fs_map.len());
Ok(fs_map)
}
// #[tracing_attributes::instrument(skip(dev, fs_map))]
fn get_super_block_uuid(path: &std::path::Path) -> std::io::Result<std::io::Result<(Uuid, bcachefs::bch_sb_handle)>> {
let sb = bch_bindgen::rs::read_super(&path)?;
let super_block = match sb {
Err(e) => { return Ok(Err(e)); }
Ok(sb) => sb,
};
let uuid = (&super_block).sb().uuid();
tracing::debug!(found="bcachefs superblock", devnode=?path, ?uuid);
Ok(Ok((uuid, super_block)))
}

View File

@ -1,12 +1,11 @@
use log::info;
use tracing::info;
fn check_for_key(key_name: &std::ffi::CStr) -> anyhow::Result<bool> {
use crate::keyutils::{self, keyctl_search};
use bch_bindgen::keyutils::{self, keyctl_search};
let key_name = key_name.to_bytes_with_nul().as_ptr() as *const _;
let key_type = c_str!("logon");
let key_id =
unsafe { keyctl_search(keyutils::KEY_SPEC_USER_KEYRING, key_type, key_name, 0) };
let key_id = unsafe { keyctl_search(keyutils::KEY_SPEC_USER_KEYRING, key_type, key_name, 0) };
if key_id > 0 {
info!("Key has became avaiable");
Ok(true)
@ -31,9 +30,9 @@ fn wait_for_key(uuid: &uuid::Uuid) -> anyhow::Result<()> {
const BCH_KEY_MAGIC: &str = "bch**key";
use crate::filesystem::FileSystem;
fn ask_for_key(fs: &FileSystem) -> anyhow::Result<()> {
use crate::bcachefs::{self, bch2_chacha_encrypt_key, bch_encrypted_key, bch_key};
use anyhow::anyhow;
use byteorder::{LittleEndian, ReadBytesExt};
use bch_bindgen::bcachefs::{self, bch2_chacha_encrypt_key, bch_encrypted_key, bch_key};
use std::os::raw::c_char;
let key_name = std::ffi::CString::new(format!("bcachefs:{}", fs.uuid())).unwrap();
@ -62,19 +61,18 @@ fn ask_for_key(fs: &FileSystem) -> anyhow::Result<()> {
)
};
if ret != 0 {
Err(anyhow!("chache decryption failure"))
Err(anyhow!("chacha decryption failure"))
} else if key.magic != bch_key_magic {
Err(anyhow!("failed to verify the password"))
} else {
let key_type = c_str!("logon");
let ret = unsafe {
crate::keyutils::add_key(
bch_bindgen::keyutils::add_key(
key_type,
key_name.as_c_str().to_bytes_with_nul() as *const _
as *const c_char,
key_name.as_c_str().to_bytes_with_nul() as *const _ as *const c_char,
&output as *const _ as *const _,
std::mem::size_of::<bch_key>() as u64,
crate::keyutils::KEY_SPEC_USER_KEYRING,
bch_bindgen::keyutils::KEY_SPEC_USER_KEYRING,
)
};
if ret == -1 {
@ -85,9 +83,12 @@ fn ask_for_key(fs: &FileSystem) -> anyhow::Result<()> {
}
}
pub(crate) fn prepare_key(fs: &FileSystem, password: crate::KeyLocation) -> anyhow::Result<()> {
#[tracing_attributes::instrument]
pub fn prepare_key(fs: &FileSystem, password: crate::KeyLocation) -> anyhow::Result<()> {
use crate::KeyLocation::*;
use anyhow::anyhow;
tracing::info!(msg = "checking if key exists for filesystem");
match password {
Fail => Err(anyhow!("no key available")),
Wait => Ok(wait_for_key(fs.uuid())?),

View File

@ -1,12 +1,24 @@
use structopt::StructOpt;
use anyhow::anyhow;
use structopt::StructOpt;
pub mod err {
pub enum GError {
Unknown{
message: std::borrow::Cow<'static, String>
}
}
pub type GResult<T, E, OE> =::core::result::Result< ::core::result::Result<T, E>, OE>;
pub type Result<T, E> = GResult<T, E, GError>;
}
#[macro_export]
macro_rules! c_str {
($lit:expr) => {
unsafe { std::ffi::CStr::from_ptr(concat!($lit, "\0").as_ptr() as *const std::os::raw::c_char)
.to_bytes_with_nul()
.as_ptr() as *const std::os::raw::c_char }
unsafe {
std::ffi::CStr::from_ptr(concat!($lit, "\0").as_ptr() as *const std::os::raw::c_char)
.to_bytes_with_nul()
.as_ptr() as *const std::os::raw::c_char
}
};
}
@ -20,171 +32,60 @@ impl std::fmt::Display for ErrnoError {
impl std::error::Error for ErrnoError {}
#[derive(Debug)]
pub(crate) enum KeyLocation {
pub enum KeyLocation {
Fail,
Wait,
Ask,
}
impl std::str::FromStr for KeyLocation {
#[derive(Debug)]
pub struct KeyLoc(pub Option<KeyLocation>);
impl std::ops::Deref for KeyLoc {
type Target = Option<KeyLocation>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::str::FromStr for KeyLoc {
type Err = anyhow::Error;
fn from_str(s: &str) -> anyhow::Result<Self> {
use anyhow::anyhow;
// use anyhow::anyhow;
match s {
"fail" => Ok(Self::Fail),
"wait" => Ok(Self::Wait),
"ask" => Ok(Self::Ask),
_ => Err(anyhow!("invalid password option"))
"" => Ok(KeyLoc(None)),
"fail" => Ok(KeyLoc(Some(KeyLocation::Fail))),
"wait" => Ok(KeyLoc(Some(KeyLocation::Wait))),
"ask" => Ok(KeyLoc(Some(KeyLocation::Ask))),
_ => Err(anyhow!("invalid password option")),
}
}
}
#[derive(StructOpt, Debug)]
/// Mount a bcachefs filesystem by its UUID.
struct Options {
pub struct Options {
/// Where the password would be loaded from.
///
/// Possible values are:
/// "fail" - don't ask for password, fail if filesystem is encrypted;
/// "wait" - wait for password to become available before mounting;
/// "ask" - prompt the user for password;
#[structopt(short, long, default_value = "fail")]
key_location: KeyLocation,
#[structopt(short, long, default_value = "")]
pub key_location: KeyLoc,
/// External UUID of the bcachefs filesystem
uuid: uuid::Uuid,
pub uuid: uuid::Uuid,
/// Where the filesystem should be mounted. If not set, then the filesystem
/// won't actually be mounted. But all steps preceeding mounting the
/// filesystem (e.g. asking for passphrase) will still be performed.
mountpoint: Option<std::path::PathBuf>,
pub mountpoint: Option<std::path::PathBuf>,
/// Mount options
#[structopt(short, default_value = "")]
options: String,
pub options: String,
}
mod filesystem;
mod key;
mod keyutils {
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(unused)]
pub mod filesystem;
pub mod key;
include!(concat!(env!("OUT_DIR"), "/keyutils.rs"));
}
mod bcachefs {
#![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);
TYPE, _: 4, 0;
}
use memoffset::offset_of;
impl bch_sb_field_crypt {
pub fn scrypt_flags(&self) -> Option<bch_scrypt_flags> {
let t = bch_crypt_flags(self.flags);
if t.TYPE() != bch_kdf_types::BCH_KDF_SCRYPT as u64 {
None
} else {
Some(bch_scrypt_flags(self.kdf_flags))
}
}
pub fn key(&self) -> &bch_encrypted_key {
&self.key
}
}
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::{ReadBytesExt, LittleEndian};
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 }
}
}
}
fn main_inner() -> anyhow::Result<()> {
use itertools::Itertools;
use log::{info, trace};
env_logger::init();
let opt = Options::from_args();
trace!("{:?}", opt);
let fss = filesystem::probe_filesystems()?;
info!("Found {} bcachefs filesystems: ", fss.len());
for fs in fss.values() {
info!(
"{} ({}): {}",
fs.uuid(),
if fs.encrypted() {
"encrypted"
} else {
"unencrypted"
},
fs.devices().iter().map(|d| d.display()).join(" ")
);
}
if let Some(fs) = fss.get(&opt.uuid) {
if fs.encrypted() {
info!("Making sure key is loaded for this filesystem");
key::prepare_key(&fs, opt.key_location)?;
}
if let Some(p) = opt.mountpoint {
fs.mount(&p, &opt.options)
} else {
Ok(())
}
} else {
Err(anyhow!("Filesystem {} is not found", opt.uuid))
}
}
#[no_mangle]
pub extern "C" fn main() {
if let Err(e) = main_inner() {
println!("Error: {:?}", e);
}
}
// pub fn mnt_in_use()

View File

@ -0,0 +1,63 @@
fn main() {
// convert existing log statements to tracing events
// tracing_log::LogTracer::init().expect("logtracer init failed!");
// format tracing log data to env_logger like stdout
tracing_subscriber::fmt::init();
if let Err(e) = crate::main_inner() {
tracing::error!(fatal_error = ?e);
}
}
#[tracing_attributes::instrument("main")]
pub fn main_inner() -> anyhow::Result<()> {
use structopt::StructOpt;
use bcachefs_mount::{Options, filesystem, key};
unsafe {
libc::setvbuf(
filesystem::stdout,
std::ptr::null_mut(),
libc::_IONBF,
0,
);
// libc::fflush(filesystem::stdout);
}
let opt = Options::from_args();
tracing::trace!(?opt);
let fss = filesystem::probe_filesystems()?;
let fs = fss
.get(&opt.uuid)
.ok_or_else(|| anyhow::anyhow!("filesystem was not found"))?;
tracing::info!(msg="found filesystem", %fs);
if fs.encrypted() {
let key = opt
.key_location
.0
.ok_or_else(|| anyhow::anyhow!("no keyoption specified for locked filesystem"))?;
key::prepare_key(&fs, key)?;
}
let mountpoint = opt
.mountpoint
.ok_or_else(|| anyhow::anyhow!("mountpoint option was not specified"))?;
fs.mount(&mountpoint, &opt.options)?;
Ok(())
}
#[cfg(test)]
mod test {
// use insta::assert_debug_snapshot;
// #[test]
// fn snapshot_testing() {
// insta::assert_debug_snapshot!();
// }
}