diff --git a/src/procdata.rs b/src/procdata.rs index c52657a..b12a19d 100644 --- a/src/procdata.rs +++ b/src/procdata.rs @@ -1,7 +1,7 @@ use crate::{ filters::{dirs::PathsDataFilter, intf::DataFilter, resources::ResourcesDataFilter, texts::TextDataFilter}, profile::Profile, - rootfs, + rootfs::{self, RootFS}, scanner::{binlib::ElfScanner, debpkg::DebPackageScanner, dlst::ContentFormatter, general::Scanner}, shcall::ShellScript, }; @@ -196,7 +196,7 @@ impl TintProcessor { // Scan content of all profile packages (if any) // and then let TextDataFilter removes what still should be removed. // The idea is to keep parts only relevant to the runtime. - log::debug!("Filtering packages"); + log::debug!("Adding requested packages"); let pscan = DebPackageScanner::new(Autodeps::Undef); for p in self.profile.get_packages() { log::debug!("Getting content of package \"{}\"", p); @@ -226,6 +226,17 @@ impl TintProcessor { ResourcesDataFilter::new(paths.clone().into_iter().collect::>(), self.profile.to_owned(), self.autodeps) .filter(&mut paths); + // Remove package content before dissection + // XXX: Exlude .so binaries also from the Elf reader? + for p in self.profile.get_dropped_packages() { + log::debug!("Removing dropped package contents from \"{}\"", p); + for p in pscan.get_package_contents(p.to_string())? { + for p in RootFS::expand_target(p, true) { + paths.remove(&p); + } + } + } + // Scan rootfs log::debug!("Scanning existing rootfs"); let mut p = rootfs::RootFS::new() diff --git a/src/rootfs.rs b/src/rootfs.rs index 159d45d..0846d03 100644 --- a/src/rootfs.rs +++ b/src/rootfs.rs @@ -1,5 +1,6 @@ use std::{ collections::{HashMap, HashSet}, + fs, path::{Path, PathBuf}, vec, }; @@ -9,11 +10,13 @@ pub struct RootFS { tmp: bool, // keep /tmp rootfs: HashSet, ptree: Vec, + broken_links: HashSet, } impl RootFS { pub fn new() -> Self { - let mut rf = RootFS { pds: true, tmp: true, rootfs: HashSet::default(), ptree: vec![] }; + let mut rf = + RootFS { pds: true, tmp: true, rootfs: HashSet::default(), broken_links: HashSet::default(), ptree: Vec::default() }; rf.scan(); rf @@ -47,11 +50,12 @@ impl RootFS { } for x in src { - for y in self.expand_target(x) { + for y in Self::expand_target(x, false) { rfs.remove(&y); } } + rfs.extend(self.broken_links.to_owned()); rfs.into_iter().collect::>() } @@ -61,7 +65,7 @@ impl RootFS { /// the database still pointing to the old-fashioned location (e.g. "/bin"). /// In this case fall-back is used to find also in "/bin/" if /// search for the "/usr/bin/" fails. - fn expand_target(&self, target: PathBuf) -> Vec { + pub fn expand_target(target: PathBuf, reverse: bool) -> Vec { let mut p = PathBuf::from(&target); let fname = p.file_name().unwrap().to_owned(); @@ -77,8 +81,20 @@ impl RootFS { ("/usr/lib64/".to_string(), "/lib64/".to_string()), ]); - for (_fd, fl) in aliases { - if fdir.starts_with(&fl) { + for (fd, fl) in aliases { + if reverse && fdir.starts_with(&fd) { + let mut out: Vec = Vec::default(); + + let dpth = PathBuf::from(PathBuf::from(fdir).join(&fname).to_str().unwrap().to_string()); + let dlnk = PathBuf::from(dpth.to_str().unwrap().strip_prefix("/usr").unwrap()); + + for p in [dpth, dlnk] { + if p.exists() { + out.push(p); + } + } + return out; + } else if fdir.starts_with(&fl) { return vec![ PathBuf::from(PathBuf::from(fdir).join(&fname).to_str().unwrap().to_string()), PathBuf::from(PathBuf::from(format!("/usr{}", fdir)).join(fname).to_str().unwrap().to_string()), @@ -91,7 +107,7 @@ impl RootFS { /// Diff the whole rootfs to see what's inside. fn scan(&mut self) { - for rde in walkdir::WalkDir::new("/").follow_root_links(true).contents_first(true).follow_links(false) { + for rde in walkdir::WalkDir::new("/").follow_root_links(true).contents_first(true).follow_links(true) { match rde { Ok(entry) => { let p = entry.into_path(); @@ -109,12 +125,17 @@ impl RootFS { continue; } - if p.is_file() { - self.rootfs.insert(p); + if p.is_file() && p.exists() { + if let Ok(p) = fs::canonicalize(p) { + self.rootfs.insert(p); + } } } Err(err) => { - log::warn!("Unable to access \"{}\"", err); + log::debug!("Unable to access \"{}\"", err); + if let Some(p) = err.path() { + self.broken_links.insert(p.to_path_buf()); + } } } } diff --git a/src/scanner/dlst.rs b/src/scanner/dlst.rs index b3602ec..0735277 100644 --- a/src/scanner/dlst.rs +++ b/src/scanner/dlst.rs @@ -37,7 +37,9 @@ impl<'a> ContentFormatter<'a> { if let Some(fsr) = self.fs_removed { for p in fsr { - total_size += p.size_on_disk_fast(&p.metadata().unwrap()).unwrap(); + if p.exists() { + total_size += p.size_on_disk_fast(&p.metadata().unwrap()).unwrap(); + } total_files += 1; log::debug!(" - {}", p.to_str().unwrap()); }