]> git.proxmox.com Git - proxmox-backup.git/commitdiff
pxar: .pxarexclude: absolute paths and byte based paths
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 15 Jul 2020 09:53:26 +0000 (11:53 +0200)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 15 Jul 2020 09:55:48 +0000 (11:55 +0200)
Change the .pxarexclude parser to byte based parsing with
`.split(b'\n')` instead of `.lines()`, to not panic on
non-utf8 paths.

Specially deal with absolute paths by prefixing them with
the current directory.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
src/pxar/create.rs

index b13ff40386a4ad8a13fd44cb14799a92d6b89b9c..f083152647b8cdbd4da595b69fb2883b01087614 100644 (file)
@@ -290,11 +290,13 @@ impl<'a, 'b> Archiver<'a, 'b> {
 
         let old_pattern_count = self.patterns.len();
 
+        let path_bytes = self.path.as_os_str().as_bytes();
+
         if let Some(fd) = fd {
             let file = unsafe { std::fs::File::from_raw_fd(fd.into_raw_fd()) };
 
             use io::BufRead;
-            for line in io::BufReader::new(file).lines() {
+            for line in io::BufReader::new(file).split(b'\n') {
                 let line = match line {
                     Ok(line) => line,
                     Err(err) => {
@@ -309,13 +311,29 @@ impl<'a, 'b> Archiver<'a, 'b> {
                     }
                 };
 
-                let line = line.trim();
+                let line = crate::tools::strip_ascii_whitespace(&line);
 
-                if line.is_empty() || line.starts_with('#') {
+                if line.is_empty() || line[0] == b'#' {
                     continue;
                 }
 
-                match MatchEntry::parse_pattern(line, PatternFlag::PATH_NAME, MatchType::Exclude) {
+                let mut buf;
+                let (line, mode) = if line[0] == b'/' {
+                    buf = Vec::with_capacity(path_bytes.len() + 1 + line.len());
+                    buf.extend(path_bytes);
+                    buf.extend(line);
+                    (&buf[..], MatchType::Exclude)
+                } else if line.starts_with(b"!/") {
+                    // inverted case with absolute path
+                    buf = Vec::with_capacity(path_bytes.len() + line.len());
+                    buf.extend(path_bytes);
+                    buf.extend(&line[1..]); // without the '!'
+                    (&buf[..], MatchType::Include)
+                } else {
+                    (line, MatchType::Exclude)
+                };
+
+                match MatchEntry::parse_pattern(line, PatternFlag::PATH_NAME, mode) {
                     Ok(pattern) => self.patterns.push(pattern),
                     Err(err) => {
                         let _ = writeln!(self.errors, "bad pattern in {:?}: {}", self.path, err);