mirror of https://github.com/dswd/zvault
Fix atime problem
This commit is contained in:
parent
bbafe64f85
commit
545523e5ce
|
@ -76,6 +76,14 @@ pub enum Arguments {
|
|||
repo_path: String,
|
||||
path: String
|
||||
},
|
||||
Diff {
|
||||
repo_path_old: String,
|
||||
backup_name_old: String,
|
||||
inode_old: Option<String>,
|
||||
repo_path_new: String,
|
||||
backup_name_new: String,
|
||||
inode_new: Option<String>
|
||||
},
|
||||
Analyze {
|
||||
repo_path: String
|
||||
},
|
||||
|
@ -313,6 +321,11 @@ pub fn parse() -> Arguments {
|
|||
(@arg REPO: +required "repository path")
|
||||
(@arg PATH: +required "the file path")
|
||||
)
|
||||
(@subcommand diff =>
|
||||
(about: "display difference between two backup versions")
|
||||
(@arg OLD: +required "old repository::backup[::subpath] path")
|
||||
(@arg NEW: +required "new repository::backup[::subpath] path")
|
||||
)
|
||||
(@subcommand config =>
|
||||
(about: "changes the configuration")
|
||||
(@arg REPO: +required "path of the repository")
|
||||
|
@ -460,6 +473,18 @@ pub fn parse() -> Arguments {
|
|||
path: args.value_of("PATH").unwrap().to_string()
|
||||
}
|
||||
}
|
||||
if let Some(args) = args.subcommand_matches("diff") {
|
||||
let (repository_old, backup_old, inode_old) = parse_repo_path(args.value_of("OLD").unwrap(), Some(true), None);
|
||||
let (repository_new, backup_new, inode_new) = parse_repo_path(args.value_of("NEW").unwrap(), Some(true), None);
|
||||
return Arguments::Diff {
|
||||
repo_path_old: repository_old.to_string(),
|
||||
backup_name_old: backup_old.unwrap().to_string(),
|
||||
inode_old: inode_old.map(|v| v.to_string()),
|
||||
repo_path_new: repository_new.to_string(),
|
||||
backup_name_new: backup_new.unwrap().to_string(),
|
||||
inode_new: inode_new.map(|v| v.to_string()),
|
||||
}
|
||||
}
|
||||
if let Some(args) = args.subcommand_matches("analyze") {
|
||||
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), Some(false), Some(false));
|
||||
return Arguments::Analyze {
|
||||
|
|
|
@ -95,7 +95,6 @@ fn print_inode(inode: &Inode) {
|
|||
println!("Permissions: {:3o}", inode.mode);
|
||||
println!("User: {}", inode.user);
|
||||
println!("Group: {}", inode.group);
|
||||
println!("Access time: {}", Local.timestamp(inode.access_time, 0).to_rfc2822());
|
||||
println!("Modification time: {}", Local.timestamp(inode.modify_time, 0).to_rfc2822());
|
||||
if let Some(ref target) = inode.symlink_target {
|
||||
println!("Symlink target: {}", target);
|
||||
|
@ -425,6 +424,25 @@ pub fn run() {
|
|||
println!("{}", format_inode_one_line(&inode));
|
||||
}
|
||||
},
|
||||
Arguments::Diff{repo_path_old, backup_name_old, inode_old, repo_path_new, backup_name_new, inode_new} => {
|
||||
if repo_path_old != repo_path_new {
|
||||
error!("Can only run diff on same repository");
|
||||
exit(2)
|
||||
}
|
||||
let mut repo = open_repository(&repo_path_old);
|
||||
let backup_old = get_backup(&repo, &backup_name_old);
|
||||
let backup_new = get_backup(&repo, &backup_name_new);
|
||||
let inode1 = checked(repo.get_backup_inode(&backup_old, inode_old.unwrap_or_else(|| "/".to_string())), "load subpath inode");
|
||||
let inode2 = checked(repo.get_backup_inode(&backup_new, inode_new.unwrap_or_else(|| "/".to_string())), "load subpath inode");
|
||||
let diffs = checked(repo.find_differences(&inode1, &inode2), "find differences");
|
||||
for diff in diffs {
|
||||
println!("{} {:?}", match diff.0 {
|
||||
DiffType::Add => "add",
|
||||
DiffType::Mod => "mod",
|
||||
DiffType::Del => "del"
|
||||
}, diff.1);
|
||||
}
|
||||
},
|
||||
Arguments::Config{repo_path, bundle_size, chunker, compression, encryption, hash} => {
|
||||
let mut repo = open_repository(&repo_path);
|
||||
if let Some(bundle_size) = bundle_size {
|
||||
|
|
|
@ -87,7 +87,7 @@ impl FuseInode {
|
|||
ino: self.num,
|
||||
size: self.inode.size,
|
||||
blocks: self.inode.size / 512,
|
||||
atime: Timespec::new(self.inode.access_time, 0),
|
||||
atime: Timespec::new(self.inode.modify_time, 0),
|
||||
mtime: Timespec::new(self.inode.modify_time, 0),
|
||||
ctime: Timespec::new(0, 0),
|
||||
crtime: Timespec::new(0, 0),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
pub use ::util::*;
|
||||
pub use ::bundledb::{BundleReader, BundleMode, BundleWriter, BundleInfo, BundleId, BundleDbError, BundleDb, BundleWriterError};
|
||||
pub use ::chunker::{ChunkerType, Chunker, ChunkerStatus, IChunker, ChunkerError};
|
||||
pub use ::repository::{Repository, Backup, Config, RepositoryError, RepositoryInfo, Inode, FileType, RepositoryIntegrityError, BackupFileError, BackupError, BackupOptions, BundleAnalysis, FileContents};
|
||||
pub use ::repository::{Repository, Backup, Config, RepositoryError, RepositoryInfo, Inode, FileType, RepositoryIntegrityError, BackupFileError, BackupError, BackupOptions, BundleAnalysis, FileContents, DiffType};
|
||||
pub use ::index::{Index, Location, IndexError};
|
||||
pub use ::mount::FuseFilesystem;
|
||||
|
||||
|
|
|
@ -31,6 +31,11 @@ pub struct BackupOptions {
|
|||
}
|
||||
|
||||
|
||||
pub enum DiffType {
|
||||
Add, Mod, Del
|
||||
}
|
||||
|
||||
|
||||
impl Repository {
|
||||
pub fn get_backups(&self) -> Result<HashMap<String, Backup>, RepositoryError> {
|
||||
Ok(try!(Backup::get_all_from(&self.crypto.lock().unwrap(), &self.backups_path)))
|
||||
|
@ -159,7 +164,7 @@ impl Repository {
|
|||
let meta_size = 1000; // add 1000 for encoded metadata
|
||||
backup.total_data_size += inode.size + meta_size;
|
||||
if let Some(ref_inode) = reference {
|
||||
if !ref_inode.is_unchanged(&inode) {
|
||||
if !ref_inode.is_same_meta_quick(&inode) {
|
||||
backup.changed_data_size += inode.size + meta_size;
|
||||
}
|
||||
} else {
|
||||
|
@ -295,4 +300,52 @@ impl Repository {
|
|||
versions.sort_by_key(|v| v.1.modify_time);
|
||||
Ok(versions)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn find_differences_recurse(&mut self, inode1: &Inode, inode2: &Inode, path: PathBuf, diffs: &mut Vec<(DiffType, PathBuf)>) -> Result<(), RepositoryError> {
|
||||
if !inode1.is_same_meta(inode2) || inode1.contents != inode2.contents {
|
||||
diffs.push((DiffType::Mod, path.clone()));
|
||||
}
|
||||
if let Some(ref children1) = inode1.children {
|
||||
if let Some(ref children2) = inode2.children {
|
||||
for name in children1.keys() {
|
||||
if !children2.contains_key(name) {
|
||||
diffs.push((DiffType::Del, path.join(name)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for name in children1.keys() {
|
||||
diffs.push((DiffType::Del, path.join(name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(ref children2) = inode2.children {
|
||||
if let Some(ref children1) = inode1.children {
|
||||
for (name, chunks2) in children2 {
|
||||
if let Some(chunks1) = children1.get(name) {
|
||||
if chunks1 != chunks2 {
|
||||
let inode1 = try!(self.get_inode(chunks1));
|
||||
let inode2 = try!(self.get_inode(chunks2));
|
||||
try!(self.find_differences_recurse(&inode1, &inode2, path.join(name), diffs));
|
||||
}
|
||||
} else {
|
||||
diffs.push((DiffType::Add, path.join(name)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for name in children2.keys() {
|
||||
diffs.push((DiffType::Add, path.join(name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn find_differences(&mut self, inode1: &Inode, inode2: &Inode) -> Result<Vec<(DiffType, PathBuf)>, RepositoryError> {
|
||||
let mut diffs = vec![];
|
||||
let path = PathBuf::from("/");
|
||||
try!(self.find_differences_recurse(inode1, inode2, path, &mut diffs));
|
||||
Ok(diffs)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,9 +111,9 @@ pub struct Inode {
|
|||
pub mode: u32,
|
||||
pub user: u32,
|
||||
pub group: u32,
|
||||
pub access_time: i64,
|
||||
pub __old_access_time: i64,
|
||||
pub modify_time: i64,
|
||||
pub create_time: i64,
|
||||
pub __old_create_time: i64,
|
||||
pub symlink_target: Option<String>,
|
||||
pub contents: Option<FileContents>,
|
||||
pub children: Option<BTreeMap<String, ChunkList>>
|
||||
|
@ -127,9 +127,9 @@ impl Default for Inode {
|
|||
mode: 0o644,
|
||||
user: 1000,
|
||||
group: 1000,
|
||||
access_time: 0,
|
||||
__old_access_time: 0,
|
||||
modify_time: 0,
|
||||
create_time: 0,
|
||||
__old_create_time: 0,
|
||||
symlink_target: None,
|
||||
contents: None,
|
||||
children: None
|
||||
|
@ -143,9 +143,9 @@ serde_impl!(Inode(u8) {
|
|||
mode: u32 => 3,
|
||||
user: u32 => 4,
|
||||
group: u32 => 5,
|
||||
access_time: i64 => 6,
|
||||
__old_access_time: i64 => 6,
|
||||
modify_time: i64 => 7,
|
||||
create_time: i64 => 8,
|
||||
__old_create_time: i64 => 8,
|
||||
symlink_target: Option<String> => 9,
|
||||
contents: Option<FileContents> => 10,
|
||||
children: BTreeMap<String, ChunkList> => 11
|
||||
|
@ -213,7 +213,13 @@ impl Inode {
|
|||
Ok(file)
|
||||
}
|
||||
|
||||
pub fn is_unchanged(&self, other: &Inode) -> bool {
|
||||
pub fn is_same_meta(&self, other: &Inode) -> bool {
|
||||
self.file_type == other.file_type && self.size == other.size && self.mode == other.mode
|
||||
&& self.user == other.user && self.group == other.group && self.name == other.name
|
||||
&& self.modify_time == other.modify_time && self.symlink_target == other.symlink_target
|
||||
}
|
||||
|
||||
pub fn is_same_meta_quick(&self, other: &Inode) -> bool {
|
||||
self.modify_time == other.modify_time
|
||||
&& self.file_type == other.file_type
|
||||
&& self.size == other.size
|
||||
|
@ -236,7 +242,7 @@ impl Repository {
|
|||
let mut inode = try!(Inode::get_from(path.as_ref()));
|
||||
if inode.file_type == FileType::File && inode.size > 0 {
|
||||
if let Some(reference) = reference {
|
||||
if reference.is_unchanged(&inode) {
|
||||
if reference.is_same_meta_quick(&inode) {
|
||||
inode.contents = reference.contents.clone();
|
||||
return Ok(inode)
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ use std::io::Write;
|
|||
pub use self::error::RepositoryError;
|
||||
pub use self::config::Config;
|
||||
pub use self::metadata::{Inode, FileType, FileContents};
|
||||
pub use self::backup::{BackupError, BackupOptions};
|
||||
pub use self::backup::{BackupError, BackupOptions, DiffType};
|
||||
pub use self::backup_file::{Backup, BackupFileError};
|
||||
pub use self::integrity::RepositoryIntegrityError;
|
||||
pub use self::info::{RepositoryInfo, BundleAnalysis};
|
||||
|
|
Loading…
Reference in New Issue