pxar: implement allow_existing_dirs for pxar decoder
By default, restoring an archive will fail if files with the same filename already exist in the target directory. By setting the allow_existing_dirs flag, the restore will not fail if an existing directory is encountered. The metadata (permissions, acls, ...) of the existing directory will be set to the ones from the archive. Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
parent
46d5aa0a09
commit
6a87910949
|
@ -739,10 +739,6 @@ fn restore(
|
||||||
|
|
||||||
if let Some(target) = target {
|
if let Some(target) = target {
|
||||||
|
|
||||||
if allow_existing_dirs {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
let feature_flags = pxar::CA_FORMAT_DEFAULT;
|
let feature_flags = pxar::CA_FORMAT_DEFAULT;
|
||||||
let mut decoder = pxar::SequentialDecoder::new(&mut reader, feature_flags, |path| {
|
let mut decoder = pxar::SequentialDecoder::new(&mut reader, feature_flags, |path| {
|
||||||
if verbose {
|
if verbose {
|
||||||
|
@ -750,6 +746,8 @@ fn restore(
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
decoder.set_allow_existing_dirs(allow_existing_dirs);
|
||||||
|
|
||||||
|
|
||||||
decoder.restore(Path::new(target), &Vec::new())?;
|
decoder.restore(Path::new(target), &Vec::new())?;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -64,6 +64,7 @@ fn extract_archive_from_reader<R: std::io::Read>(
|
||||||
reader: &mut R,
|
reader: &mut R,
|
||||||
target: &str,
|
target: &str,
|
||||||
feature_flags: u64,
|
feature_flags: u64,
|
||||||
|
allow_existing_dirs: bool,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
pattern: Option<Vec<pxar::PxarExcludePattern>>
|
pattern: Option<Vec<pxar::PxarExcludePattern>>
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
@ -73,6 +74,7 @@ fn extract_archive_from_reader<R: std::io::Read>(
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
decoder.set_allow_existing_dirs(allow_existing_dirs);
|
||||||
|
|
||||||
let pattern = pattern.unwrap_or(Vec::new());
|
let pattern = pattern.unwrap_or(Vec::new());
|
||||||
decoder.restore(Path::new(target), &pattern)?;
|
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_xattrs = param["no-xattrs"].as_bool().unwrap_or(false);
|
||||||
let no_fcaps = param["no-fcaps"].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 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 files_from = param["files-from"].as_str();
|
||||||
let empty = Vec::new();
|
let empty = Vec::new();
|
||||||
let arg_pattern = param["pattern"].as_array().unwrap_or(&empty);
|
let arg_pattern = param["pattern"].as_array().unwrap_or(&empty);
|
||||||
|
@ -131,12 +134,12 @@ fn extract_archive(
|
||||||
if archive == "-" {
|
if archive == "-" {
|
||||||
let stdin = std::io::stdin();
|
let stdin = std::io::stdin();
|
||||||
let mut reader = stdin.lock();
|
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 {
|
} else {
|
||||||
if verbose { println!("PXAR extract: {}", archive); }
|
if verbose { println!("PXAR extract: {}", archive); }
|
||||||
let file = std::fs::File::open(archive)?;
|
let file = std::fs::File::open(archive)?;
|
||||||
let mut reader = std::io::BufReader::new(file);
|
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)
|
Ok(Value::Null)
|
||||||
|
@ -224,6 +227,7 @@ fn main() {
|
||||||
.optional("no-xattrs", BooleanSchema::new("Ignore extended file attributes.").default(false))
|
.optional("no-xattrs", BooleanSchema::new("Ignore extended file attributes.").default(false))
|
||||||
.optional("no-fcaps", BooleanSchema::new("Ignore file capabilities.").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("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."))
|
.optional("files-from", StringSchema::new("Match pattern for files to restore."))
|
||||||
))
|
))
|
||||||
.arg_param(vec!["archive", "pattern"])
|
.arg_param(vec!["archive", "pattern"])
|
||||||
|
|
|
@ -34,6 +34,7 @@ use crate::tools::xattr;
|
||||||
pub struct SequentialDecoder<'a, R: Read, F: Fn(&Path) -> Result<(), Error>> {
|
pub struct SequentialDecoder<'a, R: Read, F: Fn(&Path) -> Result<(), Error>> {
|
||||||
reader: &'a mut R,
|
reader: &'a mut R,
|
||||||
feature_flags: u64,
|
feature_flags: u64,
|
||||||
|
allow_existing_dirs: bool,
|
||||||
skip_buffer: Vec<u8>,
|
skip_buffer: Vec<u8>,
|
||||||
callback: F,
|
callback: F,
|
||||||
}
|
}
|
||||||
|
@ -48,11 +49,16 @@ impl <'a, R: Read, F: Fn(&Path) -> Result<(), Error>> SequentialDecoder<'a, R, F
|
||||||
Self {
|
Self {
|
||||||
reader,
|
reader,
|
||||||
feature_flags,
|
feature_flags,
|
||||||
|
allow_existing_dirs: false,
|
||||||
skip_buffer,
|
skip_buffer,
|
||||||
callback,
|
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 {
|
pub (crate) fn get_reader_mut(&mut self) -> & mut R {
|
||||||
self.reader
|
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() {
|
let dir = if filename.is_empty() {
|
||||||
nix::dir::Dir::openat(pfd, ".", OFlag::O_DIRECTORY, Mode::empty())?
|
nix::dir::Dir::openat(pfd, ".", OFlag::O_DIRECTORY, Mode::empty())?
|
||||||
} else {
|
} 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))?
|
.map_err(|err| format_err!("unable to open directory {:?} - {}", full_path, err))?
|
||||||
};
|
};
|
||||||
(Some(dir.as_raw_fd()), Some(dir))
|
(Some(dir.as_raw_fd()), Some(dir))
|
||||||
|
|
Loading…
Reference in New Issue