diff --git a/pbs-client/src/backup_reader.rs b/pbs-client/src/backup_reader.rs index 0f39a395e..6a53a2559 100644 --- a/pbs-client/src/backup_reader.rs +++ b/pbs-client/src/backup_reader.rs @@ -1,23 +1,23 @@ use anyhow::{format_err, Error}; -use std::io::{Write, Seek, SeekFrom}; use std::fs::File; -use std::sync::Arc; +use std::io::{Seek, SeekFrom, Write}; use std::os::unix::fs::OpenOptionsExt; +use std::sync::Arc; use futures::future::AbortHandle; use serde_json::{json, Value}; -use pbs_tools::crypt_config::CryptConfig; -use pbs_tools::sha::sha256; -use pbs_datastore::{PROXMOX_BACKUP_READER_PROTOCOL_ID_V1, BackupManifest}; use pbs_datastore::data_blob::DataBlob; use pbs_datastore::data_blob_reader::DataBlobReader; use pbs_datastore::dynamic_index::DynamicIndexReader; use pbs_datastore::fixed_index::FixedIndexReader; use pbs_datastore::index::IndexFile; use pbs_datastore::manifest::MANIFEST_BLOB_NAME; +use pbs_datastore::{BackupManifest, PROXMOX_BACKUP_READER_PROTOCOL_ID_V1}; +use pbs_tools::crypt_config::CryptConfig; +use pbs_tools::sha::sha256; -use super::{HttpClient, H2Client}; +use super::{H2Client, HttpClient}; /// Backup Reader pub struct BackupReader { @@ -27,16 +27,18 @@ pub struct BackupReader { } impl Drop for BackupReader { - fn drop(&mut self) { self.abort.abort(); } } impl BackupReader { - fn new(h2: H2Client, abort: AbortHandle, crypt_config: Option>) -> Arc { - Arc::new(Self { h2, abort, crypt_config}) + Arc::new(Self { + h2, + abort, + crypt_config, + }) } /// Create a new instance by upgrading the connection at '/api2/json/reader' @@ -49,7 +51,6 @@ impl BackupReader { backup_time: i64, debug: bool, ) -> Result, Error> { - let param = json!({ "backup-type": backup_type, "backup-id": backup_id, @@ -57,46 +58,39 @@ impl BackupReader { "store": datastore, "debug": debug, }); - let req = HttpClient::request_builder(client.server(), client.port(), "GET", "/api2/json/reader", Some(param)).unwrap(); + let req = HttpClient::request_builder( + client.server(), + client.port(), + "GET", + "/api2/json/reader", + Some(param), + ) + .unwrap(); - let (h2, abort) = client.start_h2_connection(req, String::from(PROXMOX_BACKUP_READER_PROTOCOL_ID_V1!())).await?; + let (h2, abort) = client + .start_h2_connection(req, String::from(PROXMOX_BACKUP_READER_PROTOCOL_ID_V1!())) + .await?; Ok(BackupReader::new(h2, abort, crypt_config)) } /// Execute a GET request - pub async fn get( - &self, - path: &str, - param: Option, - ) -> Result { + pub async fn get(&self, path: &str, param: Option) -> Result { self.h2.get(path, param).await } /// Execute a PUT request - pub async fn put( - &self, - path: &str, - param: Option, - ) -> Result { + pub async fn put(&self, path: &str, param: Option) -> Result { self.h2.put(path, param).await } /// Execute a POST request - pub async fn post( - &self, - path: &str, - param: Option, - ) -> Result { + pub async fn post(&self, path: &str, param: Option) -> Result { self.h2.post(path, param).await } /// Execute a GET request and send output to a writer - pub async fn download( - &self, - file_name: &str, - output: W, - ) -> Result<(), Error> { + pub async fn download(&self, file_name: &str, output: W) -> Result<(), Error> { let path = "download"; let param = json!({ "file-name": file_name }); self.h2.download(path, Some(param), output).await @@ -105,10 +99,7 @@ impl BackupReader { /// Execute a special GET request and send output to a writer /// /// This writes random data, and is only useful to test download speed. - pub async fn speedtest( - &self, - output: W, - ) -> Result<(), Error> { + pub async fn speedtest(&self, output: W) -> Result<(), Error> { self.h2.download("speedtest", None, output).await } @@ -131,14 +122,14 @@ impl BackupReader { /// /// The manifest signature is verified if we have a crypt_config. pub async fn download_manifest(&self) -> Result<(BackupManifest, Vec), Error> { - let mut raw_data = Vec::with_capacity(64 * 1024); self.download(MANIFEST_BLOB_NAME, &mut raw_data).await?; let blob = DataBlob::load_from_reader(&mut &raw_data[..])?; // no expected digest available let data = blob.decode(None, None)?; - let manifest = BackupManifest::from_data(&data[..], self.crypt_config.as_ref().map(Arc::as_ref))?; + let manifest = + BackupManifest::from_data(&data[..], self.crypt_config.as_ref().map(Arc::as_ref))?; Ok((manifest, data)) } @@ -152,7 +143,6 @@ impl BackupReader { manifest: &BackupManifest, name: &str, ) -> Result, Error> { - let mut tmpfile = std::fs::OpenOptions::new() .write(true) .read(true) @@ -179,7 +169,6 @@ impl BackupReader { manifest: &BackupManifest, name: &str, ) -> Result { - let mut tmpfile = std::fs::OpenOptions::new() .write(true) .read(true) @@ -207,7 +196,6 @@ impl BackupReader { manifest: &BackupManifest, name: &str, ) -> Result { - let mut tmpfile = std::fs::OpenOptions::new() .write(true) .read(true) diff --git a/pbs-client/src/backup_repo.rs b/pbs-client/src/backup_repo.rs index 2fae92cef..02736e39e 100644 --- a/pbs-client/src/backup_repo.rs +++ b/pbs-client/src/backup_repo.rs @@ -3,7 +3,7 @@ use std::fmt; use anyhow::{format_err, Error}; -use pbs_api_types::{BACKUP_REPO_URL_REGEX, IP_V6_REGEX, Authid, Userid}; +use pbs_api_types::{Authid, Userid, BACKUP_REPO_URL_REGEX, IP_V6_REGEX}; /// Reference remote backup locations /// @@ -21,15 +21,22 @@ pub struct BackupRepository { } impl BackupRepository { - - pub fn new(auth_id: Option, host: Option, port: Option, store: String) -> Self { + pub fn new( + auth_id: Option, + host: Option, + port: Option, + store: String, + ) -> Self { let host = match host { - Some(host) if (IP_V6_REGEX.regex_obj)().is_match(&host) => { - Some(format!("[{}]", host)) - }, + Some(host) if (IP_V6_REGEX.regex_obj)().is_match(&host) => Some(format!("[{}]", host)), other => other, }; - Self { auth_id, host, port, store } + Self { + auth_id, + host, + port, + store, + } } pub fn auth_id(&self) -> &Authid { @@ -70,7 +77,14 @@ impl BackupRepository { impl fmt::Display for BackupRepository { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match (&self.auth_id, &self.host, self.port) { - (Some(auth_id), _, _) => write!(f, "{}@{}:{}:{}", auth_id, self.host(), self.port(), self.store), + (Some(auth_id), _, _) => write!( + f, + "{}@{}:{}:{}", + auth_id, + self.host(), + self.port(), + self.store + ), (None, Some(host), None) => write!(f, "{}:{}", host, self.store), (None, _, Some(port)) => write!(f, "{}:{}:{}", self.host(), port, self.store), (None, None, None) => write!(f, "{}", self.store), @@ -87,12 +101,15 @@ impl std::str::FromStr for BackupRepository { /// `host` parts are optional, where `host` defaults to the local /// host, and `user` defaults to `root@pam`. fn from_str(url: &str) -> Result { - - let cap = (BACKUP_REPO_URL_REGEX.regex_obj)().captures(url) + let cap = (BACKUP_REPO_URL_REGEX.regex_obj)() + .captures(url) .ok_or_else(|| format_err!("unable to parse repository url '{}'", url))?; Ok(Self { - auth_id: cap.get(1).map(|m| Authid::try_from(m.as_str().to_owned())).transpose()?, + auth_id: cap + .get(1) + .map(|m| Authid::try_from(m.as_str().to_owned())) + .transpose()?, host: cap.get(2).map(|m| m.as_str().to_owned()), port: cap.get(3).map(|m| m.as_str().parse::()).transpose()?, store: cap[4].to_owned(), diff --git a/pbs-client/src/backup_specification.rs b/pbs-client/src/backup_specification.rs index ea32b97ce..619a3a9da 100644 --- a/pbs-client/src/backup_specification.rs +++ b/pbs-client/src/backup_specification.rs @@ -6,25 +6,29 @@ const_regex! { BACKUPSPEC_REGEX = r"^([a-zA-Z0-9_-]+\.(pxar|img|conf|log)):(.+)$"; } -pub const BACKUP_SOURCE_SCHEMA: Schema = StringSchema::new( - "Backup source specification ([