pxar: better error handling on extract
Errors while applying metadata will not be considered fatal by default using `pxar extract` unless `--strict` was passed in which case it'll bail out immediately. It'll still return an error exit status if something had failed along the way. Note that most other errors will still cause it to bail out (eg. errors creating files, or I/O errors while writing the contents). Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
@ -3,8 +3,10 @@ use std::ffi::OsStr;
|
||||
use std::fs::OpenOptions;
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use anyhow::{format_err, Error};
|
||||
use anyhow::{bail, format_err, Error};
|
||||
use futures::future::FutureExt;
|
||||
use futures::select;
|
||||
use tokio::signal::unix::{signal, SignalKind};
|
||||
@ -25,6 +27,7 @@ fn extract_archive_from_reader<R: std::io::Read>(
|
||||
verbose: bool,
|
||||
match_list: &[MatchEntry],
|
||||
extract_match_default: bool,
|
||||
on_error: Option<Box<dyn FnMut(Error) -> Result<(), Error> + Send>>,
|
||||
) -> Result<(), Error> {
|
||||
proxmox_backup::pxar::extract_archive(
|
||||
pxar::decoder::Decoder::from_std(reader)?,
|
||||
@ -38,6 +41,7 @@ fn extract_archive_from_reader<R: std::io::Read>(
|
||||
println!("{:?}", path);
|
||||
}
|
||||
},
|
||||
on_error,
|
||||
)
|
||||
}
|
||||
|
||||
@ -104,6 +108,11 @@ fn extract_archive_from_reader<R: std::io::Read>(
|
||||
optional: true,
|
||||
default: false,
|
||||
},
|
||||
strict: {
|
||||
description: "Stop on errors. Otherwise most errors will simply warn.",
|
||||
optional: true,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
)]
|
||||
@ -121,6 +130,7 @@ fn extract_archive(
|
||||
no_device_nodes: bool,
|
||||
no_fifos: bool,
|
||||
no_sockets: bool,
|
||||
strict: bool,
|
||||
) -> Result<(), Error> {
|
||||
let mut feature_flags = Flags::DEFAULT;
|
||||
if no_xattrs {
|
||||
@ -166,6 +176,20 @@ fn extract_archive(
|
||||
|
||||
let extract_match_default = match_list.is_empty();
|
||||
|
||||
let was_ok = Arc::new(AtomicBool::new(true));
|
||||
let on_error = if strict {
|
||||
// by default errors are propagated up
|
||||
None
|
||||
} else {
|
||||
let was_ok = Arc::clone(&was_ok);
|
||||
// otherwise we want to log them but not act on them
|
||||
Some(Box::new(move |err| {
|
||||
was_ok.store(false, Ordering::Release);
|
||||
eprintln!("error: {}", err);
|
||||
Ok(())
|
||||
}) as Box<dyn FnMut(Error) -> Result<(), Error> + Send>)
|
||||
};
|
||||
|
||||
if archive == "-" {
|
||||
let stdin = std::io::stdin();
|
||||
let mut reader = stdin.lock();
|
||||
@ -177,6 +201,7 @@ fn extract_archive(
|
||||
verbose,
|
||||
&match_list,
|
||||
extract_match_default,
|
||||
on_error,
|
||||
)?;
|
||||
} else {
|
||||
if verbose {
|
||||
@ -192,9 +217,14 @@ fn extract_archive(
|
||||
verbose,
|
||||
&match_list,
|
||||
extract_match_default,
|
||||
on_error,
|
||||
)?;
|
||||
}
|
||||
|
||||
if !was_ok.load(Ordering::Acquire) {
|
||||
bail!("there were errors");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user