Use UID and GID tables in extraction
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Fixes #18
This commit is contained in:
parent
f5afcb9205
commit
dc9885947c
@ -195,6 +195,25 @@ impl TreeNode {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn visit_mut<F: FnMut(&mut TreeNode, &str) -> anyhow::Result<()>>(
|
||||||
|
&mut self,
|
||||||
|
func: &mut F,
|
||||||
|
prefix: String,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
func(self, &prefix)?;
|
||||||
|
if let TreeNode::Directory { children, .. } = self {
|
||||||
|
for (name, child) in children.iter_mut() {
|
||||||
|
if prefix.is_empty() {
|
||||||
|
// don't want a slash prefix
|
||||||
|
child.visit_mut(func, name.clone())?;
|
||||||
|
} else {
|
||||||
|
child.visit_mut(func, format!("{}/{}", prefix, name))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn exists(&self, pieces: &[&str]) -> bool {
|
pub fn exists(&self, pieces: &[&str]) -> bool {
|
||||||
match pieces.first() {
|
match pieces.first() {
|
||||||
None => true,
|
None => true,
|
||||||
|
@ -15,8 +15,9 @@ use nix::unistd::{Gid, Uid};
|
|||||||
|
|
||||||
use crate::chunking::RecursiveUnchunker;
|
use crate::chunking::RecursiveUnchunker;
|
||||||
use crate::commands::fully_load_pointer;
|
use crate::commands::fully_load_pointer;
|
||||||
use crate::definitions::{RecursiveChunkRef, TreeNode};
|
use crate::definitions::{FilesystemOwnership, RecursiveChunkRef, TreeNode};
|
||||||
use crate::pile::{Pile, RawPile};
|
use crate::pile::{Pile, RawPile};
|
||||||
|
use std::collections::{BTreeMap, HashMap};
|
||||||
|
|
||||||
pub fn extract<RP: RawPile>(
|
pub fn extract<RP: RawPile>(
|
||||||
target_path: &Path,
|
target_path: &Path,
|
||||||
@ -88,7 +89,17 @@ pub fn extract_from_pointer_name<RP: RawPile>(
|
|||||||
num_workers: u8,
|
num_workers: u8,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let (pointer_data, mut root_node) = fully_load_pointer(pile, pointer_name.as_ref())?;
|
let (pointer_data, mut root_node) = fully_load_pointer(pile, pointer_name.as_ref())?;
|
||||||
// TODO CONVERT THE UID AND GIDs!!!
|
|
||||||
|
let uid_translation_table = build_uid_translation_table(&pointer_data.uid_lookup);
|
||||||
|
let gid_translation_table = build_gid_translation_table(&pointer_data.gid_lookup);
|
||||||
|
|
||||||
|
// convert the UIDs and GIDs to match this system, which may be different from the usual.
|
||||||
|
apply_uid_and_gid_translation_tables(
|
||||||
|
&mut root_node.node,
|
||||||
|
&uid_translation_table,
|
||||||
|
&gid_translation_table,
|
||||||
|
);
|
||||||
|
|
||||||
extract(
|
extract(
|
||||||
&target_path.join(&root_node.name),
|
&target_path.join(&root_node.name),
|
||||||
&mut root_node.node,
|
&mut root_node.node,
|
||||||
@ -98,6 +109,83 @@ pub fn extract_from_pointer_name<RP: RawPile>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn build_uid_translation_table(
|
||||||
|
uid_lookup: &BTreeMap<u16, Option<String>>,
|
||||||
|
) -> HashMap<u16, u16> {
|
||||||
|
let mut result: HashMap<u16, u16> = Default::default();
|
||||||
|
|
||||||
|
for (old_uid, name) in uid_lookup.iter() {
|
||||||
|
if let Some(name) = name {
|
||||||
|
if let Some(user) = users::get_user_by_name(name) {
|
||||||
|
let new_uid = user.uid() as u16;
|
||||||
|
if new_uid != *old_uid {
|
||||||
|
result.insert(*old_uid, new_uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_gid_translation_table(
|
||||||
|
gid_lookup: &BTreeMap<u16, Option<String>>,
|
||||||
|
) -> HashMap<u16, u16> {
|
||||||
|
let mut result: HashMap<u16, u16> = Default::default();
|
||||||
|
|
||||||
|
for (old_gid, name) in gid_lookup.iter() {
|
||||||
|
if let Some(name) = name {
|
||||||
|
if let Some(group) = users::get_group_by_name(name) {
|
||||||
|
let new_gid = group.gid() as u16;
|
||||||
|
if new_gid != *old_gid {
|
||||||
|
result.insert(*old_gid, new_gid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_uid_and_gid_translation_tables(
|
||||||
|
node: &mut TreeNode,
|
||||||
|
uid_translation: &HashMap<u16, u16>,
|
||||||
|
gid_translation: &HashMap<u16, u16>,
|
||||||
|
) {
|
||||||
|
if uid_translation.is_empty() && gid_translation.is_empty() {
|
||||||
|
// nothing to do here :).
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let apply_to = |ownership: &mut FilesystemOwnership| {
|
||||||
|
ownership.uid = *uid_translation
|
||||||
|
.get(&ownership.uid)
|
||||||
|
.unwrap_or(&ownership.uid);
|
||||||
|
ownership.gid = *gid_translation
|
||||||
|
.get(&ownership.gid)
|
||||||
|
.unwrap_or(&ownership.gid);
|
||||||
|
};
|
||||||
|
node.visit_mut(
|
||||||
|
&mut |node, _| {
|
||||||
|
match node {
|
||||||
|
TreeNode::NormalFile { ownership, .. } => {
|
||||||
|
apply_to(ownership);
|
||||||
|
}
|
||||||
|
TreeNode::Directory { ownership, .. } => {
|
||||||
|
apply_to(ownership);
|
||||||
|
}
|
||||||
|
TreeNode::SymbolicLink { ownership, .. } => {
|
||||||
|
apply_to(ownership);
|
||||||
|
}
|
||||||
|
TreeNode::Deleted => {}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
"".to_owned(),
|
||||||
|
)
|
||||||
|
.expect("Can't fail since we don't fail.");
|
||||||
|
}
|
||||||
|
|
||||||
pub fn extract_worker<RP: RawPile>(
|
pub fn extract_worker<RP: RawPile>(
|
||||||
pile: &Pile<RP>,
|
pile: &Pile<RP>,
|
||||||
paths: Receiver<(PathBuf, RecursiveChunkRef)>,
|
paths: Receiver<(PathBuf, RecursiveChunkRef)>,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user