use std::collections::HashSet; use lazy_static::lazy_static; use rpm_rs::rpm::{ get_installed_packages, Package, }; use rpm_rs::rpmio::rpmvercmp; use updateinfo_xmlparser::{UpdateInfoDb, RpmInfo}; use crate::cli::Cli; use crate::analyzer::db::PackgeDb; lazy_static! { pub static ref update_pkgs: PackgeDb= { let mut updatedb = UpdateInfoDb::new(); updatedb.load_xml("test/updateinfo.xml").unwrap(); let mut pkgdb = PackgeDb::new(); pkgdb.load_from_updateinfodb(&updatedb); pkgdb }; } pub mod db; pub fn cuvat_run(cli: &Cli) -> crate::Result<()> { // 只报告 cve 相关 if cli.cves { return list_cves(cli) } // 只报告 sa 相关 if cli.sas { return list_sas(cli) } // 生成报告 if cli.report { return repoter(cli) } // 默认报告格式 summary(cli) } fn list_cves(cli: &Cli) -> crate::Result<()> { Ok(()) } fn list_sas(cli: &Cli) -> crate::Result<()> { Ok(()) } fn repoter(cli: &Cli) -> crate::Result<()> { Ok(()) } fn summary(cli: &Cli) -> crate::Result<()> { let mut sa_ids: HashSet = HashSet::new(); // 当前系统所有已安装的 rpm 包 let installed = get_installed_packages(); // installed 已被消费掉 // latest_installed 是所有最新版本软件包的 Vec let latest_installed: Vec = installed.into_iter().map(|(_, pkgs)| { let mut latest = pkgs[0].clone(); for pkg in pkgs.into_iter() { latest = rpmdb_package_vercmp(latest, pkg); } latest }).collect(); // 获取 sa 更新列表 for pkg in latest_installed { let name = pkg.name(); if let Some(updates) = update_pkgs.db().get(name) { for update in updates { // epoch 判断 match (update.epoch(), pkg.epoch()) { (Some(_), None) => { let _ = sa_ids.insert(update.sa().into()); }, (None, Some(_)) => continue, _ => {} } // evr 对比 if rpmvercmp(&update.evr(), &pkg.evr()) > 0 { sa_ids.insert(update.sa().into()); } } } } println!("{:#?}", sa_ids.len()); // TODO: sa -> { rpms, cves } Ok(()) } // 对比两个 rpm Package 的版本,返回最新的一个 fn rpmdb_package_vercmp(pa: Package, pb: Package) -> Package { // 首先进行 epoch 的比较 match (pa.epoch(), pb.epoch()) { (Some(_), None) => return pa, (None, Some(_)) => return pb, _ => {}, // 继续往下对比 } if rpmvercmp(&pa.evr(), &pb.evr()) > 0 { return pa } else { return pb } }