summaryrefslogtreecommitdiffhomepage
path: root/mullvad-cli/src/cmds/patch.rs
diff options
context:
space:
mode:
Diffstat (limited to 'mullvad-cli/src/cmds/patch.rs')
-rw-r--r--mullvad-cli/src/cmds/patch.rs53
1 files changed, 49 insertions, 4 deletions
diff --git a/mullvad-cli/src/cmds/patch.rs b/mullvad-cli/src/cmds/patch.rs
index d5a79aaef9..c935c08aac 100644
--- a/mullvad-cli/src/cmds/patch.rs
+++ b/mullvad-cli/src/cmds/patch.rs
@@ -2,15 +2,15 @@ use anyhow::{anyhow, Context, Result};
use mullvad_management_interface::MullvadProxyClient;
use std::{
fs::File,
- io::{stdin, BufRead, BufReader},
+ io::{stdin, stdout, BufRead, BufReader, BufWriter, Write},
path::Path,
};
/// Maximum size of a settings patch. Bigger files/streams cause the read to fail.
const MAX_PATCH_BYTES: usize = 10 * 1024;
-/// If source is specified, read from the provided file and send it as a settings patch to the daemon.
-/// Otherwise, read the patch from standard input.
+/// If source is specified, read from the provided file and send it as a settings patch to the
+/// daemon. Otherwise, read the patch from standard input.
pub async fn import(source: String) -> Result<()> {
let json_blob = tokio::task::spawn_blocking(|| get_blob(source))
.await
@@ -26,10 +26,28 @@ pub async fn import(source: String) -> Result<()> {
Ok(())
}
+/// If source is specified, write a patch to the file. Otherwise, write the patch to standard
+/// output.
+pub async fn export(dest: String) -> Result<()> {
+ let mut rpc = MullvadProxyClient::new().await?;
+ let json_blob = rpc
+ .export_json_settings()
+ .await
+ .context("Error exporting patch")?;
+
+ tokio::task::spawn_blocking(|| put_blob(dest, json_blob))
+ .await
+ .unwrap()?;
+
+ Ok(())
+}
+
fn get_blob(source: String) -> Result<String> {
match source.as_str() {
"-" => read_settings_from_stdin().context("Failed to read from stdin"),
- _ => read_settings_from_file(source).context("Failed to read from path: {source}"),
+ _ => {
+ read_settings_from_file(&source).context(format!("Failed to read from path: {source}"))
+ }
}
}
@@ -99,3 +117,30 @@ fn read_settings_from_reader(mut reader: impl BufRead) -> Result<String> {
.context("settings must be utf8 encoded")?
.to_owned())
}
+
+fn put_blob(dest: String, blob: String) -> Result<()> {
+ match dest.as_str() {
+ "-" => write_settings_to_stdout(blob).context("Failed to write to stdout"),
+ _ => write_settings_to_file(&dest, blob).context(format!("Failed to write to path {dest}")),
+ }
+}
+
+/// Write patch to standard output
+fn write_settings_to_stdout(blob: String) -> Result<()> {
+ write_settings_using_writer(BufWriter::new(stdout()), blob)
+}
+
+/// Write patch to path
+fn write_settings_to_file(path: impl AsRef<Path>, blob: String) -> Result<()> {
+ write_settings_using_writer(
+ BufWriter::new(File::options().create(true).write(true).open(path)?),
+ blob,
+ )
+}
+
+fn write_settings_using_writer(mut writer: impl Write, blob: String) -> Result<()> {
+ writer
+ .write_all(blob.as_bytes())
+ .context("Failed to write blob to destination")?;
+ writer.write_all(b"\n").context("Failed to write newline")
+}