[pbs-devel] [PATCH proxmox-backup v2 1/3] pbs-client: added overwrite-existing-files to PxarExtractOptions.
Markus Frank
m.frank at proxmox.com
Thu Aug 18 13:06:52 CEST 2022
If overwrite-existing-files is true, O_TRUNC is set (to clean the
leftovers) instead of O_EXCL and therefore overwrites the files and
does not error out.
Signed-off-by: Markus Frank <m.frank at proxmox.com>
---
v2: add O_TRUNC to oflags if overwrite_existing_files is true.
pbs-client/src/catalog_shell.rs | 4 ++--
pbs-client/src/pxar/extract.rs | 28 +++++++++++++++++++++++++---
pxar-bin/src/main.rs | 7 +++++++
3 files changed, 34 insertions(+), 5 deletions(-)
diff --git a/pbs-client/src/catalog_shell.rs b/pbs-client/src/catalog_shell.rs
index b11901ed..25e27b37 100644
--- a/pbs-client/src/catalog_shell.rs
+++ b/pbs-client/src/catalog_shell.rs
@@ -984,7 +984,7 @@ impl Shell {
.clone();
let extractor =
- crate::pxar::extract::Extractor::new(rootdir, root_meta, true, Flags::DEFAULT);
+ crate::pxar::extract::Extractor::new(rootdir, root_meta, true, false, Flags::DEFAULT);
let mut extractor = ExtractorState::new(
&mut self.catalog,
@@ -1172,7 +1172,7 @@ impl<'a> ExtractorState<'a> {
let file_name = CString::new(entry.file_name().as_bytes())?;
let mut contents = entry.contents().await?;
self.extractor
- .async_extract_file(&file_name, entry.metadata(), *size, &mut contents)
+ .async_extract_file(&file_name, entry.metadata(), *size, &mut contents, false)
.await
}
_ => {
diff --git a/pbs-client/src/pxar/extract.rs b/pbs-client/src/pxar/extract.rs
index 161d2cef..36600789 100644
--- a/pbs-client/src/pxar/extract.rs
+++ b/pbs-client/src/pxar/extract.rs
@@ -34,6 +34,7 @@ pub struct PxarExtractOptions<'a> {
pub match_list: &'a [MatchEntry],
pub extract_match_default: bool,
pub allow_existing_dirs: bool,
+ pub overwrite_existing_files: bool,
pub on_error: Option<ErrorHandler>,
}
@@ -80,6 +81,7 @@ where
dir,
root.metadata().clone(),
options.allow_existing_dirs,
+ options.overwrite_existing_files,
feature_flags,
);
@@ -198,6 +200,7 @@ where
&mut decoder.contents().ok_or_else(|| {
format_err!("found regular file entry without contents in archive")
})?,
+ extractor.overwrite_existing_files,
),
(false, _) => Ok(()), // skip this
}
@@ -215,6 +218,7 @@ where
pub struct Extractor {
feature_flags: Flags,
allow_existing_dirs: bool,
+ overwrite_existing_files: bool,
dir_stack: PxarDirStack,
/// For better error output we need to track the current path in the Extractor state.
@@ -231,11 +235,13 @@ impl Extractor {
root_dir: Dir,
metadata: Metadata,
allow_existing_dirs: bool,
+ overwrite_existing_files: bool,
feature_flags: Flags,
) -> Self {
Self {
dir_stack: PxarDirStack::new(root_dir, metadata),
allow_existing_dirs,
+ overwrite_existing_files,
feature_flags,
current_path: Arc::new(Mutex::new(OsString::new())),
on_error: Box::new(Err),
@@ -392,14 +398,21 @@ impl Extractor {
metadata: &Metadata,
size: u64,
contents: &mut dyn io::Read,
+ overwrite_existing_files: bool,
) -> Result<(), Error> {
let parent = self.parent_fd()?;
+ let mut oflags = OFlag::O_CREAT | OFlag::O_WRONLY | OFlag::O_CLOEXEC;
+ if overwrite_existing_files {
+ oflags = oflags | OFlag::O_TRUNC;
+ } else {
+ oflags = oflags | OFlag::O_EXCL;
+ }
let mut file = unsafe {
std::fs::File::from_raw_fd(
nix::fcntl::openat(
parent,
file_name,
- OFlag::O_CREAT | OFlag::O_EXCL | OFlag::O_WRONLY | OFlag::O_CLOEXEC,
+ oflags,
Mode::from_bits(0o600).unwrap(),
)
.map_err(|err| format_err!("failed to create file {:?}: {}", file_name, err))?,
@@ -448,14 +461,21 @@ impl Extractor {
metadata: &Metadata,
size: u64,
contents: &mut T,
+ overwrite_existing_files: bool,
) -> Result<(), Error> {
let parent = self.parent_fd()?;
+ let mut oflags = OFlag::O_CREAT | OFlag::O_WRONLY | OFlag::O_CLOEXEC;
+ if overwrite_existing_files {
+ oflags = oflags | OFlag::O_TRUNC;
+ } else {
+ oflags = oflags | OFlag::O_EXCL;
+ }
let mut file = tokio::fs::File::from_std(unsafe {
std::fs::File::from_raw_fd(
nix::fcntl::openat(
parent,
file_name,
- OFlag::O_CREAT | OFlag::O_EXCL | OFlag::O_WRONLY | OFlag::O_CLOEXEC,
+ oflags,
Mode::from_bits(0o600).unwrap(),
)
.map_err(|err| format_err!("failed to create file {:?}: {}", file_name, err))?,
@@ -818,7 +838,7 @@ where
)
})?;
- Ok(Extractor::new(dir, metadata, false, Flags::DEFAULT))
+ Ok(Extractor::new(dir, metadata, false, false, Flags::DEFAULT))
}
pub async fn extract_sub_dir<T, DEST, PATH>(
@@ -951,6 +971,7 @@ where
&mut file.contents().await.map_err(|_| {
format_err!("found regular file entry without contents in archive")
})?,
+ extractor.overwrite_existing_files,
)
.await?
}
@@ -998,6 +1019,7 @@ where
&mut decoder.contents().ok_or_else(|| {
format_err!("found regular file entry without contents in archive")
})?,
+ extractor.overwrite_existing_files,
)
.await?
}
diff --git a/pxar-bin/src/main.rs b/pxar-bin/src/main.rs
index 3714eb03..1dd34deb 100644
--- a/pxar-bin/src/main.rs
+++ b/pxar-bin/src/main.rs
@@ -75,6 +75,11 @@ fn extract_archive_from_reader<R: std::io::Read>(
optional: true,
default: false,
},
+ "overwrite_existing_files": {
+ description: "overwrite already existing files",
+ optional: true,
+ default: false,
+ },
"files-from": {
description: "File containing match pattern for files to restore.",
optional: true,
@@ -112,6 +117,7 @@ fn extract_archive(
no_fcaps: bool,
no_acls: bool,
allow_existing_dirs: bool,
+ overwrite_existing_files: bool,
files_from: Option<String>,
no_device_nodes: bool,
no_fifos: bool,
@@ -179,6 +185,7 @@ fn extract_archive(
let options = PxarExtractOptions {
match_list: &match_list,
allow_existing_dirs,
+ overwrite_existing_files,
extract_match_default,
on_error,
};
--
2.30.2
More information about the pbs-devel
mailing list