mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-02 00:00:03 +03:00
Add a mount.bcachefs tool
This tool currently has most of the fundmental features implemented. It can mount a filesystem specified by uuid, it can ask password for an encrypted filesystem. There may be some work that needs to be done to make it behave more like a "mount.*" tool. Related: #1 Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
06c81e31b5
commit
57ada395b2
@ -22,6 +22,7 @@ addons:
|
||||
- libsodium-dev
|
||||
- liburcu-dev
|
||||
- libzstd-dev
|
||||
- libudev-dev
|
||||
- uuid-dev
|
||||
- zlib1g-dev
|
||||
|
||||
|
19
Makefile
19
Makefile
@ -39,7 +39,7 @@ ifdef D
|
||||
CFLAGS+=-DCONFIG_VALGRIND=y
|
||||
endif
|
||||
|
||||
PKGCONFIG_LIBS="blkid uuid liburcu libsodium zlib liblz4 libzstd"
|
||||
PKGCONFIG_LIBS="blkid uuid liburcu libsodium zlib liblz4 libzstd libudev"
|
||||
ifdef BCACHEFS_FUSE
|
||||
PKGCONFIG_LIBS+="fuse3 >= 3.7"
|
||||
CFLAGS+=-DBCACHEFS_FUSE
|
||||
@ -57,7 +57,7 @@ endif
|
||||
CFLAGS+=$(PKGCONFIG_CFLAGS)
|
||||
LDLIBS+=$(PKGCONFIG_LDLIBS)
|
||||
|
||||
LDLIBS+=-lm -lpthread -lrt -lscrypt -lkeyutils -laio
|
||||
LDLIBS+=-lm -lpthread -lrt -lscrypt -lkeyutils -laio -ldl
|
||||
LDLIBS+=$(EXTRA_LDLIBS)
|
||||
|
||||
ifeq ($(PREFIX),/usr)
|
||||
@ -69,7 +69,7 @@ else
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
all: bcachefs
|
||||
all: bcachefs mount.bcachefs
|
||||
|
||||
.PHONY: tests
|
||||
tests: tests/test_helper
|
||||
@ -92,6 +92,16 @@ 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
|
||||
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)
|
||||
|
||||
tests/test_helper: $(filter ./tests/%.o, $(OBJS))
|
||||
|
||||
# If the version string differs from the last build, update the last version
|
||||
@ -119,7 +129,8 @@ install: bcachefs
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) bcachefs tests/test_helper .version $(OBJS) $(DEPS)
|
||||
$(RM) bcachefs mount.bcachefs libbcachefs_mount.a tests/test_helper .version $(OBJS) $(DEPS)
|
||||
$(RM) -rf mount/target
|
||||
|
||||
.PHONY: deb
|
||||
deb: all
|
||||
|
695
mount/Cargo.lock
generated
Normal file
695
mount/Cargo.lock
generated
Normal file
@ -0,0 +1,695 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9a60d744a80c30fcb657dfe2c1b22bcb3e814c1a1e3674f32bf5820b570fbff"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||
|
||||
[[package]]
|
||||
name = "bcachefs-mount"
|
||||
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",
|
||||
"udev",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.53.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bb26d6a69a335b8cb0e7c7e9775cd5666611dc50a37177c3f2cedcfc040e8c8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"cfg-if",
|
||||
"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.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "0.29.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
"bitflags",
|
||||
"strsim",
|
||||
"term_size",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
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"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b480f641ccf0faf324e20c1d3e53d81b7484c698b42ea677f6907ae4db195371"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067"
|
||||
dependencies = [
|
||||
"gcc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gag"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cc0b9f53275dc5fada808f1d2f82e3688a6c14d735633d1590b7be8eb2307b5"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gcc"
|
||||
version = "0.3.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getset"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f62a139c59ae846c3964c392f12aac68f1997d1a40e9d3b40a89a4ab553e04a0"
|
||||
dependencies = [
|
||||
"proc-macro-error 0.4.12",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[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.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99e85c08494b21a9054e7fe1374a732aeadaff3980b6990b94bfd3a70f690005"
|
||||
|
||||
[[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 = "log"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "5.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b471253da97532da4b61552249c521e01e736071f71c1a4f7ebbfbf0a06aad6"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-display"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "718b422bc6b056b6374f7ffc3b2d9b55180a4af59a089835df1963994676d8b6"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"parse-display-derive",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-display-derive"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7cf2deb364a60cc0f633c1ffe619b42463993c91352ae367010b8420e442655"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"regex-syntax",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peeking_take_while"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr 0.4.12",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr 1.0.2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn-mid",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn-mid",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rpassword"
|
||||
version = "4.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99371657d3c8e4d816fb6221db98fa408242b0b53bac08f8676a41f8554fe99f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"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 = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "structopt"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"lazy_static",
|
||||
"structopt-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "structopt-derive"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error 1.0.2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "410a7488c0a728c7ceb4ad59b9567eb4053d02e8cc7f5c0e0eeeb39518369213"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn-mid"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"rand",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term_size"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
dependencies = [
|
||||
"term_size",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
||||
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-segmentation"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||
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"
|
34
mount/Cargo.toml
Normal file
34
mount/Cargo.toml
Normal file
@ -0,0 +1,34 @@
|
||||
[package]
|
||||
name = "bcachefs-mount"
|
||||
version = "0.1.0"
|
||||
authors = ["Yuxuan Shui <yshuiv7@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
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"
|
||||
getset = "0.1"
|
||||
itertools = "0.9"
|
||||
structopt = "0.3"
|
||||
parse-display = "0.1"
|
||||
errno = "0.2"
|
||||
either = "1.5"
|
||||
rpassword = "4"
|
||||
byteorder = "1.3"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[build-dependencies]
|
||||
pkg-config = "0.3"
|
||||
bindgen = { version = "0.53", default-features = false }
|
67
mount/build.rs
Normal file
67
mount/build.rs
Normal file
@ -0,0 +1,67 @@
|
||||
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();
|
||||
}
|
174
mount/src/filesystem.rs
Normal file
174
mount/src/filesystem.rs
Normal file
@ -0,0 +1,174 @@
|
||||
extern "C" {
|
||||
pub static stdout: *mut libc::FILE;
|
||||
}
|
||||
|
||||
use getset::{CopyGetters, Getters};
|
||||
use std::path::PathBuf;
|
||||
#[derive(Getters, CopyGetters)]
|
||||
pub struct FileSystem {
|
||||
/// External UUID of the bcachefs
|
||||
#[getset(get = "pub")]
|
||||
uuid: uuid::Uuid,
|
||||
/// Whether filesystem is encrypted
|
||||
#[getset(get_copy = "pub")]
|
||||
encrypted: bool,
|
||||
/// Super block
|
||||
#[getset(get = "pub")]
|
||||
sb: bcachefs::bch_sb_handle,
|
||||
/// Member devices for this filesystem
|
||||
#[getset(get = "pub")]
|
||||
devices: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
/// Parse a comma-separated mount options and split out mountflags and filesystem
|
||||
/// specific options.
|
||||
fn parse_mount_options(options: impl AsRef<str>) -> (Option<String>, u64) {
|
||||
use either::Either::*;
|
||||
let (opts, flags) = options
|
||||
.as_ref()
|
||||
.split(",")
|
||||
.map(|o| match o {
|
||||
"dirsync" => Left(libc::MS_DIRSYNC),
|
||||
"lazytime" => Left(1 << 25), // MS_LAZYTIME
|
||||
"mand" => Left(libc::MS_MANDLOCK),
|
||||
"noatime" => Left(libc::MS_NOATIME),
|
||||
"nodev" => Left(libc::MS_NODEV),
|
||||
"nodiratime" => Left(libc::MS_NODIRATIME),
|
||||
"noexec" => Left(libc::MS_NOEXEC),
|
||||
"nosuid" => Left(libc::MS_NOSUID),
|
||||
"ro" => Left(libc::MS_RDONLY),
|
||||
"rw" => Left(0),
|
||||
"relatime" => Left(libc::MS_RELATIME),
|
||||
"strictatime" => Left(libc::MS_STRICTATIME),
|
||||
"sync" => Left(libc::MS_SYNCHRONOUS),
|
||||
"" => Left(0),
|
||||
o @ _ => Right(o),
|
||||
})
|
||||
.fold((Vec::new(), 0), |(mut opts, flags), next| match next {
|
||||
Left(f) => (opts, flags | f),
|
||||
Right(o) => {
|
||||
opts.push(o);
|
||||
(opts, flags)
|
||||
}
|
||||
});
|
||||
|
||||
use itertools::Itertools;
|
||||
(
|
||||
if opts.len() == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(opts.iter().join(","))
|
||||
},
|
||||
flags,
|
||||
)
|
||||
}
|
||||
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
Ok(fss)
|
||||
}
|
96
mount/src/key.rs
Normal file
96
mount/src/key.rs
Normal file
@ -0,0 +1,96 @@
|
||||
use log::info;
|
||||
|
||||
fn check_for_key(key_name: &std::ffi::CStr) -> anyhow::Result<bool> {
|
||||
use crate::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) };
|
||||
if key_id > 0 {
|
||||
info!("Key has became avaiable");
|
||||
Ok(true)
|
||||
} else if errno::errno().0 != libc::ENOKEY {
|
||||
Err(crate::ErrnoError(errno::errno()).into())
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
fn wait_for_key(uuid: &uuid::Uuid) -> anyhow::Result<()> {
|
||||
let key_name = std::ffi::CString::new(format!("bcachefs:{}", uuid)).unwrap();
|
||||
loop {
|
||||
if check_for_key(&key_name)? {
|
||||
break Ok(());
|
||||
}
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||
}
|
||||
}
|
||||
|
||||
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 std::os::raw::c_char;
|
||||
|
||||
let key_name = std::ffi::CString::new(format!("bcachefs:{}", fs.uuid())).unwrap();
|
||||
if check_for_key(&key_name)? {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let bch_key_magic = BCH_KEY_MAGIC.as_bytes().read_u64::<LittleEndian>().unwrap();
|
||||
let crypt = fs.sb().sb().crypt().unwrap();
|
||||
let pass = rpassword::read_password_from_tty(Some("Enter passphrase: "))?;
|
||||
let pass = std::ffi::CString::new(pass.trim_end())?; // bind to keep the CString alive
|
||||
let mut output: bch_key = unsafe {
|
||||
bcachefs::derive_passphrase(
|
||||
crypt as *const _ as *mut _,
|
||||
pass.as_c_str().to_bytes_with_nul().as_ptr() as *const _,
|
||||
)
|
||||
};
|
||||
|
||||
let mut key = crypt.key().clone();
|
||||
let ret = unsafe {
|
||||
bch2_chacha_encrypt_key(
|
||||
&mut output as *mut _,
|
||||
fs.sb().sb().nonce(),
|
||||
&mut key as *mut _ as *mut _,
|
||||
std::mem::size_of::<bch_encrypted_key>() as u64,
|
||||
)
|
||||
};
|
||||
if ret != 0 {
|
||||
Err(anyhow!("chache 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(
|
||||
key_type,
|
||||
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,
|
||||
)
|
||||
};
|
||||
if ret == -1 {
|
||||
Err(anyhow!("failed to add key to keyring: {}", errno::errno()))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn prepare_key(fs: &FileSystem, password: crate::KeyLocation) -> anyhow::Result<()> {
|
||||
use crate::KeyLocation::*;
|
||||
use anyhow::anyhow;
|
||||
match password {
|
||||
Fail => Err(anyhow!("no key available")),
|
||||
Wait => Ok(wait_for_key(fs.uuid())?),
|
||||
Ask => ask_for_key(fs),
|
||||
}
|
||||
}
|
1
mount/src/keyutils_wrapper.h
Normal file
1
mount/src/keyutils_wrapper.h
Normal file
@ -0,0 +1 @@
|
||||
#include <keyutils.h>
|
190
mount/src/lib.rs
Normal file
190
mount/src/lib.rs
Normal file
@ -0,0 +1,190 @@
|
||||
use structopt::StructOpt;
|
||||
use anyhow::anyhow;
|
||||
|
||||
#[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 }
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ErrnoError(errno::Errno);
|
||||
impl std::fmt::Display for ErrnoError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
impl std::error::Error for ErrnoError {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum KeyLocation {
|
||||
Fail,
|
||||
Wait,
|
||||
Ask,
|
||||
}
|
||||
|
||||
impl std::str::FromStr for KeyLocation {
|
||||
type Err = anyhow::Error;
|
||||
fn from_str(s: &str) -> anyhow::Result<Self> {
|
||||
use anyhow::anyhow;
|
||||
match s {
|
||||
"fail" => Ok(Self::Fail),
|
||||
"wait" => Ok(Self::Wait),
|
||||
"ask" => Ok(Self::Ask),
|
||||
_ => Err(anyhow!("invalid password option"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(StructOpt, Debug)]
|
||||
/// Mount a bcachefs filesystem by its UUID.
|
||||
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,
|
||||
|
||||
/// External UUID of the bcachefs filesystem
|
||||
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>,
|
||||
|
||||
/// 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"));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
4
mount/src/libbcachefs_wrapper.h
Normal file
4
mount/src/libbcachefs_wrapper.h
Normal file
@ -0,0 +1,4 @@
|
||||
#include <libbcachefs/super-io.h>
|
||||
#include <libbcachefs/checksum.h>
|
||||
#include <libbcachefs/bcachefs_format.h>
|
||||
#include <crypto.h>
|
Loading…
Reference in New Issue
Block a user