[pbs-devel] [PATCH proxmox-backup v4] fix #4380: check if file is excluded before running `stat()`
Gabriel Goller
g.goller at proxmox.com
Wed Aug 16 16:03:30 CEST 2023
Passed a closure with the `stat()` function call to `match_mode_lazy()`. This
will traverse through all patterns and try to match using the path only, if a
`file_mode` is needed, it will run the closure. This means that if we exclude
a file with the `MatchType::ANY_FILE_TYPE`, we will skip it without running
`stat()` on it.
Added `pathpatterns` crate to local overrides in cargo.toml.
Signed-off-by: Gabriel Goller <g.goller at proxmox.com>
---
changes v3:
- match only by path and exclude the matched files, the run `stat()` and
match again, this time using the `file_mode`. This will match everything
twice in the worst case, which is not optimal.
changes v2:
- checking for `read` and `execute` permissions before entering directory,
doesn't work because there are a lot of side-effects (executed by
different user, AppArmor, SELinux, ...).
changes v1:
- checking for excluded files with `matches()` before executing `stat()`,
this doesn't work because we get the file_mode from `stat()` and don't
want to ignore it when matching.
Cargo.toml | 1 +
pbs-client/src/pxar/create.rs | 68 +++++++++++++++++++++++++----------
2 files changed, 50 insertions(+), 19 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index 2a05c471..c54bc28b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -262,6 +262,7 @@ proxmox-rrd.workspace = true
#proxmox-apt = { path = "../proxmox-apt" }
#proxmox-openid = { path = "../proxmox-openid-rs" }
+#pathpatterns = {path = "../pathpatterns" }
#pxar = { path = "../pxar" }
diff --git a/pbs-client/src/pxar/create.rs b/pbs-client/src/pxar/create.rs
index 2577cf98..7027a7d2 100644
--- a/pbs-client/src/pxar/create.rs
+++ b/pbs-client/src/pxar/create.rs
@@ -21,7 +21,6 @@ use pxar::Metadata;
use proxmox_io::vec;
use proxmox_lang::c_str;
-use proxmox_sys::error::SysError;
use proxmox_sys::fs::{self, acl, xattr};
use pbs_datastore::catalog::BackupCatalogWriter;
@@ -420,7 +419,7 @@ impl Archiver {
for file in dir.iter() {
let file = file?;
- let file_name = file.file_name().to_owned();
+ let file_name = file.file_name();
let file_name_bytes = file_name.to_bytes();
if file_name_bytes == b"." || file_name_bytes == b".." {
continue;
@@ -434,25 +433,56 @@ impl Archiver {
assert_single_path_component(os_file_name)?;
let full_path = self.path.join(os_file_name);
- let stat = match nix::sys::stat::fstatat(
- dir_fd,
- file_name.as_c_str(),
- nix::fcntl::AtFlags::AT_SYMLINK_NOFOLLOW,
- ) {
- Ok(stat) => stat,
- Err(ref err) if err.not_found() => continue,
- Err(err) => return Err(err).context(format!("stat failed on {:?}", full_path)),
- };
-
let match_path = PathBuf::from("/").join(full_path.clone());
- if self
- .patterns
- .matches(match_path.as_os_str().as_bytes(), Some(stat.st_mode))
- == Some(MatchType::Exclude)
- {
+
+ let mut stat_results: Option<FileStat> = None;
+
+ let stat =
+ self.patterns
+ .matches_mode_lazy(match_path.as_os_str().as_bytes(), || {
+ match nix::sys::stat::fstatat(
+ dir_fd,
+ file_name.to_owned().as_c_str(),
+ nix::fcntl::AtFlags::AT_SYMLINK_NOFOLLOW,
+ ) {
+ Ok(stat) => {
+ stat_results = Some(stat);
+ Ok(stat.st_mode)
+ }
+ Err(e) => Err(e),
+ }
+ })
+ .map_err(|err| {
+ anyhow::Error::new(err).context(format!(
+ "stat failed on {:?} with {:?}",
+ full_path,
+ err.desc()
+ ))
+ })?;
+
+ if stat == Some(MatchType::Exclude) {
continue;
}
+ if stat_results.is_none() {
+ match nix::sys::stat::fstatat(
+ dir_fd,
+ file_name.to_owned().as_c_str(),
+ nix::fcntl::AtFlags::AT_SYMLINK_NOFOLLOW,
+ ) {
+ Ok(stat) => {
+ stat_results = Some(stat);
+ }
+ Err(err) => {
+ return Err(err).context(format!(
+ "stat failed on {:?} with {:?}",
+ full_path,
+ err.desc()
+ ));
+ }
+ }
+ }
+
self.entry_counter += 1;
if self.entry_counter > self.entry_limit {
bail!(
@@ -462,9 +492,9 @@ impl Archiver {
}
file_list.push(FileListEntry {
- name: file_name,
+ name: file_name.to_owned(),
path: full_path,
- stat,
+ stat: stat_results.unwrap(),
});
}
--
2.39.2
More information about the pbs-devel
mailing list