use std::process::ExitCode;
use serde_json::Map;
use syd::caps::CapSet;
#[cfg(all(
not(coverage),
not(feature = "prof"),
not(target_os = "android"),
not(target_arch = "riscv64"),
target_page_size_4k,
target_pointer_width = "64"
))]
#[global_allocator]
static GLOBAL: hardened_malloc::HardenedMalloc = hardened_malloc::HardenedMalloc;
#[cfg(feature = "prof")]
#[global_allocator]
static GLOBAL: tcmalloc::TCMalloc = tcmalloc::TCMalloc;
syd::main! {
use lexopt::prelude::*;
syd::set_sigpipe_dfl()?;
let mut parser = lexopt::Parser::from_env();
#[expect(clippy::never_loop)]
while let Some(arg) = parser.next()? {
match arg {
Short('h') => {
help();
return Ok(ExitCode::SUCCESS);
}
_ => return Err(arg.unexpected().into()),
}
}
let mut cap = Map::new();
for set in [
CapSet::Bounding,
CapSet::Permitted,
CapSet::Inheritable,
CapSet::Ambient,
CapSet::Effective,
] {
let mut vec = Vec::new();
#[expect(clippy::disallowed_methods)]
for flag in syd::caps::Capabilities::all() {
let cap: syd::caps::Capability = flag.try_into().unwrap();
if syd::caps::has_cap(None, set, cap).expect("syd::caps::has_cap") {
vec.push(serde_json::Value::String(cap.to_string()));
}
}
cap.insert(set2name(set), serde_json::Value::Array(vec));
}
#[expect(clippy::disallowed_methods)]
let cap = serde_json::to_string_pretty(&cap).unwrap();
println!("{cap}");
Ok(ExitCode::SUCCESS)
}
fn set2name(set: CapSet) -> String {
match set {
CapSet::Ambient => "ambient",
CapSet::Bounding => "bounding",
CapSet::Effective => "effective",
CapSet::Inheritable => "inheritable",
CapSet::Permitted => "permitted",
}
.to_string()
}
fn help() {
println!("Usage: syd-cap [-h]");
println!("Print information on Linux capabilities.");
}