1
0
forked from brl/citadel-tools
citadel-tools/citadel-install/src/cli.rs

151 lines
4.0 KiB
Rust
Raw Normal View History

2018-12-31 23:27:17 +00:00
use std::io::{self,Write};
use std::path::Path;
use Result;
use util::Disk;
use rpassword;
use installer::Installer;
pub fn run_cli_install() -> Result<bool> {
let disk = match choose_disk()? {
Some(disk) => disk,
None => return Ok(false),
};
display_disk(&disk);
let passphrase = match read_passphrase()? {
Some(passphrase) => passphrase,
None => return Ok(false),
};
if !confirm_install(&disk)? {
return Ok(false);
}
run_install(disk, passphrase)?;
Ok(true)
}
pub fn run_cli_install_with<P: AsRef<Path>>(target: P) -> Result<bool> {
let disk = find_disk_by_path(target.as_ref())?;
display_disk(&disk);
let passphrase = match read_passphrase()? {
Some(passphrase) => passphrase,
None => return Ok(false),
};
if !confirm_install(&disk)? {
return Ok(false);
}
run_install(disk, passphrase)?;
Ok(true)
}
fn run_install(disk: Disk, passphrase: String) -> Result<()> {
let mut install = Installer::new();
install.set_target(disk.path().to_str().unwrap());
install.set_passphrase(&passphrase);
install.set_install_syslinux(true);
install.verify()?;
install.run()
}
fn display_disk(disk: &Disk) {
println!();
println!(" Device: {}", disk.path().display());
println!(" Size: {}", disk.size_str());
println!(" Model: {}", disk.model());
println!();
}
fn find_disk_by_path(path: &Path) -> Result<Disk> {
if !path.exists() {
bail!("Target disk path {} does not exist", path.display());
}
for disk in Disk::probe_all()? {
if disk.path() == path {
return Ok(disk.clone());
}
}
Err(format_err!("Installation target {} is not a valid disk", path.display()))
}
fn choose_disk() -> Result<Option<Disk>> {
let disks = Disk::probe_all()?;
if disks.is_empty() {
bail!("No disks found.");
}
loop {
prompt_choose_disk(&disks)?;
let line = read_line()?;
if line == "q" || line == "Q" {
return Ok(None);
}
if let Ok(n) = line.parse::<usize>() {
if n > 0 && n <= disks.len() {
return Ok(Some(disks[n-1].clone()));
}
}
}
}
fn prompt_choose_disk(disks: &[Disk]) -> Result<()> {
println!("Available disks:\n");
for idx in 0..disks.len() {
println!(" [{}]: {} Size: {} Model: {}", idx + 1, disks[idx].path().display(), disks[idx].size_str(), disks[idx].model());
}
print!("\nChoose a disk to install to (q to quit): ");
io::stdout().flush()?;
Ok(())
}
fn read_line() -> Result<String> {
let mut input = String::new();
io::stdin().read_line(&mut input)?;
if input.ends_with('\n') {
input.pop();
}
Ok(input)
}
fn read_passphrase() -> Result<Option<String>> {
loop {
println!("Enter a disk encryption passphrase (or 'q' to quit)");
println!();
let passphrase = rpassword::read_password_from_tty(Some(" Passphrase : "))?;
if passphrase.is_empty() {
println!("Passphrase cannot be empty");
continue;
}
if passphrase == "q" || passphrase == "Q" {
return Ok(None);
}
let confirm = rpassword::read_password_from_tty(Some(" Confirm : "))?;
if confirm == "q" || confirm == "Q" {
return Ok(None);
}
println!();
if passphrase == confirm {
return Ok(Some(passphrase));
}
println!("Passphrases do not match");
println!();
}
}
fn confirm_install(disk: &Disk) -> Result<bool> {
println!("Are you sure you want to completely erase this this device?");
println!();
println!(" Device: {}", disk.path().display());
println!(" Size: {}", disk.size_str());
println!(" Model: {}", disk.model());
println!();
print!("Type YES (uppercase) to continue with install: ");
io::stdout().flush()?;
let answer = read_line()?;
Ok(answer == "YES")
}