cvrf2cusa/src/lib.rs
Jia Chao 6a75014e83 添加 auto 子命令,用于 cuavrs 系统自动转换,专用,尚未完成
Signed-off-by: Jia Chao <jiac13@chinaunicom.cn>
2024-07-02 09:42:50 +08:00

187 lines
5.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use std::collections::HashMap;
use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf};
use cvrf_xmlparser::{
CVRF,
// SaInfo 即为 CUSA
// SaInfo,
};
pub mod cli;
mod config;
/// 定义 crate::Error
/// 大部分函数返回的错误
pub type Error = Box<dyn std::error::Error + Send + Sync>;
/// 定义 crate::Result
pub type Result<T> = std::result::Result<T, Error>;
pub fn cumain() -> Result<()> {
let cli = cli::parse();
match cli.subcommand {
cli::CliSub::Convert(cli) => covert(&cli),
cli::CliSub::Db(cli) => sadb(&cli),
cli::CliSub::Auto(_) => auto(),
}
}
/// 可使用 convert 函数将 cvrf 格式文件转换并输出至指定的 cusa 文件。
///
/// 例:
///
/// ```no_run
/// use cvrf2cusa::cli::ConvertCli
///
/// let cli = ConvertCli::new(
/// // input
/// "xxx-cvrf.xml".to_string,
/// // output
/// Some("pkg_version_said.json".to_string),
/// // print to screen
/// false,
/// );
///
/// cvrf2cusa::Convert(cli)?;
/// ```
pub fn covert(cli: &cli::ConvertCli) -> Result<()> {
// 检查 input此为必须项
let input = Path::new(&cli.input);
if !input.is_file() {
return Err("输入的文件不是有效的文件路径!".into());
}
// 从 input 读取 cvrf并转换为 cusa
let mut cvrf = CVRF::new();
cvrf.load_xml(&cli.input)?;
let cusa = cvrf.sainfo();
let data = serde_json::to_string_pretty(&cusa)?;
// 是否将 cusa 输出至指定文件
if let Some(output) = &cli.output {
let output = Path::new(output);
// output 所在父路径须提前创建
let parent = output.parent().unwrap();
if !parent.exists() {
return Err("无法访问输出文件所在路径,请确认!".into());
}
// 写入文件
let mut json_file = fs::OpenOptions::new().read(true).write(true).create(true).open(output)?;
json_file.write(data.as_bytes())?;
json_file.flush()?;
// 在输出到文件模式下,默认不再标准输出打印 CUSA
if !cli.print {
return Ok(())
}
}
// 在标准输出打印 CUSA
println!("{}", data);
Ok(())
}
pub fn sadb(cli: &cli::SaDbCli) -> Result<()> {
let source = &cli.from;
// 只要文件
let files = walk_dir(source, true);
let mut sadb = HashMap::new();
let mut cvedb = HashMap::new();
for _file in files {
match _file.extension() {
Some(tail) => {
if tail != "xml" {
continue;
}
// 从 xml 中读取 cvrf 并转换为 cusa
let file = if let Some(file) = _file.to_str() {
file
} else {
continue;
};
let mut cvrf = CVRF::new();
let _ = cvrf.load_xml(file);
let sa = cvrf.sainfo();
// cvedb
sa.cves.clone().into_iter().for_each(|cve| {
cvedb.insert(cve.id.clone(), cve);
});
// sadb
// 很烦,华为干的这事儿
// 2022/cvrf-openEuler-SA-2022-2063.xml 里的 ID 为 openEuler-SA-2022-2046
// 暂不处理
// TODO
if let Some(_) = sadb.insert(sa.id.clone(), sa) {
// unimplemented!();
}
}
_ => {}
}
}
// 写入 sadb 文件
let data = serde_json::to_string_pretty(&sadb)?;
let mut sadb_file = fs::OpenOptions::new().read(true).write(true).create(true).open(&cli.sa)?;
sadb_file.write(data.as_bytes())?;
sadb_file.flush()?;
// 写入 cvedb 文件
let data = serde_json::to_string_pretty(&cvedb)?;
let mut cvedb_file = fs::OpenOptions::new().read(true).write(true).create(true).open(&cli.cve)?;
cvedb_file.write(data.as_bytes())?;
cvedb_file.flush()?;
Ok(())
}
// 递归去读一个路径,返回一个文件列表
#[allow(dead_code)]
fn walk_dir<P: AsRef<Path>>(path: P, nodir: bool) -> Vec<PathBuf>
{
let mut res = vec![];
for entry in std::fs::read_dir(path).expect("read_dir call failed!") {
let entry = entry.unwrap().path();
if entry.is_dir() {
if !nodir {
res.push(entry.clone());
}
res.append(&mut walk_dir(entry, nodir));
} else {
// 暂不处理链接等情况
res.push(entry);
}
}
res
}
/// 从配置文件中读取 cvrf 和 cusa 数据库的路径,并执行自动转换操作
pub fn auto() -> Result<()> {
// 默认配置为,但也可读取执行命令路径下的配置
let config = {
let default = Path::new("/etc/cuvars/cvrf2cusa.json");
if default.is_file() {
default.to_str().unwrap()
} else {
"cvrf2cusa.json"
}
};
let auto = config::AutoConfig::from(config)?;
todo!();
Ok(())
}