Browse Source

xattrs

pull/10/head
Dennis Schwerdel 5 years ago
parent
commit
1212d08917
  1. 1
      Cargo.lock
  2. 3
      Cargo.toml
  3. 2
      README.md
  4. 3
      src/cli/mod.rs
  5. 2
      src/main.rs
  6. 43
      src/repository/metadata.rs
  7. 12
      src/repository/tarfile.rs

1
Cargo.lock generated

@ -27,6 +27,7 @@ dependencies = [
"squash-sys 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tar 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
"xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]

3
Cargo.toml

@ -1,7 +1,7 @@
[package]
name = "zvault"
version = "0.1.0"
authors = ["Dennis Schwerdel <schwerdel@informatik.uni-kl.de>"]
authors = ["Dennis Schwerdel <schwerdel@googlemail.com>"]
description = "Deduplicating backup tool"
[dependencies]
@ -27,6 +27,7 @@ fuse = "0.3"
lazy_static = "0.2"
rand = "0.3"
tar = "0.4"
xattr = "0.1"
time = "*"
libc = "*"

2
README.md

@ -99,8 +99,6 @@ Recommended: Brotli/2-7
### Core functionality
- Recompress & combine bundles
- File attributes
- xattrs https://crates.io/crates/xattr
### CLI functionality
- list --tree

3
src/cli/mod.rs

@ -30,8 +30,7 @@ impl ErrorCode {
pub fn code(&self) -> i32 {
match *self {
// Crazy stuff
ErrorCode::InitializeLogger => -1,
ErrorCode::InvalidExcludes => -1,
ErrorCode::InitializeLogger | ErrorCode::InvalidExcludes => -1,
// Arguments
ErrorCode::InvalidArgs => 1,
ErrorCode::UnsafeArgs => 2,

2
src/main.rs

@ -1,4 +1,5 @@
#![recursion_limit="128"]
#![allow(unknown_lints, float_cmp)]
extern crate serde;
extern crate rmp_serde;
#[macro_use] extern crate serde_utils;
@ -21,6 +22,7 @@ extern crate regex;
extern crate fuse;
extern crate rand;
extern crate time;
extern crate xattr;
extern crate libc;
extern crate tar;

43
src/repository/metadata.rs

@ -1,6 +1,7 @@
use ::prelude::*;
use filetime::{self, FileTime};
use xattr;
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
@ -23,6 +24,11 @@ quick_error!{
description("Failed to obtain metadata for file")
display("Inode error: failed to obtain metadata for file {:?}\n\tcaused by: {}", path, err)
}
ReadXattr(err: io::Error, path: PathBuf) {
cause(err)
description("Failed to obtain xattr for file")
display("Inode error: failed to obtain xattr for file {:?}\n\tcaused by: {}", path, err)
}
ReadLinkTarget(err: io::Error, path: PathBuf) {
cause(err)
description("Failed to obtain link target for file")
@ -48,6 +54,11 @@ quick_error!{
description("Failed to set file ownership")
display("Inode error: failed to set file ownership on {:?}\n\tcaused by: {}", path, err)
}
SetXattr(err: io::Error, path: PathBuf) {
cause(err)
description("Failed to set xattr")
display("Inode error: failed to set xattr on {:?}\n\tcaused by: {}", path, err)
}
Integrity(reason: &'static str) {
description("Integrity error")
display("Inode error: inode integrity error: {}", reason)
@ -117,7 +128,8 @@ pub struct Inode {
pub children: Option<BTreeMap<String, ChunkList>>,
pub cum_size: u64,
pub cum_dirs: usize,
pub cum_files: usize
pub cum_files: usize,
pub xattrs: BTreeMap<String, msgpack::Bytes>
}
impl Default for Inode {
fn default() -> Self {
@ -134,7 +146,8 @@ impl Default for Inode {
children: None,
cum_size: 0,
cum_dirs: 0,
cum_files: 0
cum_files: 0,
xattrs: BTreeMap::new()
}
}
}
@ -145,15 +158,14 @@ serde_impl!(Inode(u8?) {
mode: u32 => 3,
user: u32 => 4,
group: u32 => 5,
//__old_access_time: i64 => 6,
timestamp: i64 => 7,
//__old_create_time: i64 => 8,
symlink_target: Option<String> => 9,
data: Option<FileData> => 10,
children: Option<BTreeMap<String, ChunkList>> => 11,
cum_size: u64 => 12,
cum_dirs: usize => 13,
cum_files: usize => 14
cum_files: usize => 14,
xattrs: BTreeMap<String, msgpack::Bytes> => 15
});
@ -183,6 +195,14 @@ impl Inode {
inode.user = meta.st_uid();
inode.group = meta.st_gid();
inode.timestamp = meta.st_mtime();
if xattr::SUPPORTED_PLATFORM {
if let Ok(attrs) = xattr::list(path) {
for name in attrs {
let data = try!(xattr::get(path, &name).map_err(|e| InodeError::ReadXattr(e, path.to_owned())));
inode.xattrs.insert(name.to_string_lossy().to_string(), data.into());
}
}
}
Ok(inode)
}
@ -205,12 +225,21 @@ impl Inode {
}
}
}
let time = FileTime::from_seconds_since_1970(self.timestamp as u64, 0);
try!(filetime::set_file_times(&full_path, time, time).map_err(|e| InodeError::SetTimes(e, full_path.clone())));
if !self.xattrs.is_empty() {
if xattr::SUPPORTED_PLATFORM {
for (name, data) in &self.xattrs {
try!(xattr::set(&full_path, name, data).map_err(|e| InodeError::SetXattr(e, full_path.clone())))
}
} else {
warn!("Not setting xattr on {:?}", full_path);
}
}
try!(fs::set_permissions(
&full_path,
Permissions::from_mode(self.mode)
).map_err(|e| InodeError::SetPermissions(e, full_path.clone(), self.mode)));
let time = FileTime::from_seconds_since_1970(self.timestamp as u64, 0);
try!(filetime::set_file_times(&full_path, time, time).map_err(|e| InodeError::SetTimes(e, full_path.clone())));
try!(chown(&full_path, self.user, self.group).map_err(|e| InodeError::SetOwnership(e, full_path.clone())));
Ok(file)
}

12
src/repository/tarfile.rs

@ -113,15 +113,11 @@ impl Repository {
roots.push((inode, chunks));
}
}
let mut root_inode;
let chunks;
if roots.len() == 1 {
let r = roots.pop().unwrap();
root_inode = r.0;
chunks = r.1;
Ok(roots.pop().unwrap())
} else {
warn!("Tar file contains multiple roots, adding dummy folder");
root_inode = Inode {
let mut root_inode = Inode {
file_type: FileType::Directory,
mode: 0o755,
name: "archive".to_string(),
@ -138,9 +134,9 @@ impl Repository {
root_inode.cum_dirs += inode.cum_dirs;
}
root_inode.children = Some(children);
chunks = try!(self.put_inode(&root_inode));
let chunks = try!(self.put_inode(&root_inode));
Ok((root_inode, chunks))
}
Ok((root_inode, chunks))
}
pub fn import_tarfile<P: AsRef<Path>>(&mut self, tarfile: P) -> Result<Backup, RepositoryError> {

Loading…
Cancel
Save