pxar: extract PxarExtractOptions

same as PxarCreateOptions, but for extraction/restore rather than
create.

Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
This commit is contained in:
Fabian Grünbichler 2021-01-25 14:42:55 +01:00 committed by Wolfgang Bumiller
parent 77486a608e
commit 72064fd0df
4 changed files with 35 additions and 30 deletions

View File

@ -1354,20 +1354,24 @@ async fn restore(param: Value) -> Result<Value, Error> {
let mut reader = BufferedDynamicReader::new(index, chunk_reader); let mut reader = BufferedDynamicReader::new(index, chunk_reader);
let options = proxmox_backup::pxar::PxarExtractOptions {
match_list: &[],
extract_match_default: true,
allow_existing_dirs,
on_error: None,
};
if let Some(target) = target { if let Some(target) = target {
proxmox_backup::pxar::extract_archive( proxmox_backup::pxar::extract_archive(
pxar::decoder::Decoder::from_std(reader)?, pxar::decoder::Decoder::from_std(reader)?,
Path::new(target), Path::new(target),
&[],
true,
proxmox_backup::pxar::Flags::DEFAULT, proxmox_backup::pxar::Flags::DEFAULT,
allow_existing_dirs,
|path| { |path| {
if verbose { if verbose {
println!("{:?}", path); println!("{:?}", path);
} }
}, },
None, options,
) )
.map_err(|err| format_err!("error extracting archive - {}", err))?; .map_err(|err| format_err!("error extracting archive - {}", err))?;
} else { } else {

View File

@ -17,31 +17,26 @@ use proxmox::api::cli::*;
use proxmox::api::api; use proxmox::api::api;
use proxmox_backup::tools; use proxmox_backup::tools;
use proxmox_backup::pxar::{fuse, format_single_line_entry, ENCODER_MAX_ENTRIES, ErrorHandler, Flags}; use proxmox_backup::pxar::{fuse, format_single_line_entry, ENCODER_MAX_ENTRIES, Flags, PxarExtractOptions};
fn extract_archive_from_reader<R: std::io::Read>( fn extract_archive_from_reader<R: std::io::Read>(
reader: &mut R, reader: &mut R,
target: &str, target: &str,
feature_flags: Flags, feature_flags: Flags,
allow_existing_dirs: bool,
verbose: bool, verbose: bool,
match_list: &[MatchEntry], options: PxarExtractOptions,
extract_match_default: bool,
on_error: Option<ErrorHandler>,
) -> Result<(), Error> { ) -> Result<(), Error> {
proxmox_backup::pxar::extract_archive( proxmox_backup::pxar::extract_archive(
pxar::decoder::Decoder::from_std(reader)?, pxar::decoder::Decoder::from_std(reader)?,
Path::new(target), Path::new(target),
&match_list,
extract_match_default,
feature_flags, feature_flags,
allow_existing_dirs,
|path| { |path| {
if verbose { if verbose {
println!("{:?}", path); println!("{:?}", path);
} }
}, },
on_error, options,
) )
} }
@ -190,6 +185,13 @@ fn extract_archive(
}) as Box<dyn FnMut(Error) -> Result<(), Error> + Send>) }) as Box<dyn FnMut(Error) -> Result<(), Error> + Send>)
}; };
let options = PxarExtractOptions {
match_list: &match_list,
allow_existing_dirs,
extract_match_default,
on_error,
};
if archive == "-" { if archive == "-" {
let stdin = std::io::stdin(); let stdin = std::io::stdin();
let mut reader = stdin.lock(); let mut reader = stdin.lock();
@ -197,11 +199,8 @@ fn extract_archive(
&mut reader, &mut reader,
&target, &target,
feature_flags, feature_flags,
allow_existing_dirs,
verbose, verbose,
&match_list, options,
extract_match_default,
on_error,
)?; )?;
} else { } else {
if verbose { if verbose {
@ -213,11 +212,8 @@ fn extract_archive(
&mut reader, &mut reader,
&target, &target,
feature_flags, feature_flags,
allow_existing_dirs,
verbose, verbose,
&match_list, options,
extract_match_default,
on_error,
)?; )?;
} }
@ -297,6 +293,7 @@ fn extract_archive(
}, },
)] )]
/// Create a new .pxar archive. /// Create a new .pxar archive.
#[allow(clippy::too_many_arguments)]
fn create_archive( fn create_archive(
archive: String, archive: String,
source: String, source: String,

View File

@ -24,17 +24,21 @@ use crate::pxar::dir_stack::PxarDirStack;
use crate::pxar::metadata; use crate::pxar::metadata;
use crate::pxar::Flags; use crate::pxar::Flags;
pub struct PxarExtractOptions<'a> {
pub match_list: &'a[MatchEntry],
pub extract_match_default: bool,
pub allow_existing_dirs: bool,
pub on_error: Option<ErrorHandler>,
}
pub type ErrorHandler = Box<dyn FnMut(Error) -> Result<(), Error> + Send>; pub type ErrorHandler = Box<dyn FnMut(Error) -> Result<(), Error> + Send>;
pub fn extract_archive<T, F>( pub fn extract_archive<T, F>(
mut decoder: pxar::decoder::Decoder<T>, mut decoder: pxar::decoder::Decoder<T>,
destination: &Path, destination: &Path,
match_list: &[MatchEntry],
extract_match_default: bool,
feature_flags: Flags, feature_flags: Flags,
allow_existing_dirs: bool,
mut callback: F, mut callback: F,
on_error: Option<ErrorHandler>, options: PxarExtractOptions,
) -> Result<(), Error> ) -> Result<(), Error>
where where
T: pxar::decoder::SeqRead, T: pxar::decoder::SeqRead,
@ -69,17 +73,17 @@ where
let mut extractor = Extractor::new( let mut extractor = Extractor::new(
dir, dir,
root.metadata().clone(), root.metadata().clone(),
allow_existing_dirs, options.allow_existing_dirs,
feature_flags, feature_flags,
); );
if let Some(on_error) = on_error { if let Some(on_error) = options.on_error {
extractor.on_error(on_error); extractor.on_error(on_error);
} }
let mut match_stack = Vec::new(); let mut match_stack = Vec::new();
let mut err_path_stack = vec![OsString::from("/")]; let mut err_path_stack = vec![OsString::from("/")];
let mut current_match = extract_match_default; let mut current_match = options.extract_match_default;
while let Some(entry) = decoder.next() { while let Some(entry) = decoder.next() {
use pxar::EntryKind; use pxar::EntryKind;
@ -99,7 +103,7 @@ where
extractor.set_path(entry.path().as_os_str().to_owned()); extractor.set_path(entry.path().as_os_str().to_owned());
let match_result = match_list.matches( let match_result = options.match_list.matches(
entry.path().as_os_str().as_bytes(), entry.path().as_os_str().as_bytes(),
Some(metadata.file_type() as u32), Some(metadata.file_type() as u32),
); );

View File

@ -59,7 +59,7 @@ mod flags;
pub use flags::Flags; pub use flags::Flags;
pub use create::{create_archive, PxarCreateOptions}; pub use create::{create_archive, PxarCreateOptions};
pub use extract::{extract_archive, ErrorHandler}; pub use extract::{extract_archive, ErrorHandler, PxarExtractOptions};
/// The format requires to build sorted directory lookup tables in /// The format requires to build sorted directory lookup tables in
/// memory, so we restrict the number of allowed entries to limit /// memory, so we restrict the number of allowed entries to limit