From 5a6cf4b55b3ef2f450a64fcbeb4bcde2a7d2a32c Mon Sep 17 00:00:00 2001 From: Dennis Schwerdel Date: Wed, 12 Apr 2017 14:08:21 +0200 Subject: [PATCH] Storing user/group id map in backup and using it on restore (re #2) --- CHANGELOG.md | 2 ++ Cargo.lock | 10 ++++++++++ Cargo.toml | 1 + src/cli/mod.rs | 2 +- src/main.rs | 1 + src/repository/backup.rs | 30 ++++++++++++++++++++++++++++-- src/repository/backup_file.rs | 8 ++++++-- 7 files changed, 49 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 517615c..8033c8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ This project follows [semantic versioning](http://semver.org). - [fixed] Fixed a deadlock in the bundle upload code - [fixed] Also setting repository dirty on crash - [fixed] Ignoring missing backups folder +- [fixed] Fixed problems with uploads from relative repository paths +- [fixed] Fixed finished messages ### v0.1.0 (2017-04-11) diff --git a/Cargo.lock b/Cargo.lock index c728e63..29c587e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,6 +29,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)", + "users 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "xattr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -432,6 +433,14 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "utf8-ranges" version = "1.0.0" @@ -527,6 +536,7 @@ dependencies = [ "checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" +"checksum users 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7ae8fdf783cb9652109c99886459648feb92ecc749e6b8e7930f6decba74c7c" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum vec_map 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8cdc8b93bd0198ed872357fb2e667f7125646b1762f16d60b2c96350d361897" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/Cargo.toml b/Cargo.toml index c13728b..c97dd01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ tar = "0.4" xattr = "0.1" crossbeam = "0.2" pbr = "1.0.0-alpha.3" +users = "0.5" time = "*" libc = "*" diff --git a/src/cli/mod.rs b/src/cli/mod.rs index e9c64ab..3afb1c0 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -382,7 +382,7 @@ pub fn run() -> Result<(), ErrorCode> { if tar { checked!(repo.export_tarfile(inode, &dst_path), "restore backup", ErrorCode::RestoreRun); } else { - checked!(repo.restore_inode_tree(inode, &dst_path), "restore backup", ErrorCode::RestoreRun); + checked!(repo.restore_inode_tree(&backup, inode, &dst_path), "restore backup", ErrorCode::RestoreRun); } info!("Restore finished"); }, diff --git a/src/main.rs b/src/main.rs index 8cbb50c..7a88882 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ extern crate time; extern crate xattr; extern crate crossbeam; extern crate pbr; +extern crate users; extern crate libc; extern crate tar; diff --git a/src/repository/backup.rs b/src/repository/backup.rs index 227be97..ea9386f 100644 --- a/src/repository/backup.rs +++ b/src/repository/backup.rs @@ -7,6 +7,7 @@ use std::os::linux::fs::MetadataExt; use chrono::prelude::*; use regex::RegexSet; +use users::{self, Users, Groups}; quick_error!{ @@ -135,11 +136,22 @@ impl Repository { Ok(()) } - pub fn restore_inode_tree>(&mut self, inode: Inode, path: P) -> Result<(), RepositoryError> { + pub fn restore_inode_tree>(&mut self, backup: &Backup, inode: Inode, path: P) -> Result<(), RepositoryError> { let _lock = try!(self.lock(false)); let mut queue = VecDeque::new(); queue.push_back((path.as_ref().to_owned(), inode)); - while let Some((path, inode)) = queue.pop_front() { + let cache = users::UsersCache::new(); + while let Some((path, mut inode)) = queue.pop_front() { + if let Some(name) = backup.user_names.get(&inode.user) { + if let Some(user) = cache.get_user_by_name(name) { + inode.user = user.uid(); + } + } + if let Some(name) = backup.group_names.get(&inode.group) { + if let Some(group) = cache.get_group_by_name(name) { + inode.group = group.gid(); + } + } try!(self.save_inode_at(&inode, &path)); if inode.file_type == FileType::Directory { let path = path.join(inode.name); @@ -162,6 +174,20 @@ impl Repository { ) -> Result { let path = path.as_ref(); let mut inode = try!(self.create_inode(path, reference)); + if !backup.user_names.contains_key(&inode.user) { + if let Some(user) = users::get_user_by_uid(inode.user) { + backup.user_names.insert(inode.user, user.name().to_string()); + } else { + warn!("Failed to retrieve name of user {}", inode.user); + } + } + if !backup.group_names.contains_key(&inode.group) { + if let Some(group) = users::get_group_by_gid(inode.group) { + backup.group_names.insert(inode.group, group.name().to_string()); + } else { + warn!("Failed to retrieve name of group {}", inode.group); + } + } let mut meta_size = 0; inode.cum_size = inode.size; if inode.file_type == FileType::Directory { diff --git a/src/repository/backup_file.rs b/src/repository/backup_file.rs index d753fdd..e12c4bd 100644 --- a/src/repository/backup_file.rs +++ b/src/repository/backup_file.rs @@ -88,7 +88,9 @@ pub struct Backup { pub host: String, pub path: String, pub config: Config, - pub modified: bool + pub modified: bool, + pub user_names: HashMap, + pub group_names: HashMap } serde_impl!(Backup(u8?) { root: ChunkList => 0, @@ -106,7 +108,9 @@ serde_impl!(Backup(u8?) { host: String => 12, path: String => 13, config: Config => 14, - modified: bool => 15 + modified: bool => 15, + user_names: HashMap => 16, + group_names: HashMap => 17 }); impl Backup {