1 use structopt::StructOpt;
7 unsafe { std::ffi::CStr::from_ptr(concat!($lit, "\0").as_ptr() as *const std::os::raw::c_char)
9 .as_ptr() as *const std::os::raw::c_char }
14 struct ErrnoError(errno::Errno);
15 impl std::fmt::Display for ErrnoError {
16 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
20 impl std::error::Error for ErrnoError {}
23 pub(crate) enum KeyLocation {
29 impl std::str::FromStr for KeyLocation {
30 type Err = anyhow::Error;
31 fn from_str(s: &str) -> anyhow::Result<Self> {
34 "fail" => Ok(Self::Fail),
35 "wait" => Ok(Self::Wait),
36 "ask" => Ok(Self::Ask),
37 _ => Err(anyhow!("invalid password option"))
42 #[derive(StructOpt, Debug)]
43 /// Mount a bcachefs filesystem by its UUID.
45 /// Where the password would be loaded from.
47 /// Possible values are:
48 /// "fail" - don't ask for password, fail if filesystem is encrypted;
49 /// "wait" - wait for password to become available before mounting;
50 /// "ask" - prompt the user for password;
51 #[structopt(short, long, default_value = "fail")]
52 key_location: KeyLocation,
54 /// External UUID of the bcachefs filesystem
57 /// Where the filesystem should be mounted. If not set, then the filesystem
58 /// won't actually be mounted. But all steps preceeding mounting the
59 /// filesystem (e.g. asking for passphrase) will still be performed.
60 mountpoint: Option<std::path::PathBuf>,
63 #[structopt(short, default_value = "")]
70 #![allow(non_upper_case_globals)]
71 #![allow(non_camel_case_types)]
72 #![allow(non_snake_case)]
75 include!(concat!(env!("OUT_DIR"), "/keyutils.rs"));
79 #![allow(non_upper_case_globals)]
80 #![allow(non_camel_case_types)]
81 #![allow(non_snake_case)]
84 include!(concat!(env!("OUT_DIR"), "/bcachefs.rs"));
86 use bitfield::bitfield;
88 pub struct bch_scrypt_flags(u64);
94 pub struct bch_crypt_flags(u64);
97 use memoffset::offset_of;
98 impl bch_sb_field_crypt {
99 pub fn scrypt_flags(&self) -> Option<bch_scrypt_flags> {
100 let t = bch_crypt_flags(self.flags);
101 if t.TYPE() != bch_kdf_types::BCH_KDF_SCRYPT as u64 {
104 Some(bch_scrypt_flags(self.kdf_flags))
107 pub fn key(&self) -> &bch_encrypted_key {
112 pub fn crypt(&self) -> Option<&bch_sb_field_crypt> {
114 let ptr = bch2_sb_field_get(
115 self as *const _ as *mut _,
116 bch_sb_field_type::BCH_SB_FIELD_crypt,
121 let offset = offset_of!(bch_sb_field_crypt, field);
122 Some(&*((ptr.sub(offset)) as *const _))
126 pub fn uuid(&self) -> uuid::Uuid {
127 uuid::Uuid::from_bytes(self.user_uuid.b)
130 /// Get the nonce used to encrypt the superblock
131 pub fn nonce(&self) -> nonce {
132 use byteorder::{ReadBytesExt, LittleEndian};
133 let mut internal_uuid = &self.uuid.b[..];
134 let dword1 = internal_uuid.read_u32::<LittleEndian>().unwrap();
135 let dword2 = internal_uuid.read_u32::<LittleEndian>().unwrap();
136 nonce { d: [0, 0, dword1, dword2] }
140 pub fn sb(&self) -> &bch_sb {
146 fn main_inner() -> anyhow::Result<()> {
147 use itertools::Itertools;
148 use log::{info, trace};
151 let opt = Options::from_args();
154 let fss = filesystem::probe_filesystems()?;
155 info!("Found {} bcachefs filesystems: ", fss.len());
156 for fs in fss.values() {
165 fs.devices().iter().map(|d| d.display()).join(" ")
169 if let Some(fs) = fss.get(&opt.uuid) {
171 info!("Making sure key is loaded for this filesystem");
172 key::prepare_key(&fs, opt.key_location)?;
175 if let Some(p) = opt.mountpoint {
176 fs.mount(&p, &opt.options)
181 Err(anyhow!("Filesystem {} is not found", opt.uuid))
186 pub extern "C" fn main() {
187 if let Err(e) = main_inner() {
188 println!("Error: {:?}", e);