]> git.sesse.net Git - bcachefs-tools-debian/blob - rust-src/mount/src/lib.rs
rust: use rustfmt defaults
[bcachefs-tools-debian] / rust-src / mount / src / lib.rs
1 use anyhow::anyhow;
2 use clap::Parser;
3 use uuid::Uuid;
4
5 pub mod err {
6     pub enum GError {
7         Unknown {
8             message: std::borrow::Cow<'static, String>,
9         },
10     }
11     pub type GResult<T, E, OE> = ::core::result::Result<::core::result::Result<T, E>, OE>;
12     pub type Result<T, E> = GResult<T, E, GError>;
13 }
14
15 #[macro_export]
16 macro_rules! c_str {
17     ($lit:expr) => {
18         unsafe {
19             std::ffi::CStr::from_ptr(concat!($lit, "\0").as_ptr() as *const std::os::raw::c_char)
20                 .to_bytes_with_nul()
21                 .as_ptr() as *const std::os::raw::c_char
22         }
23     };
24 }
25
26 #[derive(Debug)]
27 struct ErrnoError(errno::Errno);
28 impl std::fmt::Display for ErrnoError {
29     fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
30         self.0.fmt(f)
31     }
32 }
33 impl std::error::Error for ErrnoError {}
34
35 #[derive(Clone, Debug)]
36 pub enum KeyLocation {
37     Fail,
38     Wait,
39     Ask,
40 }
41
42 #[derive(Clone, Debug)]
43 pub struct KeyLoc(pub Option<KeyLocation>);
44 impl std::ops::Deref for KeyLoc {
45     type Target = Option<KeyLocation>;
46     fn deref(&self) -> &Self::Target {
47         &self.0
48     }
49 }
50 impl std::str::FromStr for KeyLoc {
51     type Err = anyhow::Error;
52     fn from_str(s: &str) -> anyhow::Result<Self> {
53         // use anyhow::anyhow;
54         match s {
55             "" => Ok(KeyLoc(None)),
56             "fail" => Ok(KeyLoc(Some(KeyLocation::Fail))),
57             "wait" => Ok(KeyLoc(Some(KeyLocation::Wait))),
58             "ask" => Ok(KeyLoc(Some(KeyLocation::Ask))),
59             _ => Err(anyhow!("invalid password option")),
60         }
61     }
62 }
63
64 fn parse_fstab_uuid(uuid_raw: &str) -> Result<Uuid, uuid::Error> {
65     let mut uuid = String::from(uuid_raw);
66     if uuid.starts_with("UUID=") {
67         uuid = uuid.replacen("UUID=", "", 1);
68     }
69     return Uuid::parse_str(&uuid);
70 }
71
72 /// Mount a bcachefs filesystem by its UUID.
73 #[derive(Parser, Debug)]
74 #[command(author, version, about, long_about = None)]
75 pub struct Cli {
76     /// Where the password would be loaded from.
77     ///
78     /// Possible values are:
79     /// "fail" - don't ask for password, fail if filesystem is encrypted;
80     /// "wait" - wait for password to become available before mounting;
81     /// "ask" -  prompt the user for password;
82     #[arg(short, long, default_value = "", verbatim_doc_comment)]
83     pub key_location: KeyLoc,
84
85     /// External UUID of the bcachefs filesystem
86     ///
87     /// Accepts the UUID as is or as fstab style UUID=<UUID>
88     #[arg(value_parser=parse_fstab_uuid)]
89     pub uuid: uuid::Uuid,
90
91     /// Where the filesystem should be mounted. If not set, then the filesystem
92     /// won't actually be mounted. But all steps preceeding mounting the
93     /// filesystem (e.g. asking for passphrase) will still be performed.
94     pub mountpoint: Option<std::path::PathBuf>,
95
96     /// Mount options
97     #[arg(short, default_value = "")]
98     pub options: String,
99 }
100
101 pub mod filesystem;
102 pub mod key;
103
104 // pub fn mnt_in_use()
105
106 #[test]
107 fn verify_cli() {
108     use clap::CommandFactory;
109     Cli::command().debug_assert()
110 }