key: Try systemd-ask-password when stdin is /dev/null

When mount.bcachefs is started with stdin set to /dev/null (such as when
it is started by systemd during boot), try to use systemd-ask-password
to ask for the passphrase.
This commit is contained in:
beviu 2025-09-10 17:42:41 +02:00
parent ad41f28c4c
commit e5f4be87a8
No known key found for this signature in database
GPG Key ID: C6AAE70FD32E0112
2 changed files with 35 additions and 6 deletions

View File

@ -30,7 +30,7 @@ bch_bindgen = { path = "bch_bindgen" }
strum = { version = "0.26", features = ["derive"] }
strum_macros = "0.26"
zeroize = { version = "1", features = ["std", "zeroize_derive"] }
rustix = { version = "0.38.34", features = ["termios"] }
rustix = { version = "0.38.34", features = ["fs", "termios"] }
owo-colors = "4"
[dependencies.env_logger]

View File

@ -1,8 +1,9 @@
use std::{
ffi::{c_long, CStr, CString},
fs,
io::{stdin, IsTerminal},
io::{self, stdin, IsTerminal},
mem,
os::fd::{AsFd, BorrowedFd},
path::Path,
process::{Command, Stdio},
ptr, thread,
@ -143,10 +144,10 @@ impl Passphrase {
}
pub fn new(uuid: &Uuid) -> Result<Self> {
if stdin().is_terminal() {
Self::new_from_prompt(uuid)
} else {
Self::new_from_stdin()
match get_stdin_type() {
StdinType::Terminal => Self::new_from_prompt(uuid),
StdinType::DevNull => Self::new_from_askpassword(uuid).unwrap_or_else(|err| Err(err)),
StdinType::Other => Self::new_from_stdin(),
}
}
@ -253,3 +254,31 @@ impl Passphrase {
Ok((passphrase_key, sb_key))
}
}
fn is_dev_null(fd: BorrowedFd) -> io::Result<bool> {
let stat = rustix::fs::fstat(fd)?;
let file_type = rustix::fs::FileType::from_raw_mode(stat.st_mode);
if file_type != rustix::fs::FileType::CharacterDevice {
return Ok(false);
}
let major = rustix::fs::major(stat.st_rdev);
let minor = rustix::fs::minor(stat.st_rdev);
Ok(major == 1 && minor == 3)
}
enum StdinType {
Terminal,
DevNull,
Other,
}
fn get_stdin_type() -> StdinType {
let stdin = stdin();
if stdin.is_terminal() {
StdinType::Terminal
} else if is_dev_null(stdin.as_fd()).unwrap_or(false) {
StdinType::DevNull
} else {
StdinType::Other
}
}