]> git.sesse.net Git - bcachefs-tools-debian/blob - rust-src/mount/src/lib.rs
rust: support fstab style mount
[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 }