diff --git a/src/cdrw.rs b/src/cdrw.rs index 91af634..a452e1f 100644 --- a/src/cdrw.rs +++ b/src/cdrw.rs @@ -134,6 +134,28 @@ impl CdReader { eject(&self.device) } + pub fn is_cd_present(&self) -> Result { + let mut cmd = Command::new("blockdev"); + let cmd = cmd.arg("--getsize64").arg(&self.device); + + debug!("execting command: {:?}", cmd); + let output = cmd + .output() + .context("faild to execute blockdev, check PATH")?; + + if output.status.success() { + debug!("disk detected in drive, continuing"); + Ok(true) + } else { + debug!("no disk in drive"); + Ok(false) + } + } + + pub fn wait_for_media(&self) -> Result<()> { + wait_for_media(&self.device) + } + pub fn read(&self, name: &str) -> Result> { let tmpdir = tempdir()?; diff --git a/src/secret_reader.rs b/src/secret_reader.rs index 9601ce4..2417c73 100644 --- a/src/secret_reader.rs +++ b/src/secret_reader.rs @@ -5,7 +5,7 @@ use anyhow::{anyhow, Context, Result}; use clap::{Args, ValueEnum}; use glob::Paths; -use log::debug; +use log::{debug, info}; use std::{ env, io::{self, Read, Write}, @@ -111,29 +111,48 @@ impl CdrPasswordReader { impl PasswordReader for CdrPasswordReader { fn read(&mut self, _prompt: &str) -> Result> { - match self.cdr.eject() { - Ok(()) => (), - Err(e) => return Err(e), - } - - print!( - "Place authentication CD in the drive, close the drive, then press \n\ - the \"Enter\" key to continue: " - ); - match io::stdout().flush() { - Ok(()) => (), - Err(e) => return Err(e.into()), - } - util::wait_for_line()?; + let passwd = loop { + // if no cd is in the drive + if !self.cdr.is_cd_present()? { + get_media(&self.cdr)?; + } + // try to read + match self.cdr.read("password") { + Err(_) => { + // failed to read from the password file + info!("Failed to read password from CD"); + get_media(&self.cdr)?; + } + // return password wrapped in Zeroizing + Ok(p) => break Zeroizing::new(String::from_utf8(p)?), + } + }; + Ok(passwd) + } +} - // Passwords are utf8 and `String::from_utf8` explicitly does *not* - // copy the Vec. - let password = self.cdr.read("password")?; - let password = Zeroizing::new(String::from_utf8(password)?); - debug!("read password: {:?}", password.deref()); +fn get_media(cdr: &CdReader) -> Result<()> { + // eject the drive + match cdr.eject() { + Ok(()) => (), + Err(e) => return Err(e), + } - Ok(password) + // prompt user for the cd + print!( + "Place authentication CD in the drive, close the drive, then press \n\ + the \"Enter\" key to continue: " + ); + match io::stdout().flush() { + Ok(()) => (), + Err(e) => return Err(e.into()), } + + // wait for user to press enter + util::wait_for_line()?; + + // wait for media to "settle" + cdr.wait_for_media() } #[derive(Args, Clone, Debug, Default)]