]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
split mount into a library crate for rust reuse
authorKayla Firestack <dev@kaylafire.me>
Mon, 18 Oct 2021 17:27:51 +0000 (13:27 -0400)
committerKayla Firestack <dev@kaylafire.me>
Mon, 18 Oct 2021 20:30:52 +0000 (16:30 -0400)
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

25 files changed:
Makefile
flake.nix
rust-src/bch_bindgen/.gitignore [new file with mode: 0644]
rust-src/bch_bindgen/Cargo.lock [new file with mode: 0644]
rust-src/bch_bindgen/Cargo.toml [new file with mode: 0644]
rust-src/bch_bindgen/build.rs [new file with mode: 0644]
rust-src/bch_bindgen/rustfmt.toml [new file with mode: 0644]
rust-src/bch_bindgen/src/bcachefs.rs [new file with mode: 0644]
rust-src/bch_bindgen/src/keyutils.rs [new file with mode: 0644]
rust-src/bch_bindgen/src/keyutils_wrapper.h [moved from rust-src/mount/src/keyutils_wrapper.h with 100% similarity]
rust-src/bch_bindgen/src/lib.rs [new file with mode: 0644]
rust-src/bch_bindgen/src/libbcachefs_wrapper.h [moved from rust-src/mount/src/libbcachefs_wrapper.h with 59% similarity]
rust-src/bch_bindgen/src/rs.rs [new file with mode: 0644]
rust-src/mount/.gitignore [new file with mode: 0644]
rust-src/mount/Cargo.lock
rust-src/mount/Cargo.toml
rust-src/mount/README.md [new file with mode: 0644]
rust-src/mount/build.rs [deleted file]
rust-src/mount/default.nix
rust-src/mount/module.nix [new file with mode: 0644]
rust-src/mount/rustfmt.toml [new file with mode: 0644]
rust-src/mount/src/filesystem.rs
rust-src/mount/src/key.rs
rust-src/mount/src/lib.rs
rust-src/mount/src/main.rs [new file with mode: 0644]

index 9ee1ff00dc605871abb79b6a6c211a0a9d99e6f4..dc56d7bb489a2a087784cd0af4b8ed5e6e06476e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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
index 36dda0ec8479272b81c0004c3bf40452260e4948..02df6c73cedfebe55caaaf5a243d15bb5725508f 100644 (file)
--- a/flake.nix
+++ b/flake.nix
                                        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;
                        };
 
diff --git a/rust-src/bch_bindgen/.gitignore b/rust-src/bch_bindgen/.gitignore
new file mode 100644 (file)
index 0000000..0aa133a
--- /dev/null
@@ -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
diff --git a/rust-src/bch_bindgen/Cargo.lock b/rust-src/bch_bindgen/Cargo.lock
new file mode 100644 (file)
index 0000000..2138d33
--- /dev/null
@@ -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"
diff --git a/rust-src/bch_bindgen/Cargo.toml b/rust-src/bch_bindgen/Cargo.toml
new file mode 100644 (file)
index 0000000..91cc77f
--- /dev/null
@@ -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 }
diff --git a/rust-src/bch_bindgen/build.rs b/rust-src/bch_bindgen/build.rs
new file mode 100644 (file)
index 0000000..fd570db
--- /dev/null
@@ -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`");
+}
diff --git a/rust-src/bch_bindgen/rustfmt.toml b/rust-src/bch_bindgen/rustfmt.toml
new file mode 100644 (file)
index 0000000..a2b7f32
--- /dev/null
@@ -0,0 +1,2 @@
+max_width=120
+hard_tabs = true
diff --git a/rust-src/bch_bindgen/src/bcachefs.rs b/rust-src/bch_bindgen/src/bcachefs.rs
new file mode 100644 (file)
index 0000000..cc98ffc
--- /dev/null
@@ -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 (file)
index 0000000..30fc56f
--- /dev/null
@@ -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/lib.rs b/rust-src/bch_bindgen/src/lib.rs
new file mode 100644 (file)
index 0000000..c19b5a2
--- /dev/null
@@ -0,0 +1,7 @@
+pub mod bcachefs;
+pub mod keyutils;
+pub mod rs;
+
+pub mod c {
+       pub use crate::bcachefs::*;
+}
similarity index 59%
rename from rust-src/mount/src/libbcachefs_wrapper.h
rename to rust-src/bch_bindgen/src/libbcachefs_wrapper.h
index 9d9754c12e63386c2fa12b7ca5247a18ab5edee7..2a0e7026068582c3f2b33ff855e0f726f347c4a3 100644 (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"
+
diff --git a/rust-src/bch_bindgen/src/rs.rs b/rust-src/bch_bindgen/src/rs.rs
new file mode 100644 (file)
index 0000000..4452f0b
--- /dev/null
@@ -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)
+}
diff --git a/rust-src/mount/.gitignore b/rust-src/mount/.gitignore
new file mode 100644 (file)
index 0000000..644cd42
--- /dev/null
@@ -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
index 77ccbba753cb14e535d5ff0933e146b0ba5863cf..92d13cf5b370443f7964a3598d4e2409da7e0888 100644 (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.1.0"
+version = "0.3.1"
 dependencies = [
  "anyhow",
- "bindgen",
- "bitfield",
+ "bch_bindgen",
  "byteorder",
+ "camino",
  "clap",
  "either",
- "env_logger",
  "errno",
  "gag",
  "getset",
  "itertools",
  "libc",
- "log",
- "memoffset",
  "parse-display",
- "pkg-config",
  "rpassword",
  "structopt",
+ "tracing",
+ "tracing-attributes",
+ "tracing-log",
+ "tracing-subscriber",
+ "udev",
+ "uuid",
+]
+
+[[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.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,17 +127,35 @@ 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"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
 
+[[package]]
+name = "camino"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b"
+
 [[package]]
 name = "cexpr"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
+checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89"
 dependencies = [
  "nom",
 ]
@@ -120,11 +166,29 @@ version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
 
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+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 = "0.29.3"
+version = "1.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a"
+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"
@@ -519,11 +648,49 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
+[[package]]
+name = "ryu"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+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 = "0.1.1"
+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 = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
+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"
index 4fd0d497bdeeab204064d3da695a025ade0db368..d48d4f727d917b01350764f75ce9fa11e6e7c9d1 100644 (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 }
diff --git a/rust-src/mount/README.md b/rust-src/mount/README.md
new file mode 100644 (file)
index 0000000..e4700f6
--- /dev/null
@@ -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
diff --git a/rust-src/mount/build.rs b/rust-src/mount/build.rs
deleted file mode 100644 (file)
index 6542889..0000000
+++ /dev/null
@@ -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();
-}
index 84c046b15a85392d524c325b92eb85b68c2009bf..dab7db770f73b3e2bee63ae0fa145ecad7ee8f5e 100644 (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";
diff --git a/rust-src/mount/module.nix b/rust-src/mount/module.nix
new file mode 100644 (file)
index 0000000..b62aa7d
--- /dev/null
@@ -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
+                       '';
+               })
+       ]);
+}
diff --git a/rust-src/mount/rustfmt.toml b/rust-src/mount/rustfmt.toml
new file mode 100644 (file)
index 0000000..a2b7f32
--- /dev/null
@@ -0,0 +1,2 @@
+max_width=120
+hard_tabs = true
index 36af8c058c7a0044c4d4ee464dccfe2de6d34c89..b1575c26590e684c4df6a9231894beefc79d4ab3 100644 (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;
+
+#[tracing_attributes::instrument]
 pub fn probe_filesystems() -> anyhow::Result<HashMap<Uuid, FileSystem>> {
-       use std::os::unix::ffi::OsStrExt;
+       tracing::trace!("enumerating udev devices");
        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);
+
+       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)))
 }
index 6769f52c4a8b127db63caaf70585921f6499c180..91c92d1c22997ee4bcba12e81927b27f7953ca32 100644 (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())?),
index 751eab38168ef6aae10cff4b73f51f26b08bccb4..4e918e13edd050817b54689e2a703dfeaac6b540 100644 (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,
-}
-
-mod filesystem;
-mod key;
-mod keyutils {
-       #![allow(non_upper_case_globals)]
-       #![allow(non_camel_case_types)]
-       #![allow(non_snake_case)]
-       #![allow(unused)]
-
-       include!(concat!(env!("OUT_DIR"), "/keyutils.rs"));
+       pub options: String,
 }
 
-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"));
+pub mod filesystem;
+pub mod key;
 
-       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()
diff --git a/rust-src/mount/src/main.rs b/rust-src/mount/src/main.rs
new file mode 100644 (file)
index 0000000..92b6917
--- /dev/null
@@ -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!();
+       // }
+}