diff --git a/TODO.rst b/TODO.rst index 8c102666..33fef3c9 100644 --- a/TODO.rst +++ b/TODO.rst @@ -1,8 +1,6 @@ TODO list for Proxmox Backup ============================ -* do not abort host backups on file permission errors - * proxmox-backup-client: verify server cert (save/compare last saved cert fingerprint) Suggestions diff --git a/src/pxar/encoder.rs b/src/pxar/encoder.rs index 05641fac..05747e6d 100644 --- a/src/pxar/encoder.rs +++ b/src/pxar/encoder.rs @@ -697,6 +697,14 @@ impl<'a, W: Write, C: BackupCatalogWriter> Encoder<'a, W, C> { (Some((buffer, stat)), excludes) } Ok(None) => (None, Vec::new()), + Err(nix::Error::Sys(Errno::EACCES)) => { + // No permission to read .pxarexclude, ignore its contents. + eprintln!( + "ignoring match patterns in {:?}: open file failed - EACCES", + self.full_path().join(".pxarexclude"), + ); + (None, Vec::new()) + } Err(err) => bail!("error while reading exclude file - {}", err), }; for excl in &excludes { @@ -777,6 +785,7 @@ impl<'a, W: Write, C: BackupCatalogWriter> Encoder<'a, W, C> { let start_pos = self.writer_pos; if filename.as_bytes() == b".pxarexclude" { + // pxar_exclude is none in case of error EACCES. if let Some((ref content, ref stat)) = pxar_exclude { let filefd = match nix::fcntl::openat( rawfd, @@ -789,6 +798,14 @@ impl<'a, W: Write, C: BackupCatalogWriter> Encoder<'a, W, C> { self.report_vanished_file(&self.full_path())?; continue; } + Err(nix::Error::Sys(Errno::EACCES)) => { + let filename_osstr = std::ffi::OsStr::from_bytes(filename.to_bytes()); + eprintln!( + "skipping {:?}: open file failed - EACCES", + self.full_path().join(filename_osstr), + ); + continue; + } Err(err) => { let filename_osstr = std::ffi::OsStr::from_bytes(filename.to_bytes()); bail!( @@ -810,8 +827,8 @@ impl<'a, W: Write, C: BackupCatalogWriter> Encoder<'a, W, C> { catalog.add_file(&filename, stat.st_size as u64, stat.st_mtime as u64)?; } self.encode_pxar_exclude(filefd, stat, child_magic, content)?; - continue; } + continue; } if is_root && filename.as_bytes() == b".pxarexclude-cli" { @@ -846,6 +863,14 @@ impl<'a, W: Write, C: BackupCatalogWriter> Encoder<'a, W, C> { self.relative_path.pop(); continue; } + Err(nix::Error::Sys(Errno::EACCES)) => { + eprintln!( + "skipping {:?}: open dir failed - EACCES", + self.full_path(), + ); + self.relative_path.pop(); + continue; + } Err(err) => bail!("open dir {:?} failed - {}", self.full_path(), err), }; @@ -901,6 +926,14 @@ impl<'a, W: Write, C: BackupCatalogWriter> Encoder<'a, W, C> { self.relative_path.pop(); continue; } + Err(nix::Error::Sys(Errno::EACCES)) => { + eprintln!( + "skipping {:?}: open file failed - EACCES", + self.full_path(), + ); + self.relative_path.pop(); + continue; + } Err(err) => bail!("open file {:?} failed - {}", self.full_path(), err), }; diff --git a/src/pxar/match_pattern.rs b/src/pxar/match_pattern.rs index d4424264..066b876d 100644 --- a/src/pxar/match_pattern.rs +++ b/src/pxar/match_pattern.rs @@ -97,18 +97,19 @@ impl MatchPattern { pub fn from_file( parent_fd: RawFd, filename: &P, - ) -> Result, Vec, FileStat)>, Error> { + ) -> Result, Vec, FileStat)>, nix::Error> { let stat = match stat::fstatat(parent_fd, filename, AtFlags::AT_SYMLINK_NOFOLLOW) { Ok(stat) => stat, Err(nix::Error::Sys(Errno::ENOENT)) => return Ok(None), - Err(err) => bail!("stat failed - {}", err), + Err(err) => return Err(err), }; let filefd = fcntl::openat(parent_fd, filename, OFlag::O_NOFOLLOW, Mode::empty())?; let mut file = unsafe { File::from_raw_fd(filefd) }; let mut content_buffer = Vec::new(); - let _bytes = file.read_to_end(&mut content_buffer)?; + let _bytes = file.read_to_end(&mut content_buffer) + .map_err(|_| Errno::EIO)?; let mut match_pattern = Vec::new(); for line in content_buffer.split(|&c| c == b'\n') { @@ -129,8 +130,8 @@ impl MatchPattern { /// Pattern starting with '!' are interpreted as negative match pattern. /// Pattern with trailing `/` match only against directories. /// `.` as well as `..` and any pattern containing `\0` are invalid and will - /// result in an error. - pub fn from_line(line: &[u8]) -> Result, Error> { + /// result in an error with Errno::EINVAL. + pub fn from_line(line: &[u8]) -> Result, nix::Error> { let mut input = line; if input.starts_with(b"#") { @@ -160,7 +161,7 @@ impl MatchPattern { } if input.is_empty() || input == b"." || input == b".." || input.contains(&b'\0') { - bail!("invalid path component encountered"); + return Err(nix::Error::Sys(Errno::EINVAL)); } Ok(Some(MatchPattern {