src/bin/pxar.rs: allow to pass paths and match patterns as args to pxar extract
To improve usability it is now possible to directly pass paths or match patterns as arguments to pxar extract to partially restore an archive. The patterns provided via CLI are appended to the ones read from file by the --files-from option in order to have priority over those. Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
parent
9aa3f68278
commit
a0ec687cd7
|
@ -12,6 +12,7 @@ use serde_json::{Value};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::os::unix::fs::OpenOptionsExt;
|
use std::os::unix::fs::OpenOptionsExt;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
|
||||||
|
@ -91,6 +92,8 @@ fn extract_archive(
|
||||||
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 files_from = param["files-from"].as_str();
|
let files_from = param["files-from"].as_str();
|
||||||
|
let empty = Vec::new();
|
||||||
|
let arg_pattern = param["pattern"].as_array().unwrap_or(&empty);
|
||||||
|
|
||||||
let mut feature_flags = pxar::CA_FORMAT_DEFAULT;
|
let mut feature_flags = pxar::CA_FORMAT_DEFAULT;
|
||||||
if no_xattrs {
|
if no_xattrs {
|
||||||
|
@ -103,15 +106,25 @@ fn extract_archive(
|
||||||
feature_flags ^= pxar::CA_FORMAT_WITH_ACL;
|
feature_flags ^= pxar::CA_FORMAT_WITH_ACL;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pattern = match files_from {
|
let mut pattern_list = Vec::new();
|
||||||
Some(filename) => {
|
if let Some(filename) = files_from {
|
||||||
let dir = nix::dir::Dir::open("./", nix::fcntl::OFlag::O_RDONLY, nix::sys::stat::Mode::empty())?;
|
let dir = nix::dir::Dir::open("./", nix::fcntl::OFlag::O_RDONLY, nix::sys::stat::Mode::empty())?;
|
||||||
let fd = dir.as_raw_fd();
|
if let Some((mut pattern, _, _)) = pxar::PxarExcludePattern::from_file(dir.as_raw_fd(), filename)? {
|
||||||
|
pattern_list.append(&mut pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pxar::PxarExcludePattern::from_file(fd, filename)?
|
for s in arg_pattern {
|
||||||
.and_then(|(pattern, _, _)| Some(pattern))
|
let l = s.as_str().ok_or_else(|| format_err!("Invalid pattern string slice"))?;
|
||||||
},
|
let p = pxar::PxarExcludePattern::from_line(l.as_bytes())?
|
||||||
None => None,
|
.ok_or_else(|| format_err!("Invalid match pattern in arguments"))?;
|
||||||
|
pattern_list.push(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
let pattern = if pattern_list.len() > 0 {
|
||||||
|
Some(pattern_list)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
if archive == "-" {
|
if archive == "-" {
|
||||||
|
@ -186,25 +199,31 @@ fn main() {
|
||||||
.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("all-file-systems", BooleanSchema::new("Include mounted sudirs.").default(false))
|
.optional("all-file-systems", BooleanSchema::new("Include mounted sudirs.").default(false))
|
||||||
))
|
))
|
||||||
.arg_param(vec!["archive", "source"])
|
.arg_param(vec!["archive", "source"])
|
||||||
.completion_cb("archive", tools::complete_file_name)
|
.completion_cb("archive", tools::complete_file_name)
|
||||||
.completion_cb("source", tools::complete_file_name)
|
.completion_cb("source", tools::complete_file_name)
|
||||||
.into()
|
.into()
|
||||||
)
|
)
|
||||||
.insert("extract", CliCommand::new(
|
.insert("extract", CliCommand::new(
|
||||||
ApiMethod::new(
|
ApiMethod::new(
|
||||||
extract_archive,
|
extract_archive,
|
||||||
ObjectSchema::new("Extract an archive.")
|
ObjectSchema::new("Extract an archive.")
|
||||||
.required("archive", StringSchema::new("Archive name."))
|
.required("archive", StringSchema::new("Archive name."))
|
||||||
|
.optional("pattern", Arc::new(
|
||||||
|
ArraySchema::new(
|
||||||
|
"List of paths or pattern matching files to restore",
|
||||||
|
Arc::new(StringSchema::new("Path or pattern matching files to restore.").into())
|
||||||
|
).into()
|
||||||
|
))
|
||||||
.optional("target", StringSchema::new("Target directory."))
|
.optional("target", StringSchema::new("Target directory."))
|
||||||
.optional("verbose", BooleanSchema::new("Verbose output.").default(false))
|
.optional("verbose", BooleanSchema::new("Verbose output.").default(false))
|
||||||
.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("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"])
|
.arg_param(vec!["archive", "pattern"])
|
||||||
.completion_cb("archive", tools::complete_file_name)
|
.completion_cb("archive", tools::complete_file_name)
|
||||||
.completion_cb("target", tools::complete_file_name)
|
.completion_cb("target", tools::complete_file_name)
|
||||||
.completion_cb("files-from", tools::complete_file_name)
|
.completion_cb("files-from", tools::complete_file_name)
|
||||||
|
|
Loading…
Reference in New Issue