From 9b38443314e4d7c243fb079b69114b8539e1d984 Mon Sep 17 00:00:00 2001 From: Christian Ebner Date: Tue, 28 May 2019 11:16:21 +0200 Subject: [PATCH] pxar: change logic and impl all command line flags for xattrs/fcaps/acls Allows to individually set the flags for storing/dumping/restoring of xattrs/fcaps/acls in the cli of pxar. Changes logic so that each of them can be threated individually. Signed-off-by: Christian Ebner --- src/bin/pxar.rs | 27 +++++++++++++-- src/pxar/encoder.rs | 20 +++++++---- src/pxar/sequential_decoder.rs | 62 +++++++++++++++++++++++++++------- 3 files changed, 88 insertions(+), 21 deletions(-) diff --git a/src/bin/pxar.rs b/src/bin/pxar.rs index 0ed66ab8..4675ca1f 100644 --- a/src/bin/pxar.rs +++ b/src/bin/pxar.rs @@ -48,13 +48,23 @@ fn dump_archive( ) -> Result { let archive = tools::required_string_param(¶m, "archive")?; + let with_xattrs = param["with-xattrs"].as_bool().unwrap_or(false); + let with_fcaps = param["with-fcaps"].as_bool().unwrap_or(false); + let with_acls = param["with-acls"].as_bool().unwrap_or(false); let file = std::fs::File::open(archive)?; let mut reader = std::io::BufReader::new(file); let mut feature_flags = pxar::CA_FORMAT_DEFAULT; - feature_flags ^= pxar::CA_FORMAT_WITH_XATTRS; - feature_flags ^= pxar::CA_FORMAT_WITH_FCAPS; + if !with_xattrs { + feature_flags ^= pxar::CA_FORMAT_WITH_XATTRS; + } + if !with_fcaps { + feature_flags ^= pxar::CA_FORMAT_WITH_FCAPS; + } + if !with_acls { + feature_flags ^= pxar::CA_FORMAT_WITH_ACL; + } let mut decoder = pxar::SequentialDecoder::new(&mut reader, feature_flags); let stdout = std::io::stdout(); @@ -79,6 +89,7 @@ fn extract_archive( let verbose = param["verbose"].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_acls = param["no-acls"].as_bool().unwrap_or(false); let file = std::fs::File::open(archive)?; @@ -90,6 +101,9 @@ fn extract_archive( if no_fcaps { feature_flags ^= pxar::CA_FORMAT_WITH_FCAPS; } + if no_acls { + feature_flags ^= pxar::CA_FORMAT_WITH_ACL; + } let mut decoder = pxar::SequentialDecoder::new(&mut reader, feature_flags); @@ -115,6 +129,7 @@ fn create_archive( let all_file_systems = param["all-file-systems"].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_acls = param["no-acls"].as_bool().unwrap_or(false); let source = PathBuf::from(source); @@ -135,6 +150,9 @@ fn create_archive( if no_fcaps { feature_flags ^= pxar::CA_FORMAT_WITH_FCAPS; } + if no_acls { + feature_flags ^= pxar::CA_FORMAT_WITH_ACL; + } pxar::Encoder::encode(source, &mut dir, &mut writer, all_file_systems, verbose, feature_flags)?; @@ -155,6 +173,7 @@ fn main() { .optional("verbose", BooleanSchema::new("Verbose output.").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-acls", BooleanSchema::new("Ignore access control list entries.").default(false)) .optional("all-file-systems", BooleanSchema::new("Include mounted sudirs.").default(false)) )) .arg_param(vec!["archive", "source"]) @@ -171,6 +190,7 @@ fn main() { .optional("verbose", BooleanSchema::new("Verbose output.").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-acls", BooleanSchema::new("Ignore access control list entries.").default(false)) )) .arg_param(vec!["archive", "target"]) .completion_cb("archive", tools::complete_file_name) @@ -192,6 +212,9 @@ fn main() { dump_archive, ObjectSchema::new("Textual dump of archive contents (debug toolkit).") .required("archive", StringSchema::new("Archive name.")) + .optional("with-xattrs", BooleanSchema::new("Dump extended file attributes.").default(false)) + .optional("with-fcaps", BooleanSchema::new("Dump file capabilities.").default(false)) + .optional("with-acls", BooleanSchema::new("Dump access control list entries.").default(false)) )) .arg_param(vec!["archive"]) .completion_cb("archive", tools::complete_file_name) diff --git a/src/pxar/encoder.rs b/src/pxar/encoder.rs index b8552399..c40209cf 100644 --- a/src/pxar/encoder.rs +++ b/src/pxar/encoder.rs @@ -220,16 +220,22 @@ impl <'a, W: Write> Encoder<'a, W> { Ok(()) } + /// True if all of the given feature flags are set in the Encoder, false otherwise fn has_features(&self, feature_flags: u64) -> bool { (self.feature_flags & feature_flags) == feature_flags } + /// True if at least one of the given feature flags is set in the Encoder, false otherwise + fn has_some_features(&self, feature_flags: u64) -> bool { + (self.feature_flags & feature_flags) != 0 + } + fn read_xattrs(&self, fd: RawFd, stat: &FileStat) -> Result<(Vec, Option), Error> { let mut xattrs = Vec::new(); let mut fcaps = None; let flags = CA_FORMAT_WITH_XATTRS | CA_FORMAT_WITH_FCAPS; - if !self.has_features(flags) { + if !self.has_some_features(flags) { return Ok((xattrs, fcaps)); } // Should never be called on symlinks, just in case check anyway @@ -260,11 +266,13 @@ impl <'a, W: Write> Encoder<'a, W> { }; if xattr::is_security_capability(&name) { - // fcaps are stored in own format within the archive - fcaps = Some(CaFormatFCaps { - data: value, - }); - } else { + if self.has_features(CA_FORMAT_WITH_FCAPS) { + // fcaps are stored in own format within the archive + fcaps = Some(CaFormatFCaps { + data: value, + }); + } + } else if self.has_features(CA_FORMAT_WITH_XATTRS) { xattrs.push(CaFormatXAttr { name: name.to_vec(), value: value, diff --git a/src/pxar/sequential_decoder.rs b/src/pxar/sequential_decoder.rs index dbe99837..49e210b4 100644 --- a/src/pxar/sequential_decoder.rs +++ b/src/pxar/sequential_decoder.rs @@ -778,20 +778,56 @@ impl <'a, R: Read> SequentialDecoder<'a, R> { } fn dump_if_attribute(&mut self, header: &CaFormatHeader, verbose: bool) -> Result { - let dump_string = match header.htype { - CA_FORMAT_XATTR => format!("XAttr: {:?}", self.read_xattr((header.size - HEADER_SIZE) as usize)?), - CA_FORMAT_FCAPS => format!("FCaps: {:?}", self.read_fcaps((header.size - HEADER_SIZE) as usize)?), - CA_FORMAT_ACL_USER => format!("ACLUser: {:?}", self.read_item::()?), - CA_FORMAT_ACL_GROUP => format!("ACLGroup: {:?}", self.read_item::()?), - CA_FORMAT_ACL_GROUP_OBJ => format!("ACLGroupObj: {:?}", self.read_item::()?), - CA_FORMAT_ACL_DEFAULT => format!("ACLDefault: {:?}", self.read_item::()?), - CA_FORMAT_ACL_DEFAULT_USER => format!("ACLDefaultUser: {:?}", self.read_item::()?), - CA_FORMAT_ACL_DEFAULT_GROUP => format!("ACLDefaultGroup: {:?}", self.read_item::()?), + match header.htype { + CA_FORMAT_XATTR => { + let xattr = self.read_xattr((header.size - HEADER_SIZE) as usize)?; + if verbose && self.has_features(CA_FORMAT_WITH_XATTRS) { + println!("XAttr: {:?}", xattr); + } + }, + CA_FORMAT_FCAPS => { + let fcaps = self.read_fcaps((header.size - HEADER_SIZE) as usize)?; + if verbose && self.has_features(CA_FORMAT_WITH_FCAPS) { + println!("FCaps: {:?}", fcaps); + } + }, + CA_FORMAT_ACL_USER => { + let user = self.read_item::()?; + if verbose && self.has_features(CA_FORMAT_WITH_ACL) { + println!("ACLUser: {:?}", user); + } + }, + CA_FORMAT_ACL_GROUP => { + let group = self.read_item::()?; + if verbose && self.has_features(CA_FORMAT_WITH_ACL) { + println!("ACLGroup: {:?}", group); + } + }, + CA_FORMAT_ACL_GROUP_OBJ => { + let group_obj = self.read_item::()?; + if verbose && self.has_features(CA_FORMAT_WITH_ACL) { + println!("ACLGroupObj: {:?}", group_obj); + } + }, + CA_FORMAT_ACL_DEFAULT => { + let default = self.read_item::()?; + if verbose && self.has_features(CA_FORMAT_WITH_ACL) { + println!("ACLDefault: {:?}", default); + } + }, + CA_FORMAT_ACL_DEFAULT_USER => { + let default_user = self.read_item::()?; + if verbose && self.has_features(CA_FORMAT_WITH_ACL) { + println!("ACLDefaultUser: {:?}", default_user); + } + }, + CA_FORMAT_ACL_DEFAULT_GROUP => { + let default_group = self.read_item::()?; + if verbose && self.has_features(CA_FORMAT_WITH_ACL) { + println!("ACLDefaultGroup: {:?}", default_group); + } + }, _ => return Ok(false), - }; - let flags = CA_FORMAT_WITH_XATTRS | CA_FORMAT_WITH_FCAPS | CA_FORMAT_WITH_ACL; - if verbose && self.has_features(flags) { - println!("{}", dump_string); } Ok(true)