From e0f4f30933a7b0bcf0c8c6d39c3a990bffe2bc27 Mon Sep 17 00:00:00 2001 From: Dennis Schwerdel Date: Sun, 16 Apr 2017 19:26:15 +0200 Subject: [PATCH] moved pax extension code out --- src/repository/metadata.rs | 2 +- src/repository/tarfile.rs | 61 +++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/repository/metadata.rs b/src/repository/metadata.rs index 058ecea..5e5b54e 100644 --- a/src/repository/metadata.rs +++ b/src/repository/metadata.rs @@ -171,7 +171,7 @@ impl Inode { if meta.file_type().is_symlink() { inode.symlink_target = Some(try!(fs::read_link(path).map_err(|e| InodeError::ReadLinkTarget(e, path.to_owned()))).to_string_lossy().to_string()); } - inode.mode = meta.st_mode() & 0o7777; + inode.mode = meta.permissions().mode(); inode.user = meta.st_uid(); inode.group = meta.st_gid(); inode.timestamp = meta.st_mtime(); diff --git a/src/repository/tarfile.rs b/src/repository/tarfile.rs index 9975537..85faddd 100644 --- a/src/repository/tarfile.rs +++ b/src/repository/tarfile.rs @@ -11,6 +11,46 @@ use chrono::prelude::*; use tar; +struct PaxBuilder(Vec); + +impl PaxBuilder { + pub fn new() -> Self { + PaxBuilder(Vec::new()) + } + + pub fn add(&mut self, key: &str, value: &str) { + let mut len_len = 1; + let mut max_len = 10; + let rest_len = 3 + key.len() + value.len(); + while rest_len + len_len >= max_len { + len_len += 1; + max_len *= 10; + } + let len = rest_len + len_len; + write!(&mut self.0, "{} {}={}\n", len, key, value).unwrap(); + } + + fn as_bytes(&self) -> &[u8] { + &self.0 + } +} + + +trait BuilderExt { + fn append_pax_extensions(&mut self, headers: &PaxBuilder) -> Result<(), io::Error>; +} + +impl BuilderExt for tar::Builder { + fn append_pax_extensions(&mut self, headers: &PaxBuilder) -> Result<(), io::Error> { + let mut header = tar::Header::new_ustar(); + header.set_size(headers.as_bytes().len() as u64); + header.set_entry_type(tar::EntryType::XHeader); + header.set_cksum(); + self.append(&header, headers.as_bytes()) + } +} + + static PAX_XATTR_PREFIX: &'static str = "SCHILY.xattr."; fn inode_from_entry(entry: &mut tar::Entry) -> Result { @@ -214,26 +254,11 @@ impl Repository { } fn export_xattrs(&mut self, inode: &Inode, tarfile: &mut tar::Builder) -> Result<(), RepositoryError> { - let mut data = Vec::new(); + let mut pax = PaxBuilder::new(); for (key, value) in &inode.xattrs { - let mut len_len = 1; - let mut max_len = 10; - let rest_len = 3 + key.len() + value.len() + PAX_XATTR_PREFIX.len(); - while rest_len + len_len >= max_len { - len_len += 1; - max_len *= 10; - } - let len = rest_len + len_len; - let value = str::from_utf8(value).unwrap(); - let line = format!("{} {}{}={}\n", len, PAX_XATTR_PREFIX, key, value); - assert_eq!(line.len(), len); - data.extend_from_slice(line.as_bytes()); + pax.add(&format!("{}{}", PAX_XATTR_PREFIX,key), str::from_utf8(value).unwrap()); } - let mut header = tar::Header::new_ustar(); - header.set_size(data.len() as u64); - header.set_entry_type(tar::EntryType::XHeader); - header.set_cksum(); - Ok(try!(tarfile.append(&header, Cursor::new(&data)))) + Ok(try!(tarfile.append_pax_extensions(&pax))) } fn export_tarfile_recurse(&mut self, backup: &Backup, path: &Path, inode: Inode, tarfile: &mut tar::Builder) -> Result<(), RepositoryError> {