* [pbs-devel] [PATCH proxmox-backup 0/3] pbs-client feature #3923
@ 2022-08-16 9:19 Markus Frank
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 1/3] added overwrite-existing-files as Markus Frank
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Markus Frank @ 2022-08-16 9:19 UTC (permalink / raw)
To: pbs-devel
These patches are for ignore-acl, ignore-xattr, ignore-ownership &
overwrite-existing-files parameter in proxmox-backup-client.
Markus Frank (3):
overwrite-existing-files for pxar
skip xattr/acl/ownership options
added ignore-acl/xattr/ownership & overwrite parameter to
proxmox-backup-client
pbs-client/src/catalog_shell.rs | 4 +--
pbs-client/src/pxar/extract.rs | 24 ++++++++++++++--
pbs-client/src/pxar/flags.rs | 1 +
pbs-client/src/pxar/metadata.rs | 48 ++++++++++++++++++++-----------
proxmox-backup-client/src/main.rs | 40 +++++++++++++++++++++++++-
pxar-bin/src/main.rs | 7 +++++
6 files changed, 101 insertions(+), 23 deletions(-)
--
2.30.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 1/3] added overwrite-existing-files as
2022-08-16 9:19 [pbs-devel] [PATCH proxmox-backup 0/3] pbs-client feature #3923 Markus Frank
@ 2022-08-16 9:19 ` Markus Frank
2022-08-16 9:48 ` Markus Frank
2022-08-17 7:31 ` Wolfgang Bumiller
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 2/3] skip xattr/acl/ownership options Markus Frank
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 3/3] added ignore-acl/xattr/ownership & overwrite parameter to proxmox-backup-client Markus Frank
2 siblings, 2 replies; 7+ messages in thread
From: Markus Frank @ 2022-08-16 9:19 UTC (permalink / raw)
To: pbs-devel
If true, O_EXCL is not set and therefore overwrites the files and does not
error out.
Signed-off-by: Markus Frank <m.frank@proxmox.com>
---
pbs-client/src/catalog_shell.rs | 4 ++--
| 24 +++++++++++++++++++++---
pxar-bin/src/main.rs | 7 +++++++
3 files changed, 30 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
}
_ => {
--git a/pbs-client/src/pxar/extract.rs b/pbs-client/src/pxar/extract.rs
index 161d2cef..3b9151aa 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,19 @@ 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_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 +459,19 @@ 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_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 +834,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 +967,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 +1015,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..4b49df51 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 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
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 2/3] skip xattr/acl/ownership options
2022-08-16 9:19 [pbs-devel] [PATCH proxmox-backup 0/3] pbs-client feature #3923 Markus Frank
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 1/3] added overwrite-existing-files as Markus Frank
@ 2022-08-16 9:19 ` Markus Frank
2022-08-17 7:36 ` Wolfgang Bumiller
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 3/3] added ignore-acl/xattr/ownership & overwrite parameter to proxmox-backup-client Markus Frank
2 siblings, 1 reply; 7+ messages in thread
From: Markus Frank @ 2022-08-16 9:19 UTC (permalink / raw)
To: pbs-devel
added cases to skip xattr/acl/ownership if the flags are not set.
Also added WITH_PERMISSIONS to Default-Flags, because otherwise it
would be needed to activly set it and most filesystems that support
XATTR and ACL also support POSIX-Permissions.
Signed-off-by: Markus Frank <m.frank@proxmox.com>
---
pbs-client/src/pxar/flags.rs | 1 +
pbs-client/src/pxar/metadata.rs | 48 +++++++++++++++++++++------------
2 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/pbs-client/src/pxar/flags.rs b/pbs-client/src/pxar/flags.rs
index d46c8af3..938d0c57 100644
--- a/pbs-client/src/pxar/flags.rs
+++ b/pbs-client/src/pxar/flags.rs
@@ -135,6 +135,7 @@ bitflags! {
Flags::WITH_FLAG_PROJINHERIT.bits() |
Flags::WITH_SUBVOLUME.bits() |
Flags::WITH_SUBVOLUME_RO.bits() |
+ Flags::WITH_PERMISSIONS.bits() |
Flags::WITH_XATTRS.bits() |
Flags::WITH_ACL.bits() |
Flags::WITH_SELINUX.bits() |
diff --git a/pbs-client/src/pxar/metadata.rs b/pbs-client/src/pxar/metadata.rs
index 22bc5f9d..3195fb03 100644
--- a/pbs-client/src/pxar/metadata.rs
+++ b/pbs-client/src/pxar/metadata.rs
@@ -100,27 +100,17 @@ pub fn apply(
on_error: &mut (dyn FnMut(Error) -> Result<(), Error> + Send),
) -> Result<(), Error> {
let c_proc_path = CString::new(format!("/proc/self/fd/{}", fd)).unwrap();
+ apply_ownership(flags, c_proc_path.as_ptr(), metadata, &mut *on_error)?;
- unsafe {
- // UID and GID first, as this fails if we lose access anyway.
- c_result!(libc::chown(
- c_proc_path.as_ptr(),
- metadata.stat.uid,
- metadata.stat.gid
- ))
- .map(drop)
- .or_else(allow_notsupp)
- .map_err(|err| format_err!("failed to set ownership: {}", err))
- .or_else(&mut *on_error)?;
- }
-
- let mut skip_xattrs = false;
+ let mut skip_xattrs = !flags.contains(Flags::WITH_XATTRS);
apply_xattrs(flags, c_proc_path.as_ptr(), metadata, &mut skip_xattrs)
.or_else(&mut *on_error)?;
add_fcaps(flags, c_proc_path.as_ptr(), metadata, &mut skip_xattrs).or_else(&mut *on_error)?;
- apply_acls(flags, &c_proc_path, metadata, path_info)
- .map_err(|err| format_err!("failed to apply acls: {}", err))
- .or_else(&mut *on_error)?;
+ if flags.contains(Flags::WITH_ACL) {
+ apply_acls(flags, &c_proc_path, metadata, path_info)
+ .map_err(|err| format_err!("failed to apply acls: {}", err))
+ .or_else(&mut *on_error)?;
+ }
apply_quota_project_id(flags, fd, metadata).or_else(&mut *on_error)?;
// Finally mode and time. We may lose access with mode, but the changing the mode also
@@ -162,6 +152,30 @@ pub fn apply(
Ok(())
}
+pub fn apply_ownership(
+ flags: Flags,
+ c_proc_path: *const libc::c_char,
+ metadata: &Metadata,
+ on_error: &mut (dyn FnMut(Error) -> Result<(), Error> + Send),
+) -> Result<(), Error> {
+ if !flags.contains(Flags::WITH_PERMISSIONS) {
+ return Ok(());
+ }
+ unsafe {
+ // UID and GID first, as this fails if we lose access anyway.
+ c_result!(libc::chown(
+ c_proc_path,
+ metadata.stat.uid,
+ metadata.stat.gid
+ ))
+ .map(drop)
+ .or_else(allow_notsupp)
+ .map_err(|err| format_err!("failed to set ownership: {}", err))
+ .or_else(&mut *on_error)?;
+ }
+ Ok(())
+}
+
fn add_fcaps(
flags: Flags,
c_proc_path: *const libc::c_char,
--
2.30.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 3/3] added ignore-acl/xattr/ownership & overwrite parameter to proxmox-backup-client
2022-08-16 9:19 [pbs-devel] [PATCH proxmox-backup 0/3] pbs-client feature #3923 Markus Frank
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 1/3] added overwrite-existing-files as Markus Frank
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 2/3] skip xattr/acl/ownership options Markus Frank
@ 2022-08-16 9:19 ` Markus Frank
2 siblings, 0 replies; 7+ messages in thread
From: Markus Frank @ 2022-08-16 9:19 UTC (permalink / raw)
To: pbs-devel
If ignore-acl/ignore-xattr/ignore-ownership is set, the corresponding flag gets
removed.
overwrite-existing-files is saved as an PxarExtractOption like allow-existing-dirs.
Signed-off-by: Markus Frank <m.frank@proxmox.com>
---
proxmox-backup-client/src/main.rs | 40 ++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/proxmox-backup-client/src/main.rs b/proxmox-backup-client/src/main.rs
index 4bb9aa5e..20c29e26 100644
--- a/proxmox-backup-client/src/main.rs
+++ b/proxmox-backup-client/src/main.rs
@@ -1201,6 +1201,26 @@ We do not extract '.pxar' archives when writing to standard output.
type: CryptMode,
optional: true,
},
+ "ignore-ownership": {
+ type: Boolean,
+ description: "ignore owner settings",
+ optional: true,
+ },
+ "ignore-acl": {
+ type: Boolean,
+ description: "ignore acl errors",
+ optional: true,
+ },
+ "ignore-xattr": {
+ type: Boolean,
+ description: "ignore xattr errors",
+ optional: true,
+ },
+ "overwrite-existing-files": {
+ type: Boolean,
+ description: "overwrite existing files",
+ optional: true,
+ },
}
}
)]
@@ -1210,6 +1230,11 @@ async fn restore(param: Value) -> Result<Value, Error> {
let allow_existing_dirs = param["allow-existing-dirs"].as_bool().unwrap_or(false);
+ let ignore_acls = param["ignore-acl"].as_bool().unwrap_or(false);
+ let ignore_xattrs = param["ignore-xattr"].as_bool().unwrap_or(false);
+ let ignore_ownership = param["ignore-ownership"].as_bool().unwrap_or(false);
+ let overwrite_existing_files = param["overwrite-existing-files"].as_bool().unwrap_or(false);
+
let archive_name = json::required_string_param(¶m, "archive-name")?;
let rate = match param["rate"].as_str() {
@@ -1331,14 +1356,27 @@ async fn restore(param: Value) -> Result<Value, Error> {
match_list: &[],
extract_match_default: true,
allow_existing_dirs,
+ overwrite_existing_files,
on_error: None,
};
+ let mut feature_flags = pbs_client::pxar::Flags::DEFAULT;
+
+ if ignore_ownership {
+ feature_flags.remove(pbs_client::pxar::Flags::WITH_PERMISSIONS);
+ }
+ if ignore_acls {
+ feature_flags.remove(pbs_client::pxar::Flags::WITH_ACL);
+ }
+ if ignore_xattrs {
+ feature_flags.remove(pbs_client::pxar::Flags::WITH_XATTRS);
+ }
+
if let Some(target) = target {
pbs_client::pxar::extract_archive(
pxar::decoder::Decoder::from_std(reader)?,
Path::new(target),
- pbs_client::pxar::Flags::DEFAULT,
+ feature_flags,
|path| {
log::debug!("{:?}", path);
},
--
2.30.2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [pbs-devel] [PATCH proxmox-backup 1/3] added overwrite-existing-files as
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 1/3] added overwrite-existing-files as Markus Frank
@ 2022-08-16 9:48 ` Markus Frank
2022-08-17 7:31 ` Wolfgang Bumiller
1 sibling, 0 replies; 7+ messages in thread
From: Markus Frank @ 2022-08-16 9:48 UTC (permalink / raw)
To: pbs-devel
I am sorry. Subject/Commit-Message should be:
added overwrite-existing-files to PxarExtractOptions
On 8/16/22 11:19, Markus Frank wrote:
> If true, O_EXCL is not set and therefore overwrites the files and does not
> error out.
>
> Signed-off-by: Markus Frank <m.frank@proxmox.com>
> ---
> pbs-client/src/catalog_shell.rs | 4 ++--
> pbs-client/src/pxar/extract.rs | 24 +++++++++++++++++++++---
> pxar-bin/src/main.rs | 7 +++++++
> 3 files changed, 30 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..3b9151aa 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,19 @@ 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_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 +459,19 @@ 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_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 +834,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 +967,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 +1015,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..4b49df51 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 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
>
>
>
> _______________________________________________
> pbs-devel mailing list
> pbs-devel@lists.proxmox.com
> https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
>
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [pbs-devel] [PATCH proxmox-backup 1/3] added overwrite-existing-files as
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 1/3] added overwrite-existing-files as Markus Frank
2022-08-16 9:48 ` Markus Frank
@ 2022-08-17 7:31 ` Wolfgang Bumiller
1 sibling, 0 replies; 7+ messages in thread
From: Wolfgang Bumiller @ 2022-08-17 7:31 UTC (permalink / raw)
To: Markus Frank; +Cc: pbs-devel
On Tue, Aug 16, 2022 at 11:19:27AM +0200, Markus Frank wrote:
> If true, O_EXCL is not set and therefore overwrites the files and does not
> error out.
>
> Signed-off-by: Markus Frank <m.frank@proxmox.com>
> ---
> pbs-client/src/catalog_shell.rs | 4 ++--
> pbs-client/src/pxar/extract.rs | 24 +++++++++++++++++++++---
> pxar-bin/src/main.rs | 7 +++++++
> 3 files changed, 30 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..3b9151aa 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,19 @@ 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;
When replacing existing files we should include `O_TRUNC`, too,
otherwise if the new file is smaller and doesn't end in a hole (where we
already fixup the size with an explicit truncate() call) it'll have
parts of the previous contents left over at the end.
> + if !overwrite_existing_files {
> + 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 +459,19 @@ 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_EXCL;
> + }
same here
> 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 +834,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 +967,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 +1015,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..4b49df51 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 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
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [pbs-devel] [PATCH proxmox-backup 2/3] skip xattr/acl/ownership options
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 2/3] skip xattr/acl/ownership options Markus Frank
@ 2022-08-17 7:36 ` Wolfgang Bumiller
0 siblings, 0 replies; 7+ messages in thread
From: Wolfgang Bumiller @ 2022-08-17 7:36 UTC (permalink / raw)
To: Markus Frank; +Cc: pbs-devel
On Tue, Aug 16, 2022 at 11:19:28AM +0200, Markus Frank wrote:
> added cases to skip xattr/acl/ownership if the flags are not set.
> Also added WITH_PERMISSIONS to Default-Flags, because otherwise it
> would be needed to activly set it and most filesystems that support
> XATTR and ACL also support POSIX-Permissions.
>
> Signed-off-by: Markus Frank <m.frank@proxmox.com>
> ---
> pbs-client/src/pxar/flags.rs | 1 +
> pbs-client/src/pxar/metadata.rs | 48 +++++++++++++++++++++------------
> 2 files changed, 32 insertions(+), 17 deletions(-)
>
> diff --git a/pbs-client/src/pxar/flags.rs b/pbs-client/src/pxar/flags.rs
> index d46c8af3..938d0c57 100644
> --- a/pbs-client/src/pxar/flags.rs
> +++ b/pbs-client/src/pxar/flags.rs
> @@ -135,6 +135,7 @@ bitflags! {
> Flags::WITH_FLAG_PROJINHERIT.bits() |
> Flags::WITH_SUBVOLUME.bits() |
> Flags::WITH_SUBVOLUME_RO.bits() |
> + Flags::WITH_PERMISSIONS.bits() |
> Flags::WITH_XATTRS.bits() |
> Flags::WITH_ACL.bits() |
> Flags::WITH_SELINUX.bits() |
> diff --git a/pbs-client/src/pxar/metadata.rs b/pbs-client/src/pxar/metadata.rs
> index 22bc5f9d..3195fb03 100644
> --- a/pbs-client/src/pxar/metadata.rs
> +++ b/pbs-client/src/pxar/metadata.rs
> @@ -100,27 +100,17 @@ pub fn apply(
> on_error: &mut (dyn FnMut(Error) -> Result<(), Error> + Send),
> ) -> Result<(), Error> {
> let c_proc_path = CString::new(format!("/proc/self/fd/{}", fd)).unwrap();
> + apply_ownership(flags, c_proc_path.as_ptr(), metadata, &mut *on_error)?;
>
> - unsafe {
> - // UID and GID first, as this fails if we lose access anyway.
> - c_result!(libc::chown(
> - c_proc_path.as_ptr(),
> - metadata.stat.uid,
> - metadata.stat.gid
> - ))
> - .map(drop)
> - .or_else(allow_notsupp)
> - .map_err(|err| format_err!("failed to set ownership: {}", err))
> - .or_else(&mut *on_error)?;
> - }
> -
> - let mut skip_xattrs = false;
> + let mut skip_xattrs = !flags.contains(Flags::WITH_XATTRS);
> apply_xattrs(flags, c_proc_path.as_ptr(), metadata, &mut skip_xattrs)
> .or_else(&mut *on_error)?;
> add_fcaps(flags, c_proc_path.as_ptr(), metadata, &mut skip_xattrs).or_else(&mut *on_error)?;
> - apply_acls(flags, &c_proc_path, metadata, path_info)
> - .map_err(|err| format_err!("failed to apply acls: {}", err))
> - .or_else(&mut *on_error)?;
> + if flags.contains(Flags::WITH_ACL) {
> + apply_acls(flags, &c_proc_path, metadata, path_info)
> + .map_err(|err| format_err!("failed to apply acls: {}", err))
> + .or_else(&mut *on_error)?;
> + }
> apply_quota_project_id(flags, fd, metadata).or_else(&mut *on_error)?;
>
> // Finally mode and time. We may lose access with mode, but the changing the mode also
> @@ -162,6 +152,30 @@ pub fn apply(
> Ok(())
> }
>
> +pub fn apply_ownership(
> + flags: Flags,
> + c_proc_path: *const libc::c_char,
> + metadata: &Metadata,
> + on_error: &mut (dyn FnMut(Error) -> Result<(), Error> + Send),
> +) -> Result<(), Error> {
> + if !flags.contains(Flags::WITH_PERMISSIONS) {
> + return Ok(());
> + }
While we're at it, I think we should rename `WITH_PERMISSIONS` to
`WITH_OWNER`, as it doesn't affect permissions ;-)
We could mask the chmod call in metadata::apply with this instead and
have both flags separately?
But I'd like to get rid fo this confusion in the code :-)
> + unsafe {
> + // UID and GID first, as this fails if we lose access anyway.
> + c_result!(libc::chown(
> + c_proc_path,
> + metadata.stat.uid,
> + metadata.stat.gid
> + ))
> + .map(drop)
> + .or_else(allow_notsupp)
> + .map_err(|err| format_err!("failed to set ownership: {}", err))
> + .or_else(&mut *on_error)?;
> + }
> + Ok(())
> +}
> +
> fn add_fcaps(
> flags: Flags,
> c_proc_path: *const libc::c_char,
> --
> 2.30.2
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2022-08-17 7:37 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-16 9:19 [pbs-devel] [PATCH proxmox-backup 0/3] pbs-client feature #3923 Markus Frank
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 1/3] added overwrite-existing-files as Markus Frank
2022-08-16 9:48 ` Markus Frank
2022-08-17 7:31 ` Wolfgang Bumiller
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 2/3] skip xattr/acl/ownership options Markus Frank
2022-08-17 7:36 ` Wolfgang Bumiller
2022-08-16 9:19 ` [pbs-devel] [PATCH proxmox-backup 3/3] added ignore-acl/xattr/ownership & overwrite parameter to proxmox-backup-client Markus Frank
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox