diff options
author | Kai Michaelis <kai@sequoia-pgp.org> | 2018-12-11 12:21:35 +0100 |
---|---|---|
committer | Kai Michaelis <kai@sequoia-pgp.org> | 2018-12-11 12:30:05 +0100 |
commit | f4a0ed240644298654f0c9ee4c200b66642deb1c (patch) | |
tree | f1e3f936f22ce25c8db6cec9214b1052334aa131 /tool | |
parent | eecbf652b083f09d5fb3912cb47ebff954424e5f (diff) |
tool: ask before overwriting files, add --force
Diffstat (limited to 'tool')
-rw-r--r-- | tool/Cargo.toml | 1 | ||||
-rw-r--r-- | tool/src/commands/mod.rs | 16 | ||||
-rw-r--r-- | tool/src/sq.rs | 71 | ||||
-rw-r--r-- | tool/src/sq_cli.rs | 4 |
4 files changed, 55 insertions, 37 deletions
diff --git a/tool/Cargo.toml b/tool/Cargo.toml index c54433e9..db23b307 100644 --- a/tool/Cargo.toml +++ b/tool/Cargo.toml @@ -31,6 +31,7 @@ prettytable-rs = "0.8.0" rpassword = "2.0.0" tempfile = "3.0.4" time = "0.1.38" +promptly = "0.1.5" [build-dependencies] clap = "2.27.1" diff --git a/tool/src/commands/mod.rs b/tool/src/commands/mod.rs index fa265747..eb95f755 100644 --- a/tool/src/commands/mod.rs +++ b/tool/src/commands/mod.rs @@ -93,19 +93,20 @@ pub fn encrypt(store: &mut store::Store, pub fn sign(input: &mut io::Read, output_path: Option<&str>, secrets: Vec<openpgp::TPK>, detached: bool, binary: bool, - append: bool, notarize: bool) + append: bool, notarize: bool, force: bool) -> Result<()> { match (detached, append|notarize) { (_, false) | (true, true) => - sign_data(input, output_path, secrets, detached, binary, append), + sign_data(input, output_path, secrets, detached, binary, append, + force), (false, true) => - sign_message(input, output_path, secrets, binary, notarize), + sign_message(input, output_path, secrets, binary, notarize, force), } } fn sign_data(input: &mut io::Read, output_path: Option<&str>, secrets: Vec<openpgp::TPK>, detached: bool, binary: bool, - append: bool) + append: bool, force: bool) -> Result<()> { let (mut output, prepend_sigs, tmp_path): (Box<io::Write>, Vec<Signature>, Option<PathBuf>) = @@ -137,7 +138,7 @@ fn sign_data(input: &mut io::Read, output_path: Option<&str>, let tmp_path = tmp_file.path().into(); (Box::new(tmp_file), sigs, Some(tmp_path)) } else { - (create_or_stdout(output_path)?, Vec::new(), None) + (create_or_stdout(output_path, force)?, Vec::new(), None) }; let mut output = if ! binary { @@ -195,9 +196,10 @@ fn sign_data(input: &mut io::Read, output_path: Option<&str>, } fn sign_message(input: &mut io::Read, output_path: Option<&str>, - secrets: Vec<openpgp::TPK>, binary: bool, notarize: bool) + secrets: Vec<openpgp::TPK>, binary: bool, notarize: bool, + force: bool) -> Result<()> { - let mut output = create_or_stdout(output_path)?; + let mut output = create_or_stdout(output_path, force)?; let output = if ! binary { Box::new(armor::Writer::new(&mut output, armor::Kind::Message, diff --git a/tool/src/sq.rs b/tool/src/sq.rs index 0720b5a1..2e429179 100644 --- a/tool/src/sq.rs +++ b/tool/src/sq.rs @@ -7,12 +7,13 @@ extern crate prettytable; extern crate rpassword; extern crate tempfile; extern crate time; +extern crate promptly; use failure::ResultExt; use prettytable::{Table, Cell, Row}; use std::fs::{File, OpenOptions}; use std::io; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::exit; extern crate sequoia_openpgp as openpgp; @@ -37,12 +38,30 @@ fn open_or_stdin(f: Option<&str>) -> Result<Box<io::Read>, failure::Error> { } } -fn create_or_stdout(f: Option<&str>) -> Result<Box<io::Write>, failure::Error> { +fn create_or_stdout(f: Option<&str>, force: bool) + -> Result<Box<io::Write>, failure::Error> { + use promptly::prompt_default; + match f { - Some(f) => Ok(Box::new(OpenOptions::new().write(true).create_new(true) - .open(f) - .context("Failed to create output file")?)), None => Ok(Box::new(io::stdout())), + Some(p) if p == "-" => Ok(Box::new(io::stdout())), + Some(f) => { + let p = Path::new(f); + let path_ok = force || !p.exists() || + prompt_default(format!("{} exists already. Overwrite?", f), false); + + if path_ok { + Ok(Box::new(OpenOptions::new() + .write(true) + .truncate(true) + .create(true) + .open(f) + .context("Failed to create output file")?)) + } else { + eprintln!("Cannot continue"); + exit(1); + } + } } } @@ -83,6 +102,7 @@ fn real_main() -> Result<(), failure::Error> { exit(1); }, }; + let force = matches.is_present("force"); let domain_name = matches.value_of("domain").unwrap_or("org.sequoia-pgp.sq"); let mut builder = Context::configure(domain_name) @@ -96,7 +116,7 @@ fn real_main() -> Result<(), failure::Error> { match matches.subcommand() { ("decrypt", Some(m)) => { let mut input = open_or_stdin(m.value_of("input"))?; - let mut output = create_or_stdout(m.value_of("output"))?; + let mut output = create_or_stdout(m.value_of("output"), force)?; let signatures: usize = m.value_of("signatures").unwrap_or("0").parse()?; let tpks = m.values_of("public-key-file") @@ -114,7 +134,7 @@ fn real_main() -> Result<(), failure::Error> { }, ("encrypt", Some(m)) => { let mut input = open_or_stdin(m.value_of("input"))?; - let mut output = create_or_stdout(m.value_of("output"))?; + let mut output = create_or_stdout(m.value_of("output"), force)?; let mut output = if ! m.is_present("binary") { Box::new(armor::Writer::new(&mut output, armor::Kind::Message, @@ -148,11 +168,11 @@ fn real_main() -> Result<(), failure::Error> { .map(load_tpks) .unwrap_or(Ok(vec![]))?; commands::sign(&mut input, output, secrets, detached, binary, - append, notarize)?; + append, notarize, force)?; }, ("verify", Some(m)) => { let mut input = open_or_stdin(m.value_of("input"))?; - let mut output = create_or_stdout(m.value_of("output"))?; + let mut output = create_or_stdout(m.value_of("output"), force)?; let mut detached = if let Some(f) = m.value_of("detached") { Some(File::open(f)?) } else { @@ -172,14 +192,14 @@ fn real_main() -> Result<(), failure::Error> { ("enarmor", Some(m)) => { let mut input = open_or_stdin(m.value_of("input"))?; - let mut output = create_or_stdout(m.value_of("output"))?; + let mut output = create_or_stdout(m.value_of("output"), force)?; let mut filter = armor::Writer::new(&mut output, armor::Kind::File, &[])?; io::copy(&mut input, &mut filter)?; }, ("dearmor", Some(m)) => { let mut input = open_or_stdin(m.value_of("input"))?; - let mut output = create_or_stdout(m.value_of("output"))?; + let mut output = create_or_stdout(m.value_of("output"), force)?; let mut filter = armor::Reader::new(&mut input, None); io::copy(&mut filter, &mut output)?; }, @@ -187,7 +207,7 @@ fn real_main() -> Result<(), failure::Error> { match m.subcommand() { ("decode", Some(m)) => { let mut input = open_or_stdin(m.value_of("input"))?; - let mut output = create_or_stdout(m.value_of("output"))?; + let mut output = create_or_stdout(m.value_of("output"), force)?; let ac = autocrypt::AutocryptHeaders::from_reader(input)?; for h in &ac.headers { if let Some(ref tpk) = h.key { @@ -206,7 +226,7 @@ fn real_main() -> Result<(), failure::Error> { ("dump", Some(m)) => { let mut input = open_or_stdin(m.value_of("input"))?; - let mut output = create_or_stdout(m.value_of("output"))?; + let mut output = create_or_stdout(m.value_of("output"), force)?; commands::dump(&mut input, &mut output, m.is_present("mpis"), m.is_present("hex"))?; }, @@ -247,7 +267,7 @@ fn real_main() -> Result<(), failure::Error> { } let id = id.unwrap(); - let mut output = create_or_stdout(m.value_of("output"))?; + let mut output = create_or_stdout(m.value_of("output"), force)?; let mut output = if ! m.is_present("binary") { Box::new(armor::Writer::new(&mut output, armor::Kind::PublicKey, @@ -298,7 +318,7 @@ fn real_main() -> Result<(), failure::Error> { ("export", Some(m)) => { let tpk = store.lookup(m.value_of("label").unwrap())?.tpk()?; - let mut output = create_or_stdout(m.value_of("output"))?; + let mut output = create_or_stdout(m.value_of("output"), force)?; let mut output = if ! m.is_present("binary") { Box::new(armor::Writer::new(&mut output, armor::Kind::PublicKey, @@ -401,8 +421,6 @@ fn real_main() -> Result<(), failure::Error> { use openpgp::packet::KeyFlags; use openpgp::armor::{Writer, Kind}; use openpgp::serialize::Serialize; - use std::io; - use std::fs::File; let mut builder = TPKBuilder::default(); @@ -491,25 +509,18 @@ fn real_main() -> Result<(), failure::Error> { exit(1); } }; - let mut stdout = io::stdout(); // write out key - if key_path == "-" { - let mut w = Writer::new(&mut stdout, Kind::SecretKey, &[])?; - tsk.serialize(&mut w)?; - } else { - let mut fd = File::create(key_path)?; - let mut w = Writer::new(&mut fd, Kind::SecretKey, &[])?; + { + let w = create_or_stdout(Some(&key_path), force)?; + let mut w = Writer::new(w, Kind::SecretKey, &[])?; tsk.serialize(&mut w)?; } // write out rev cert - if rev_path == "-" { - let mut w = Writer::new(&mut stdout, Kind::Signature, &[])?; - rev.serialize(&mut w)?; - } else { - let mut fd = File::create(rev_path)?; - let mut w = Writer::new(&mut fd, Kind::Signature, &[])?; + { + let w = create_or_stdout(Some(&rev_path), force)?; + let mut w = Writer::new(w, Kind::Signature, &[])?; rev.serialize(&mut w)?; } } else { diff --git a/tool/src/sq_cli.rs b/tool/src/sq_cli.rs index 6bcf351c..78a9b484 100644 --- a/tool/src/sq_cli.rs +++ b/tool/src/sq_cli.rs @@ -26,6 +26,10 @@ pub fn build() -> App<'static, 'static> { .long("policy") .short("p") .help("Sets the network policy to use")) + .arg(Arg::with_name("force") + .long("force") + .short("f") + .help("Overwrite files without asking")) .subcommand(SubCommand::with_name("decrypt") .display_order(10) .about("Decrypts an OpenPGP message") |