diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs index 1b0133bf..dc0a6f10 100644 --- a/src/bin/proxmox-backup-client.rs +++ b/src/bin/proxmox-backup-client.rs @@ -739,10 +739,6 @@ fn restore( if let Some(target) = target { - if allow_existing_dirs { - unimplemented!(); - } - let feature_flags = pxar::CA_FORMAT_DEFAULT; let mut decoder = pxar::SequentialDecoder::new(&mut reader, feature_flags, |path| { if verbose { @@ -750,6 +746,8 @@ fn restore( } Ok(()) }); + decoder.set_allow_existing_dirs(allow_existing_dirs); + decoder.restore(Path::new(target), &Vec::new())?; } else { diff --git a/src/bin/pxar.rs b/src/bin/pxar.rs index 9641b118..095a2713 100644 --- a/src/bin/pxar.rs +++ b/src/bin/pxar.rs @@ -64,6 +64,7 @@ fn extract_archive_from_reader( reader: &mut R, target: &str, feature_flags: u64, + allow_existing_dirs: bool, verbose: bool, pattern: Option> ) -> Result<(), Error> { @@ -73,6 +74,7 @@ fn extract_archive_from_reader( } Ok(()) }); + decoder.set_allow_existing_dirs(allow_existing_dirs); let pattern = pattern.unwrap_or(Vec::new()); decoder.restore(Path::new(target), &pattern)?; @@ -92,6 +94,7 @@ fn extract_archive( let no_xattrs = param["no-xattrs"].as_bool().unwrap_or(false); let no_fcaps = param["no-fcaps"].as_bool().unwrap_or(false); let no_acls = param["no-acls"].as_bool().unwrap_or(false); + let allow_existing_dirs = param["allow-existing-dirs"].as_bool().unwrap_or(false); let files_from = param["files-from"].as_str(); let empty = Vec::new(); let arg_pattern = param["pattern"].as_array().unwrap_or(&empty); @@ -131,12 +134,12 @@ fn extract_archive( if archive == "-" { let stdin = std::io::stdin(); let mut reader = stdin.lock(); - extract_archive_from_reader(&mut reader, target, feature_flags, verbose, pattern)?; + extract_archive_from_reader(&mut reader, target, feature_flags, allow_existing_dirs, verbose, pattern)?; } else { if verbose { println!("PXAR extract: {}", archive); } let file = std::fs::File::open(archive)?; let mut reader = std::io::BufReader::new(file); - extract_archive_from_reader(&mut reader, target, feature_flags, verbose, pattern)?; + extract_archive_from_reader(&mut reader, target, feature_flags, allow_existing_dirs, verbose, pattern)?; } Ok(Value::Null) @@ -224,6 +227,7 @@ fn main() { .optional("no-xattrs", BooleanSchema::new("Ignore extended file attributes.").default(false)) .optional("no-fcaps", BooleanSchema::new("Ignore file capabilities.").default(false)) .optional("no-acls", BooleanSchema::new("Ignore access control list entries.").default(false)) + .optional("allow-existing-dirs", BooleanSchema::new("Allows directories to already exist on restore.").default(false)) .optional("files-from", StringSchema::new("Match pattern for files to restore.")) )) .arg_param(vec!["archive", "pattern"]) diff --git a/src/pxar/sequential_decoder.rs b/src/pxar/sequential_decoder.rs index 79ae2d53..cdeea2c7 100644 --- a/src/pxar/sequential_decoder.rs +++ b/src/pxar/sequential_decoder.rs @@ -34,6 +34,7 @@ use crate::tools::xattr; pub struct SequentialDecoder<'a, R: Read, F: Fn(&Path) -> Result<(), Error>> { reader: &'a mut R, feature_flags: u64, + allow_existing_dirs: bool, skip_buffer: Vec, callback: F, } @@ -48,11 +49,16 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F Self { reader, feature_flags, + allow_existing_dirs: false, skip_buffer, callback, } } + pub fn set_allow_existing_dirs(&mut self, allow: bool) { + self.allow_existing_dirs = allow; + } + pub (crate) fn get_reader_mut(&mut self) -> & mut R { self.reader } @@ -632,7 +638,7 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F let dir = if filename.is_empty() { nix::dir::Dir::openat(pfd, ".", OFlag::O_DIRECTORY, Mode::empty())? } else { - dir_mkdirat(pfd, filename, true) + dir_mkdirat(pfd, filename, !self.allow_existing_dirs) .map_err(|err| format_err!("unable to open directory {:?} - {}", full_path, err))? }; (Some(dir.as_raw_fd()), Some(dir))