syd 3.58.0

rock-solid application kernel
Documentation
//
// Syd: rock-solid application kernel
// src/utils/syd-cap.rs: Print information on Linux capabilities
//
// Copyright (c) 2024, 2025, 2026 Ali Polatel <alip@chesswob.org>
//
// SPDX-License-Identifier: GPL-3.0

use std::process::ExitCode;

use nix::errno::Errno;
#[expect(clippy::disallowed_types)]
use serde_json::Map;
use syd::{caps::CapSet, printfln};
// Set global allocator to GrapheneOS allocator.
#[cfg(all(
    not(target_os = "android"),
    not(target_arch = "loongarch64"),
    not(target_arch = "riscv64"),
    target_page_size_4k,
    target_pointer_width = "64"
))]
#[global_allocator]
static GLOBAL: hardened_malloc::HardenedMalloc = hardened_malloc::HardenedMalloc;

syd::main! {
    use lexopt::prelude::*;

    syd::set_sigpipe_dfl()?;

    // Parse CLI options.
    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()),
        }
    }

    #[expect(clippy::disallowed_types)]
    let mut cap = Map::new();
    for set in [
        CapSet::Bounding,
        CapSet::Permitted,
        CapSet::Inheritable,
        CapSet::Ambient,
        CapSet::Effective,
    ] {
        let mut vec = Vec::new();

        for flag in syd::caps::Capabilities::all()? {
            let cap: syd::caps::Capability = flag.try_into()?;
            if syd::caps::has_cap(None, set, cap)? {
                vec.push(serde_json::Value::String(cap.to_string()));
            }
        }
        cap.insert(set2name(set), serde_json::Value::Array(vec));
    }

    let cap = serde_json::to_string_pretty(&cap).or(Err(Errno::EINVAL))?;
    printfln!("{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() -> Result<(), Errno> {
    printfln!("Usage: syd-cap [-h]")?;
    printfln!("Print information on Linux capabilities.")?;
    Ok(())
}