summaryrefslogtreecommitdiffstats
path: root/tool
diff options
context:
space:
mode:
authorKai Michaelis <kai@sequoia-pgp.org>2018-12-11 12:21:35 +0100
committerKai Michaelis <kai@sequoia-pgp.org>2018-12-11 12:30:05 +0100
commitf4a0ed240644298654f0c9ee4c200b66642deb1c (patch)
treef1e3f936f22ce25c8db6cec9214b1052334aa131 /tool
parenteecbf652b083f09d5fb3912cb47ebff954424e5f (diff)
tool: ask before overwriting files, add --force
Diffstat (limited to 'tool')
-rw-r--r--tool/Cargo.toml1
-rw-r--r--tool/src/commands/mod.rs16
-rw-r--r--tool/src/sq.rs71
-rw-r--r--tool/src/sq_cli.rs4
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")