diff options
Diffstat (limited to 'mullvad-cli/src/cmds/patch.rs')
| -rw-r--r-- | mullvad-cli/src/cmds/patch.rs | 53 |
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") +} |
