Storing user/group id map in backup and using it on restore (re #2)

This commit is contained in:
Dennis Schwerdel 2017-04-12 14:08:21 +02:00
parent 57e62b7880
commit 5a6cf4b55b
7 changed files with 49 additions and 5 deletions

View File

@ -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)

10
Cargo.lock generated
View File

@ -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"

View File

@ -30,6 +30,7 @@ tar = "0.4"
xattr = "0.1"
crossbeam = "0.2"
pbr = "1.0.0-alpha.3"
users = "0.5"
time = "*"
libc = "*"

View File

@ -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");
},

View File

@ -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;

View File

@ -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<P: AsRef<Path>>(&mut self, inode: Inode, path: P) -> Result<(), RepositoryError> {
pub fn restore_inode_tree<P: AsRef<Path>>(&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<Inode, RepositoryError> {
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 {

View File

@ -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<u32, String>,
pub group_names: HashMap<u32, String>
}
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<u32, String> => 16,
group_names: HashMap<u32, String> => 17
});
impl Backup {