use std::collections::BTreeMap; use clap::crate_name; use osquery_rust::plugin::{ColumnDef, ColumnType, Plugin, Table}; use osquery_rust::prelude::*; #[osquery_rust::args] fn main() -> std::io::Result<()> { let args = Args::parse(); if !args.standalone { let mut manager = Server::new(Some(crate_name!()), args.socket().unwrap().as_str()).unwrap(); manager.register_plugin(Plugin::Table(Table::new( "xbps_packages", xbps_packages_columns(), xbps_packages_generate, ))); manager.run(); } Ok(()) } fn xbps_packages_columns() -> Vec { vec![ ColumnDef::new("name", ColumnType::Text), ColumnDef::new("version", ColumnType::Text), ColumnDef::new("description", ColumnType::Text), ColumnDef::new("homepage", ColumnType::Text), ColumnDef::new("maintainer", ColumnType::Text), ColumnDef::new("install_date", ColumnType::Text), ColumnDef::new("license", ColumnType::Text), ColumnDef::new("repository", ColumnType::Text), ] } fn xbps_packages_generate(_req: ExtensionPluginRequest) -> ExtensionResponse { let mut resp = ExtensionPluginResponse::new(); let pkgdb: plist::Value = plist::from_file("/var/db/xbps/pkgdb-0.38.plist").expect("failed to read pkgdb"); if let plist::Value::Dictionary(pkgdb) = pkgdb { for (name, pkg) in pkgdb { if let plist::Value::Dictionary(pkg) = pkg { let pkgmap: Result, String> = vec![ ("name", pkg.get("pkgname")), ("version", pkg.get("pkgver")), ("description", pkg.get("short_desc")), ("homepage", pkg.get("homepage")), ("maintainer", pkg.get("maintainer")), ("install_date", pkg.get("install-date")), ("license", pkg.get("license")), ("repository", pkg.get("repository")), ] .into_iter() .map(|(key, value)| { match value { Some(plist::Value::String(value)) => Ok((key.to_owned(), value.to_owned())), None => Err(format!("{name} has no {key} field")), Some(_) => Err(format!("{name} has an invalid type in {key}")), } .map(|(key, value)| { if key == "version" { let (_, value) = value.split_at(name.len() + 1); (key, value.into()) } else { (key, value) } }) }) .collect(); if let Ok(pkgmap) = pkgmap { resp.push(pkgmap); } } } } ExtensionResponse::new(ExtensionStatus::default(), resp) }