diff --git a/pbs-api-types/src/lib.rs b/pbs-api-types/src/lib.rs index cc5103f4..8e2d1a7c 100644 --- a/pbs-api-types/src/lib.rs +++ b/pbs-api-types/src/lib.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; use proxmox::api::api; use proxmox::api::schema::{ApiStringFormat, Schema, StringSchema}; use proxmox::const_regex; +use proxmox::{IPRE, IPRE_BRACKET, IPV4OCTET, IPV4RE, IPV6H16, IPV6LS32, IPV6RE}; #[rustfmt::skip] #[macro_export] @@ -42,7 +43,37 @@ pub use userid::{PROXMOX_GROUP_ID_SCHEMA, PROXMOX_TOKEN_ID_SCHEMA, PROXMOX_TOKEN pub mod upid; pub use upid::UPID; +#[rustfmt::skip] +#[macro_use] +mod local_macros { + macro_rules! DNS_LABEL { () => (r"(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)") } + macro_rules! DNS_NAME { () => (concat!(r"(?:(?:", DNS_LABEL!() , r"\.)*", DNS_LABEL!(), ")")) } + macro_rules! CIDR_V4_REGEX_STR { () => (concat!(r"(?:", IPV4RE!(), r"/\d{1,2})$")) } + macro_rules! CIDR_V6_REGEX_STR { () => (concat!(r"(?:", IPV6RE!(), r"/\d{1,3})$")) } + macro_rules! DNS_ALIAS_LABEL { () => (r"(?:[a-zA-Z0-9_](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)") } + macro_rules! DNS_ALIAS_NAME { + () => (concat!(r"(?:(?:", DNS_ALIAS_LABEL!() , r"\.)*", DNS_ALIAS_LABEL!(), ")")) + } +} + const_regex! { + pub IP_V4_REGEX = concat!(r"^", IPV4RE!(), r"$"); + pub IP_V6_REGEX = concat!(r"^", IPV6RE!(), r"$"); + pub IP_REGEX = concat!(r"^", IPRE!(), r"$"); + pub CIDR_V4_REGEX = concat!(r"^", CIDR_V4_REGEX_STR!(), r"$"); + pub CIDR_V6_REGEX = concat!(r"^", CIDR_V6_REGEX_STR!(), r"$"); + pub CIDR_REGEX = concat!(r"^(?:", CIDR_V4_REGEX_STR!(), "|", CIDR_V6_REGEX_STR!(), r")$"); + pub HOSTNAME_REGEX = r"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)$"; + pub DNS_NAME_REGEX = concat!(r"^", DNS_NAME!(), r"$"); + pub DNS_ALIAS_REGEX = concat!(r"^", DNS_ALIAS_NAME!(), r"$"); + pub DNS_NAME_OR_IP_REGEX = concat!(r"^(?:", DNS_NAME!(), "|", IPRE!(), r")$"); + + pub SHA256_HEX_REGEX = r"^[a-f0-9]{64}$"; // fixme: define in common_regex ? + + pub PASSWORD_REGEX = r"^[[:^cntrl:]]*$"; // everything but control characters + + pub UUID_REGEX = r"^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$"; + pub BACKUP_TYPE_REGEX = concat!(r"^(", BACKUP_TYPE_RE!(), r")$"); pub BACKUP_ID_REGEX = concat!(r"^", BACKUP_ID_RE!(), r"$"); @@ -67,8 +98,23 @@ const_regex! { pub PROXMOX_SAFE_ID_REGEX = concat!(r"^", PROXMOX_SAFE_ID_REGEX_STR!(), r"$"); pub SINGLE_LINE_COMMENT_REGEX = r"^[[:^cntrl:]]*$"; + + pub BACKUP_REPO_URL_REGEX = concat!( + r"^^(?:(?:(", + USER_ID_REGEX_STR!(), "|", APITOKEN_ID_REGEX_STR!(), + ")@)?(", + DNS_NAME!(), "|", IPRE_BRACKET!(), + "):)?(?:([0-9]{1,5}):)?(", PROXMOX_SAFE_ID_REGEX_STR!(), r")$" + ); } +pub const IP_V4_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_V4_REGEX); +pub const IP_V6_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_V6_REGEX); +pub const IP_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&IP_REGEX); +pub const CIDR_V4_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_V4_REGEX); +pub const CIDR_V6_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_V6_REGEX); +pub const CIDR_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&CIDR_REGEX); + pub const FINGERPRINT_SHA256_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&FINGERPRINT_SHA256_REGEX); @@ -89,6 +135,9 @@ pub const SINGLE_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (singl pub const BACKUP_ID_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&BACKUP_ID_REGEX); +/// API schema format definition for repository URLs +pub const BACKUP_REPO_URL: ApiStringFormat = ApiStringFormat::Pattern(&BACKUP_REPO_URL_REGEX); + #[api( properties: { "upid": { @@ -141,3 +190,10 @@ impl Default for GarbageCollectionStatus { } } } + +pub const PVE_CONFIG_DIGEST_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SHA256_HEX_REGEX); +pub const CHUNK_DIGEST_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SHA256_HEX_REGEX); + +pub const PASSWORD_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&PASSWORD_REGEX); + +pub const UUID_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&UUID_REGEX); diff --git a/src/api2/types/mod.rs b/src/api2/types/mod.rs index 6698f4b7..287abc7e 100644 --- a/src/api2/types/mod.rs +++ b/src/api2/types/mod.rs @@ -5,7 +5,6 @@ use serde::{Deserialize, Serialize}; use proxmox::api::{api, schema::*}; use proxmox::const_regex; -use proxmox::{IPRE, IPRE_BRACKET, IPV4RE, IPV6RE, IPV4OCTET, IPV6H16, IPV6LS32}; use pbs_datastore::catalog::CatalogEntryType; @@ -41,45 +40,14 @@ pub const FILENAME_FORMAT: ApiStringFormat = ApiStringFormat::VerifyFn(|name| { Ok(()) }); -macro_rules! DNS_LABEL { () => (r"(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)") } -macro_rules! DNS_NAME { () => (concat!(r"(?:(?:", DNS_LABEL!() , r"\.)*", DNS_LABEL!(), ")")) } - -macro_rules! DNS_ALIAS_LABEL { () => (r"(?:[a-zA-Z0-9_](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)") } -macro_rules! DNS_ALIAS_NAME { - () => (concat!(r"(?:(?:", DNS_ALIAS_LABEL!() , r"\.)*", DNS_ALIAS_LABEL!(), ")")) -} - -macro_rules! CIDR_V4_REGEX_STR { () => (concat!(r"(?:", IPV4RE!(), r"/\d{1,2})$")) } -macro_rules! CIDR_V6_REGEX_STR { () => (concat!(r"(?:", IPV6RE!(), r"/\d{1,3})$")) } - const_regex!{ - pub IP_V4_REGEX = concat!(r"^", IPV4RE!(), r"$"); - pub IP_V6_REGEX = concat!(r"^", IPV6RE!(), r"$"); - pub IP_REGEX = concat!(r"^", IPRE!(), r"$"); - pub CIDR_V4_REGEX = concat!(r"^", CIDR_V4_REGEX_STR!(), r"$"); - pub CIDR_V6_REGEX = concat!(r"^", CIDR_V6_REGEX_STR!(), r"$"); - pub CIDR_REGEX = concat!(r"^(?:", CIDR_V4_REGEX_STR!(), "|", CIDR_V6_REGEX_STR!(), r")$"); - - pub SHA256_HEX_REGEX = r"^[a-f0-9]{64}$"; // fixme: define in common_regex ? pub SYSTEMD_DATETIME_REGEX = r"^\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?$"; // fixme: define in common_regex ? - pub PASSWORD_REGEX = r"^[[:^cntrl:]]*$"; // everything but control characters - /// Regex for verification jobs 'DATASTORE:ACTUAL_JOB_ID' pub VERIFICATION_JOB_WORKER_ID_REGEX = concat!(r"^(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):"); /// Regex for sync jobs 'REMOTE:REMOTE_DATASTORE:LOCAL_DATASTORE:ACTUAL_JOB_ID' pub SYNC_JOB_WORKER_ID_REGEX = concat!(r"^(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):(", PROXMOX_SAFE_ID_REGEX_STR!(), r"):"); - pub HOSTNAME_REGEX = r"^(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)$"; - - pub DNS_NAME_REGEX = concat!(r"^", DNS_NAME!(), r"$"); - - pub DNS_ALIAS_REGEX = concat!(r"^", DNS_ALIAS_NAME!(), r"$"); - - pub DNS_NAME_OR_IP_REGEX = concat!(r"^(?:", DNS_NAME!(), "|", IPRE!(), r")$"); - - pub BACKUP_REPO_URL_REGEX = concat!(r"^^(?:(?:(", USER_ID_REGEX_STR!(), "|", APITOKEN_ID_REGEX_STR!(), ")@)?(", DNS_NAME!(), "|", IPRE_BRACKET!() ,"):)?(?:([0-9]{1,5}):)?(", PROXMOX_SAFE_ID_REGEX_STR!(), r")$"); - pub ACL_PATH_REGEX = concat!(r"^(?:/|", r"(?:/", PROXMOX_SAFE_ID_REGEX_STR!(), ")+", r")$"); pub SUBSCRIPTION_KEY_REGEX = concat!(r"^pbs(?:[cbsp])-[0-9a-f]{10}$"); @@ -88,8 +56,6 @@ const_regex!{ pub ZPOOL_NAME_REGEX = r"^[a-zA-Z][a-z0-9A-Z\-_.:]+$"; - pub UUID_REGEX = r"^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$"; - pub DATASTORE_MAP_REGEX = concat!(r"(:?", PROXMOX_SAFE_ID_REGEX_STR!(), r"=)?", PROXMOX_SAFE_ID_REGEX_STR!()); pub TAPE_RESTORE_SNAPSHOT_REGEX = concat!(r"^", PROXMOX_SAFE_ID_REGEX_STR!(), r":", SNAPSHOT_PATH_REGEX_STR!(), r"$"); @@ -98,21 +64,6 @@ const_regex!{ pub const SYSTEMD_DATETIME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SYSTEMD_DATETIME_REGEX); -pub const IP_V4_FORMAT: ApiStringFormat = - ApiStringFormat::Pattern(&IP_V4_REGEX); - -pub const IP_V6_FORMAT: ApiStringFormat = - ApiStringFormat::Pattern(&IP_V6_REGEX); - -pub const IP_FORMAT: ApiStringFormat = - ApiStringFormat::Pattern(&IP_REGEX); - -pub const PVE_CONFIG_DIGEST_FORMAT: ApiStringFormat = - ApiStringFormat::Pattern(&SHA256_HEX_REGEX); - -pub const UUID_FORMAT: ApiStringFormat = - ApiStringFormat::Pattern(&UUID_REGEX); - pub const HOSTNAME_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&HOSTNAME_REGEX); @@ -125,24 +76,12 @@ pub const DNS_ALIAS_FORMAT: ApiStringFormat = pub const DNS_NAME_OR_IP_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&DNS_NAME_OR_IP_REGEX); -pub const PASSWORD_FORMAT: ApiStringFormat = - ApiStringFormat::Pattern(&PASSWORD_REGEX); - pub const ACL_PATH_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&ACL_PATH_REGEX); pub const NETWORK_INTERFACE_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&PROXMOX_SAFE_ID_REGEX); -pub const CIDR_V4_FORMAT: ApiStringFormat = - ApiStringFormat::Pattern(&CIDR_V4_REGEX); - -pub const CIDR_V6_FORMAT: ApiStringFormat = - ApiStringFormat::Pattern(&CIDR_V6_REGEX); - -pub const CIDR_FORMAT: ApiStringFormat = - ApiStringFormat::Pattern(&CIDR_REGEX); - pub const SUBSCRIPTION_KEY_FORMAT: ApiStringFormat = ApiStringFormat::Pattern(&SUBSCRIPTION_KEY_REGEX); @@ -181,9 +120,6 @@ pub const PROXMOX_CONFIG_DIGEST_SCHEMA: Schema = StringSchema::new( .format(&PVE_CONFIG_DIGEST_FORMAT) .schema(); -pub const CHUNK_DIGEST_FORMAT: ApiStringFormat = - ApiStringFormat::Pattern(&SHA256_HEX_REGEX); - pub const CHUNK_DIGEST_SCHEMA: Schema = StringSchema::new("Chunk digest (SHA256).") .format(&CHUNK_DIGEST_FORMAT) .schema(); diff --git a/src/bin/proxmox_client_tools/mod.rs b/src/bin/proxmox_client_tools/mod.rs index aae90c71..77c33ff0 100644 --- a/src/bin/proxmox_client_tools/mod.rs +++ b/src/bin/proxmox_client_tools/mod.rs @@ -10,12 +10,12 @@ use proxmox::{ tools::fs::file_get_json, }; +use pbs_api_types::{BACKUP_REPO_URL, Authid}; use pbs_buildcfg; use proxmox_backup::api2::access::user::UserWithTokens; -use proxmox_backup::api2::types::*; use proxmox_backup::backup::BackupDir; -use proxmox_backup::client::*; +use proxmox_backup::client::{BackupRepository, HttpClient, HttpClientOptions}; use proxmox_backup::tools; pub mod key_source; diff --git a/src/client/backup_reader.rs b/src/client/backup_reader.rs index 7f24cb9b..ca546f39 100644 --- a/src/client/backup_reader.rs +++ b/src/client/backup_reader.rs @@ -9,10 +9,15 @@ use serde_json::{json, Value}; use proxmox::tools::digest_to_hex; -use crate::{ - tools::compute_file_csum, - backup::*, -}; +use pbs_datastore::{CryptConfig, 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 crate::tools::compute_file_csum; use super::{HttpClient, H2Client}; diff --git a/src/client/backup_repo.rs b/src/client/backup_repo.rs index 091d2707..dc9b8ec8 100644 --- a/src/client/backup_repo.rs +++ b/src/client/backup_repo.rs @@ -3,12 +3,7 @@ use std::fmt; use anyhow::{format_err, Error}; -use proxmox::api::schema::*; - -use crate::api2::types::*; - -/// API schema format definition for repository URLs -pub const BACKUP_REPO_URL: ApiStringFormat = ApiStringFormat::Pattern(&BACKUP_REPO_URL_REGEX); +use pbs_api_types::{BACKUP_REPO_URL_REGEX, IP_V6_REGEX, Authid, Userid}; /// Reference remote backup locations ///