diff --git a/src/nyan_system.rs b/src/nyan_system.rs index 03157fd..fff294c 100644 --- a/src/nyan_system.rs +++ b/src/nyan_system.rs @@ -135,6 +135,52 @@ pub fn list_gpt_labeled_devs() -> Result, ExecCommandError> { Ok(res) } +/// bcachefs unlock --file=/tmp/bzzpsspass.txt /dev/loop0somedev +/// Ok so. It is stupid, because bcacheutils far from ideal. +/// But if we provide wrong password from file or stdin this stuff plays stupid and asks for right password. +/// Sooo.. In order to know if unlock was sucessfull we need to check if program exited with Ok status, +/// or it shits to STDERR still waiting for stdin +/// Returns true if unlock successful, and false otherwise +pub fn bcachefs_unlock(pass: String, dev: &str) -> Result { + use std::io::Read; + use std::io::Write; + use std::process::Stdio; + let mut child = Command::new("bcachefs") + .arg("unlock") + .arg(dev) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn()?; + + let mut c_stderr = child.stderr.take().ok_or_else(||{"Unable to get child process STDERR".to_string()})?; + + // Write password to STDIN in a limited scope + { + let mut c_stdin = child.stdin.take().ok_or_else(||{"Unable to get child process STDIN".to_string()})?; + // neccessery to use thread or we may be deadlocking + c_stdin.write_all(pass.as_bytes())?; + let bytes_written = c_stdin.write(b"\n")?; + println!("bytes_written: {}", bytes_written); + // stdin is dropped here automatically when the block ends + } + + let mut buffer = [0u8; 10]; + // This blocks. + // if unlok fails it reads 10 bytes (piece of err message) + // if sucess it reads 0 bytes and exit + let read_b = c_stderr.read(&mut buffer)?; + if read_b > 0 { + println!("STDERR error not empty, password incorrect! Try to kill a child."); + child.kill()?; + } + + // Safe to wait now; child will see EOF + let exit_status = child.wait()?; + // if exit status is SUCCESS - unloking is successful + Ok(exit_status.success()) +} + /// Cheking if device is encripted pub fn bzzpss_dev_encrypted(dev_name: &str) -> Result { match exec_command("bcachefs", &vec!["unlock", "--check"]) {