//
// libsyd: Rust-based C library for syd interaction via /dev/syd
// lib/src/lib.rs: syd API C Library
//
// Copyright (c) 2023, 2024, 2025 Ali Polatel <alip@chesswob.org>
//
// SPDX-License-Identifier: LGPL-3.0

//! # libsyd - syd API Rust Library
//!
//! `libsyd` is a C library written in Rust that implements the syd
//! stat API, providing an interface to the `/dev/syd` of syd. It
//! allows for runtime configuration and interaction with the syd
//! sandboxing environment.
//!
//! ## Overview
//! The library is designed to interact with the syd sandboxing
//! environment, offering functionalities to check and modify the state
//! of the sandbox lock, and perform system calls to `/dev/syd`.
//!
//! For more detailed information and usage instructions, refer to the syd
//! manual, available at [syd Manual](http://man.exherbolinux.org/syd.2.html).
//!
//! ## Author
//! Ali Polatel <alip@chesswob.org>

// We like safe, clean and simple code with documentation.
#![deny(missing_docs)]
#![deny(clippy::allow_attributes_without_reason)]
#![deny(clippy::arithmetic_side_effects)]
#![deny(clippy::as_ptr_cast_mut)]
#![deny(clippy::as_underscore)]
#![deny(clippy::assertions_on_result_states)]
#![deny(clippy::borrow_as_ptr)]
#![deny(clippy::branches_sharing_code)]
#![deny(clippy::case_sensitive_file_extension_comparisons)]
#![deny(clippy::cast_lossless)]
#![deny(clippy::cast_possible_truncation)]
#![deny(clippy::cast_possible_wrap)]
#![deny(clippy::cast_precision_loss)]
#![deny(clippy::cast_ptr_alignment)]
#![deny(clippy::cast_sign_loss)]
#![deny(clippy::checked_conversions)]
#![deny(clippy::clear_with_drain)]
#![deny(clippy::clone_on_ref_ptr)]
#![deny(clippy::cloned_instead_of_copied)]
#![deny(clippy::cognitive_complexity)]
#![deny(clippy::collection_is_never_read)]
#![deny(clippy::copy_iterator)]
#![deny(clippy::create_dir)]
#![deny(clippy::dbg_macro)]
#![deny(clippy::debug_assert_with_mut_call)]
#![deny(clippy::decimal_literal_representation)]
#![deny(clippy::default_trait_access)]
#![deny(clippy::default_union_representation)]
#![deny(clippy::derive_partial_eq_without_eq)]
#![deny(clippy::doc_link_with_quotes)]
#![deny(clippy::doc_markdown)]
#![deny(clippy::explicit_into_iter_loop)]
#![deny(clippy::explicit_iter_loop)]
#![deny(clippy::fallible_impl_from)]
#![deny(clippy::missing_safety_doc)]
#![deny(clippy::undocumented_unsafe_blocks)]

use std::{
    ffi::{CStr, OsStr, OsString},
    fs::{symlink_metadata, Metadata},
    os::{
        raw::{c_char, c_int},
        unix::{
            ffi::OsStrExt,
            fs::{FileTypeExt, MetadataExt},
        },
    },
    path::{Path, PathBuf},
};

/// An enumeration of the possible states for the sandbox lock.
#[repr(u8)]
#[allow(non_camel_case_types)]
pub enum lock_state_t {
    /// The sandbox lock is off, allowing all sandbox commands.
    LOCK_OFF,
    /// The sandbox lock is set to on for all processes except the initial
    /// process (syd exec child).
    LOCK_EXEC,
    /// The sandbox lock is on, disallowing all sandbox commands.
    LOCK_ON,
}

/// An enumeration of the possible actions for sandboxing.
#[repr(u8)]
#[allow(non_camel_case_types)]
pub enum action_t {
    /// Allow system call.
    ALLOW,
    /// Allow system call and warn.
    WARN,
    /// Deny system call silently.
    FILTER,
    /// Deny system call and warn.
    DENY,
    /// Deny system call, warn and panic the current Syd thread.
    PANIC,
    /// Deny system call, warn and stop the offending process.
    STOP,
    /// Deny system call, warn and kill the offending process.
    KILL,
    /// Warn, and exit Syd immediately with deny errno as exit value.
    EXIT,
}

const EFAULT: i32 = 14;
const EINVAL: i32 = 22;

#[inline(always)]
fn check_stat(stat: &Metadata) -> bool {
    if !stat.file_type().is_char_device() {
        return false;
    }

    let rdev = stat.rdev();

    let major = (rdev >> 8) & 0xff;
    let minor = rdev & 0xff;

    // dev/null
    major == 1 && minor == 3
}

fn stat<P: AsRef<Path>>(path: P) -> c_int {
    match symlink_metadata(path) {
        Ok(stat) if check_stat(&stat) => 0,
        Ok(_) => -EINVAL,
        Err(error) => match error.raw_os_error() {
            Some(e) => e.checked_neg().unwrap_or(-EINVAL),
            None => -EINVAL,
        },
    }
}

fn esyd<P: AsRef<Path>>(rule: P, elem: *const c_char, op: u8) -> c_int {
    if !matches!(op, b'+' | b'-' | b'^' | b':') {
        return -EINVAL;
    }

    if elem.is_null() {
        return -EFAULT;
    }

    // SAFETY: Trust that `elem` is a null-terminated string.
    let elem = unsafe { CStr::from_ptr(elem) };
    let elem = OsStr::from_bytes(elem.to_bytes());

    // Manually concatenate the path segments
    let mut path = OsString::from("/dev/syd/");
    path.push(rule.as_ref());
    path.push(OsStr::from_bytes(&[op]));
    path.push(elem);

    // Convert the OsString to PathBuf
    let path = PathBuf::from(path);

    stat(path)
}

/// Performs a syd API check
///
/// The caller is advised to perform this check before
/// calling any other syd API calls.
///
/// Returns API number on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_api() -> c_int {
    match stat("/dev/syd/3") {
        0 => 3,
        n => n,
    }
}

/// Performs an lstat system call on the file "/dev/syd".
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_check() -> c_int {
    stat("/dev/syd")
}

/// Causes syd to exit immediately with code 127
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_panic() -> c_int {
    stat("/dev/syd/panic")
}

/// Causes syd to reset sandboxing to the default state.
/// Allowlists, denylists and filters are going to be cleared.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_reset() -> c_int {
    stat("/dev/syd/reset")
}

/// Causes syd to read configuration from the given file descriptor.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_load(fd: c_int) -> c_int {
    let mut path = PathBuf::from("/dev/syd/load");

    let mut buf = itoa::Buffer::new();
    path.push(buf.format(fd));

    stat(path)
}

/// Sets the state of the sandbox lock.
///
/// state: The desired state of the sandbox lock.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_lock(state: lock_state_t) -> c_int {
    match state as u8 {
        0 => stat("/dev/syd/lock:off"),
        1 => stat("/dev/syd/lock:exec"),
        2 => stat("/dev/syd/lock:on"),
        _ => -EINVAL,
    }
}

/// Checks if stat sandboxing is enabled.
///
/// Returns true if stat sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_stat() -> bool {
    stat("/dev/syd/sandbox/stat?") == 0
}

/// Enable stat sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_stat() -> c_int {
    stat("/dev/syd/sandbox/stat:on")
}

/// Disable stat sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_stat() -> c_int {
    stat("/dev/syd/sandbox/stat:off")
}

/// Checks if read sandboxing is enabled.
///
/// Returns true if read sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_read() -> bool {
    stat("/dev/syd/sandbox/read?") == 0
}

/// Enable read sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_read() -> c_int {
    stat("/dev/syd/sandbox/read:on")
}

/// Disable read sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_read() -> c_int {
    stat("/dev/syd/sandbox/read:off")
}

/// Checks if write sandboxing is enabled.
///
/// Returns true if write sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_write() -> bool {
    stat("/dev/syd/sandbox/write?") == 0
}

/// Enable write sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_write() -> c_int {
    stat("/dev/syd/sandbox/write:on")
}

/// Disable write sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_write() -> c_int {
    stat("/dev/syd/sandbox/write:off")
}

/// Checks if exec sandboxing is enabled.
///
/// Returns true if exec sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_exec() -> bool {
    stat("/dev/syd/sandbox/exec?") == 0
}

/// Enable exec sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_exec() -> c_int {
    stat("/dev/syd/sandbox/exec:on")
}

/// Disable exec sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_exec() -> c_int {
    stat("/dev/syd/sandbox/exec:off")
}

/// Checks if ioctl sandboxing is enabled.
///
/// Returns true if ioctl sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_ioctl() -> bool {
    stat("/dev/syd/sandbox/ioctl?") == 0
}

/// Enable ioctl sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_ioctl() -> c_int {
    stat("/dev/syd/sandbox/ioctl:on")
}

/// Disable ioctl sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_ioctl() -> c_int {
    stat("/dev/syd/sandbox/ioctl:off")
}

/// Checks if create sandboxing is enabled.
///
/// Returns true if create sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_create() -> bool {
    stat("/dev/syd/sandbox/create?") == 0
}

/// Enable create sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_create() -> c_int {
    stat("/dev/syd/sandbox/create:on")
}

/// Disable create sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_create() -> c_int {
    stat("/dev/syd/sandbox/create:off")
}

/// Checks if delete sandboxing is enabled.
///
/// Returns true if delete sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_delete() -> bool {
    stat("/dev/syd/sandbox/delete?") == 0
}

/// Enable delete sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_delete() -> c_int {
    stat("/dev/syd/sandbox/delete:on")
}

/// Disable delete sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_delete() -> c_int {
    stat("/dev/syd/sandbox/delete:off")
}

/// Checks if rename sandboxing is enabled.
///
/// Returns true if rename sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_rename() -> bool {
    stat("/dev/syd/sandbox/rename?") == 0
}

/// Enable rename sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_rename() -> c_int {
    stat("/dev/syd/sandbox/rename:on")
}

/// Disable rename sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_rename() -> c_int {
    stat("/dev/syd/sandbox/rename:off")
}

/// Checks if symlink sandboxing is enabled.
///
/// Returns true if symlink sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_symlink() -> bool {
    stat("/dev/syd/sandbox/symlink?") == 0
}

/// Enable symlink sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_symlink() -> c_int {
    stat("/dev/syd/sandbox/symlink:on")
}

/// Disable symlink sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_symlink() -> c_int {
    stat("/dev/syd/sandbox/symlink:off")
}

/// Checks if truncate sandboxing is enabled.
///
/// Returns true if truncate sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_truncate() -> bool {
    stat("/dev/syd/sandbox/truncate?") == 0
}

/// Enable truncate sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_truncate() -> c_int {
    stat("/dev/syd/sandbox/truncate:on")
}

/// Disable truncate sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_truncate() -> c_int {
    stat("/dev/syd/sandbox/truncate:off")
}

/// Checks if chdir sandboxing is enabled.
///
/// Returns true if chdir sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_chdir() -> bool {
    stat("/dev/syd/sandbox/chdir?") == 0
}

/// Enable chdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_chdir() -> c_int {
    stat("/dev/syd/sandbox/chdir:on")
}

/// Disable chdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_chdir() -> c_int {
    stat("/dev/syd/sandbox/chdir:off")
}

/// Checks if readdir sandboxing is enabled.
///
/// Returns true if readdir sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_readdir() -> bool {
    stat("/dev/syd/sandbox/readdir?") == 0
}

/// Enable readdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_readdir() -> c_int {
    stat("/dev/syd/sandbox/readdir:on")
}

/// Disable readdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_readdir() -> c_int {
    stat("/dev/syd/sandbox/readdir:off")
}

/// Checks if mkdir sandboxing is enabled.
///
/// Returns true if mkdir sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_mkdir() -> bool {
    stat("/dev/syd/sandbox/mkdir?") == 0
}

/// Enable mkdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_mkdir() -> c_int {
    stat("/dev/syd/sandbox/mkdir:on")
}

/// Disable mkdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_mkdir() -> c_int {
    stat("/dev/syd/sandbox/mkdir:off")
}

/// Checks if chown sandboxing is enabled.
///
/// Returns true if chown sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_chown() -> bool {
    stat("/dev/syd/sandbox/chown?") == 0
}

/// Enable chown sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_chown() -> c_int {
    stat("/dev/syd/sandbox/chown:on")
}

/// Disable chown sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_chown() -> c_int {
    stat("/dev/syd/sandbox/chown:off")
}

/// Checks if chgrp sandboxing is enabled.
///
/// Returns true if chgrp sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_chgrp() -> bool {
    stat("/dev/syd/sandbox/chgrp?") == 0
}

/// Enable chgrp sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_chgrp() -> c_int {
    stat("/dev/syd/sandbox/chgrp:on")
}

/// Disable chgrp sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_chgrp() -> c_int {
    stat("/dev/syd/sandbox/chgrp:off")
}

/// Checks if chmod sandboxing is enabled.
///
/// Returns true if chmod sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_chmod() -> bool {
    stat("/dev/syd/sandbox/chmod?") == 0
}

/// Enable chmod sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_chmod() -> c_int {
    stat("/dev/syd/sandbox/chmod:on")
}

/// Disable chmod sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_chmod() -> c_int {
    stat("/dev/syd/sandbox/chmod:off")
}

/// Checks if chattr sandboxing is enabled.
///
/// Returns true if chattr sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_chattr() -> bool {
    stat("/dev/syd/sandbox/chattr?") == 0
}

/// Enable chattr sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_chattr() -> c_int {
    stat("/dev/syd/sandbox/chattr:on")
}

/// Disable chattr sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_chattr() -> c_int {
    stat("/dev/syd/sandbox/chattr:off")
}

/// Checks if chroot sandboxing is enabled.
///
/// Returns true if chroot sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_chroot() -> bool {
    stat("/dev/syd/sandbox/chroot?") == 0
}

/// Enable chroot sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_chroot() -> c_int {
    stat("/dev/syd/sandbox/chroot:on")
}

/// Disable chroot sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_chroot() -> c_int {
    stat("/dev/syd/sandbox/chroot:off")
}

/// Checks if utime sandboxing is enabled.
///
/// Returns true if utime sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_utime() -> bool {
    stat("/dev/syd/sandbox/utime?") == 0
}

/// Enable utime sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_utime() -> c_int {
    stat("/dev/syd/sandbox/utime:on")
}

/// Disable utime sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_utime() -> c_int {
    stat("/dev/syd/sandbox/utime:off")
}

/// Checks if mkdev sandboxing is enabled.
///
/// Returns true if mkdev sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_mkdev() -> bool {
    stat("/dev/syd/sandbox/mkdev?") == 0
}

/// Enable mkdev sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_mkdev() -> c_int {
    stat("/dev/syd/sandbox/mkdev:on")
}

/// Disable mkdev sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_mkdev() -> c_int {
    stat("/dev/syd/sandbox/mkdev:off")
}

/// Checks if mkfifo sandboxing is enabled.
///
/// Returns true if mkfifo sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_mkfifo() -> bool {
    stat("/dev/syd/sandbox/mkfifo?") == 0
}

/// Enable mkfifo sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_mkfifo() -> c_int {
    stat("/dev/syd/sandbox/mkfifo:on")
}

/// Disable mkfifo sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_mkfifo() -> c_int {
    stat("/dev/syd/sandbox/mkfifo:off")
}

/// Checks if mktemp sandboxing is enabled.
///
/// Returns true if mktemp sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_mktemp() -> bool {
    stat("/dev/syd/sandbox/mktemp?") == 0
}

/// Enable mktemp sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_mktemp() -> c_int {
    stat("/dev/syd/sandbox/mktemp:on")
}

/// Disable mktemp sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_mktemp() -> c_int {
    stat("/dev/syd/sandbox/mktemp:off")
}

/// Checks if net sandboxing is enabled.
///
/// Returns true if net sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_net() -> bool {
    stat("/dev/syd/sandbox/net?") == 0
}

/// Enable net sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_net() -> c_int {
    stat("/dev/syd/sandbox/net:on")
}

/// Disable net sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_net() -> c_int {
    stat("/dev/syd/sandbox/net:off")
}

/// Checks if memory sandboxing is enabled.
///
/// Returns true if memory sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_mem() -> bool {
    stat("/dev/syd/sandbox/mem?") == 0
}

/// Enable memory sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_mem() -> c_int {
    stat("/dev/syd/sandbox/mem:on")
}

/// Disable memory sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_mem() -> c_int {
    stat("/dev/syd/sandbox/mem:off")
}

/// Checks if PID sandboxing is enabled.
///
/// Returns true if PID sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_pid() -> bool {
    stat("/dev/syd/sandbox/pid?") == 0
}

/// Enable PID sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_pid() -> c_int {
    stat("/dev/syd/sandbox/pid:on")
}

/// Disable PID sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_pid() -> c_int {
    stat("/dev/syd/sandbox/pid:off")
}

/// Checks if lock sandboxing is enabled.
///
/// Returns true if lock sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_lock() -> bool {
    stat("/dev/syd/sandbox/lock?") == 0
}

/// Checks if crypt sandboxing is enabled.
///
/// Returns true if crypt sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_crypt() -> bool {
    stat("/dev/syd/sandbox/crypt?") == 0
}

/// Checks if proxy sandboxing is enabled.
///
/// Returns true if proxy sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_proxy() -> bool {
    stat("/dev/syd/sandbox/proxy?") == 0
}

/// Checks if force sandboxing is enabled.
///
/// Returns true if force sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_force() -> bool {
    stat("/dev/syd/sandbox/force?") == 0
}

/// Enable force sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_force() -> c_int {
    stat("/dev/syd/sandbox/force:on")
}

/// Disable force sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_force() -> c_int {
    stat("/dev/syd/sandbox/force:off")
}

/// Checks if TPE sandboxing is enabled.
///
/// Returns true if TPE sandboxing is enabled, false otherwise.
#[no_mangle]
pub extern "C" fn syd_enabled_tpe() -> bool {
    stat("/dev/syd/sandbox/tpe?") == 0
}

/// Enable TPE sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_enable_tpe() -> c_int {
    stat("/dev/syd/sandbox/tpe:on")
}

/// Disable TPE sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_disable_tpe() -> c_int {
    stat("/dev/syd/sandbox/tpe:off")
}

/// Set the default action for Stat Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_stat(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/stat:allow",
        action_t::WARN => "/dev/syd/default/stat:warn",
        action_t::FILTER => "/dev/syd/default/stat:filter",
        action_t::DENY => "/dev/syd/default/stat:deny",
        action_t::PANIC => "/dev/syd/default/stat:panic",
        action_t::STOP => "/dev/syd/default/stat:stop",
        action_t::KILL => "/dev/syd/default/stat:kill",
        action_t::EXIT => "/dev/syd/default/stat:exit",
    })
}

/// Set the default action for Read Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_read(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/read:allow",
        action_t::WARN => "/dev/syd/default/read:warn",
        action_t::FILTER => "/dev/syd/default/read:filter",
        action_t::DENY => "/dev/syd/default/read:deny",
        action_t::PANIC => "/dev/syd/default/read:panic",
        action_t::STOP => "/dev/syd/default/read:stop",
        action_t::KILL => "/dev/syd/default/read:kill",
        action_t::EXIT => "/dev/syd/default/read:exit",
    })
}

/// Set the default action for Write Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_write(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/write:allow",
        action_t::WARN => "/dev/syd/default/write:warn",
        action_t::FILTER => "/dev/syd/default/write:filter",
        action_t::DENY => "/dev/syd/default/write:deny",
        action_t::PANIC => "/dev/syd/default/write:panic",
        action_t::STOP => "/dev/syd/default/write:stop",
        action_t::KILL => "/dev/syd/default/write:kill",
        action_t::EXIT => "/dev/syd/default/write:exit",
    })
}

/// Set the default action for Exec Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_exec(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/exec:allow",
        action_t::WARN => "/dev/syd/default/exec:warn",
        action_t::FILTER => "/dev/syd/default/exec:filter",
        action_t::DENY => "/dev/syd/default/exec:deny",
        action_t::PANIC => "/dev/syd/default/exec:panic",
        action_t::STOP => "/dev/syd/default/exec:stop",
        action_t::KILL => "/dev/syd/default/exec:kill",
        action_t::EXIT => "/dev/syd/default/exec:exit",
    })
}

/// Set the default action for Ioctl Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_ioctl(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/ioctl:allow",
        action_t::WARN => "/dev/syd/default/ioctl:warn",
        action_t::FILTER => "/dev/syd/default/ioctl:filter",
        action_t::DENY => "/dev/syd/default/ioctl:deny",
        action_t::PANIC => "/dev/syd/default/ioctl:panic",
        action_t::STOP => "/dev/syd/default/ioctl:stop",
        action_t::KILL => "/dev/syd/default/ioctl:kill",
        action_t::EXIT => "/dev/syd/default/ioctl:exit",
    })
}

/// Set the default action for Create Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_create(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/create:allow",
        action_t::WARN => "/dev/syd/default/create:warn",
        action_t::FILTER => "/dev/syd/default/create:filter",
        action_t::DENY => "/dev/syd/default/create:deny",
        action_t::PANIC => "/dev/syd/default/create:panic",
        action_t::STOP => "/dev/syd/default/create:stop",
        action_t::KILL => "/dev/syd/default/create:kill",
        action_t::EXIT => "/dev/syd/default/create:exit",
    })
}

/// Set the default action for Delete Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_delete(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/delete:allow",
        action_t::WARN => "/dev/syd/default/delete:warn",
        action_t::FILTER => "/dev/syd/default/delete:filter",
        action_t::DENY => "/dev/syd/default/delete:deny",
        action_t::PANIC => "/dev/syd/default/delete:panic",
        action_t::STOP => "/dev/syd/default/delete:stop",
        action_t::KILL => "/dev/syd/default/delete:kill",
        action_t::EXIT => "/dev/syd/default/delete:exit",
    })
}

/// Set the default action for Rename Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_rename(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/rename:allow",
        action_t::WARN => "/dev/syd/default/rename:warn",
        action_t::FILTER => "/dev/syd/default/rename:filter",
        action_t::DENY => "/dev/syd/default/rename:deny",
        action_t::PANIC => "/dev/syd/default/rename:panic",
        action_t::STOP => "/dev/syd/default/rename:stop",
        action_t::KILL => "/dev/syd/default/rename:kill",
        action_t::EXIT => "/dev/syd/default/rename:exit",
    })
}

/// Set the default action for Symlink Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_symlink(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/symlink:allow",
        action_t::WARN => "/dev/syd/default/symlink:warn",
        action_t::FILTER => "/dev/syd/default/symlink:filter",
        action_t::DENY => "/dev/syd/default/symlink:deny",
        action_t::PANIC => "/dev/syd/default/symlink:panic",
        action_t::STOP => "/dev/syd/default/symlink:stop",
        action_t::KILL => "/dev/syd/default/symlink:kill",
        action_t::EXIT => "/dev/syd/default/symlink:exit",
    })
}

/// Set the default action for Truncate Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_truncate(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/truncate:allow",
        action_t::WARN => "/dev/syd/default/truncate:warn",
        action_t::FILTER => "/dev/syd/default/truncate:filter",
        action_t::DENY => "/dev/syd/default/truncate:deny",
        action_t::PANIC => "/dev/syd/default/truncate:panic",
        action_t::STOP => "/dev/syd/default/truncate:stop",
        action_t::KILL => "/dev/syd/default/truncate:kill",
        action_t::EXIT => "/dev/syd/default/truncate:exit",
    })
}

/// Set the default action for Chdir Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_chdir(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/chdir:allow",
        action_t::WARN => "/dev/syd/default/chdir:warn",
        action_t::FILTER => "/dev/syd/default/chdir:filter",
        action_t::DENY => "/dev/syd/default/chdir:deny",
        action_t::PANIC => "/dev/syd/default/chdir:panic",
        action_t::STOP => "/dev/syd/default/chdir:stop",
        action_t::KILL => "/dev/syd/default/chdir:kill",
        action_t::EXIT => "/dev/syd/default/chdir:exit",
    })
}

/// Set the default action for Readdir Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_readdir(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/readdir:allow",
        action_t::WARN => "/dev/syd/default/readdir:warn",
        action_t::FILTER => "/dev/syd/default/readdir:filter",
        action_t::DENY => "/dev/syd/default/readdir:deny",
        action_t::PANIC => "/dev/syd/default/readdir:panic",
        action_t::STOP => "/dev/syd/default/readdir:stop",
        action_t::KILL => "/dev/syd/default/readdir:kill",
        action_t::EXIT => "/dev/syd/default/readdir:exit",
    })
}

/// Set the default action for Mkdir Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_mkdir(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/mkdir:allow",
        action_t::WARN => "/dev/syd/default/mkdir:warn",
        action_t::FILTER => "/dev/syd/default/mkdir:filter",
        action_t::DENY => "/dev/syd/default/mkdir:deny",
        action_t::PANIC => "/dev/syd/default/mkdir:panic",
        action_t::STOP => "/dev/syd/default/mkdir:stop",
        action_t::KILL => "/dev/syd/default/mkdir:kill",
        action_t::EXIT => "/dev/syd/default/mkdir:exit",
    })
}

/// Set the default action for Chown Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_chown(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/chown:allow",
        action_t::WARN => "/dev/syd/default/chown:warn",
        action_t::FILTER => "/dev/syd/default/chown:filter",
        action_t::DENY => "/dev/syd/default/chown:deny",
        action_t::PANIC => "/dev/syd/default/chown:panic",
        action_t::STOP => "/dev/syd/default/chown:stop",
        action_t::KILL => "/dev/syd/default/chown:kill",
        action_t::EXIT => "/dev/syd/default/chown:exit",
    })
}

/// Set the default action for Chgrp Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_chgrp(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/chgrp:allow",
        action_t::WARN => "/dev/syd/default/chgrp:warn",
        action_t::FILTER => "/dev/syd/default/chgrp:filter",
        action_t::DENY => "/dev/syd/default/chgrp:deny",
        action_t::PANIC => "/dev/syd/default/chgrp:panic",
        action_t::STOP => "/dev/syd/default/chgrp:stop",
        action_t::KILL => "/dev/syd/default/chgrp:kill",
        action_t::EXIT => "/dev/syd/default/chgrp:exit",
    })
}

/// Set the default action for Chmod Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_chmod(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/chmod:allow",
        action_t::WARN => "/dev/syd/default/chmod:warn",
        action_t::FILTER => "/dev/syd/default/chmod:filter",
        action_t::DENY => "/dev/syd/default/chmod:deny",
        action_t::PANIC => "/dev/syd/default/chmod:panic",
        action_t::STOP => "/dev/syd/default/chmod:stop",
        action_t::KILL => "/dev/syd/default/chmod:kill",
        action_t::EXIT => "/dev/syd/default/chmod:exit",
    })
}

/// Set the default action for Chattr Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_chattr(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/chattr:allow",
        action_t::WARN => "/dev/syd/default/chattr:warn",
        action_t::FILTER => "/dev/syd/default/chattr:filter",
        action_t::DENY => "/dev/syd/default/chattr:deny",
        action_t::PANIC => "/dev/syd/default/chattr:panic",
        action_t::STOP => "/dev/syd/default/chattr:stop",
        action_t::KILL => "/dev/syd/default/chattr:kill",
        action_t::EXIT => "/dev/syd/default/chattr:exit",
    })
}

/// Set the default action for Chroot Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_chroot(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/chroot:allow",
        action_t::WARN => "/dev/syd/default/chroot:warn",
        action_t::FILTER => "/dev/syd/default/chroot:filter",
        action_t::DENY => "/dev/syd/default/chroot:deny",
        action_t::PANIC => "/dev/syd/default/chroot:panic",
        action_t::STOP => "/dev/syd/default/chroot:stop",
        action_t::KILL => "/dev/syd/default/chroot:kill",
        action_t::EXIT => "/dev/syd/default/chroot:exit",
    })
}

/// Set the default action for Utime Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_utime(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/utime:allow",
        action_t::WARN => "/dev/syd/default/utime:warn",
        action_t::FILTER => "/dev/syd/default/utime:filter",
        action_t::DENY => "/dev/syd/default/utime:deny",
        action_t::PANIC => "/dev/syd/default/utime:panic",
        action_t::STOP => "/dev/syd/default/utime:stop",
        action_t::KILL => "/dev/syd/default/utime:kill",
        action_t::EXIT => "/dev/syd/default/utime:exit",
    })
}

/// Set the default action for Mkdev Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_mkdev(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/mkdev:allow",
        action_t::WARN => "/dev/syd/default/mkdev:warn",
        action_t::FILTER => "/dev/syd/default/mkdev:filter",
        action_t::DENY => "/dev/syd/default/mkdev:deny",
        action_t::PANIC => "/dev/syd/default/mkdev:panic",
        action_t::STOP => "/dev/syd/default/mkdev:stop",
        action_t::KILL => "/dev/syd/default/mkdev:kill",
        action_t::EXIT => "/dev/syd/default/mkdev:exit",
    })
}

/// Set the default action for Mkfifo Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_mkfifo(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/mkfifo:allow",
        action_t::WARN => "/dev/syd/default/mkfifo:warn",
        action_t::FILTER => "/dev/syd/default/mkfifo:filter",
        action_t::DENY => "/dev/syd/default/mkfifo:deny",
        action_t::PANIC => "/dev/syd/default/mkfifo:panic",
        action_t::STOP => "/dev/syd/default/mkfifo:stop",
        action_t::KILL => "/dev/syd/default/mkfifo:kill",
        action_t::EXIT => "/dev/syd/default/mkfifo:exit",
    })
}

/// Set the default action for Mktemp Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_mktemp(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/mktemp:allow",
        action_t::WARN => "/dev/syd/default/mktemp:warn",
        action_t::FILTER => "/dev/syd/default/mktemp:filter",
        action_t::DENY => "/dev/syd/default/mktemp:deny",
        action_t::PANIC => "/dev/syd/default/mktemp:panic",
        action_t::STOP => "/dev/syd/default/mktemp:stop",
        action_t::KILL => "/dev/syd/default/mktemp:kill",
        action_t::EXIT => "/dev/syd/default/mktemp:exit",
    })
}

/// Set the default action for Network Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_net(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/net:allow",
        action_t::WARN => "/dev/syd/default/net:warn",
        action_t::FILTER => "/dev/syd/default/net:filter",
        action_t::DENY => "/dev/syd/default/net:deny",
        action_t::PANIC => "/dev/syd/default/net:panic",
        action_t::STOP => "/dev/syd/default/net:stop",
        action_t::KILL => "/dev/syd/default/net:kill",
        action_t::EXIT => "/dev/syd/default/net:exit",
    })
}

/// Set the default action for IP blocklist violations.
#[no_mangle]
pub extern "C" fn syd_default_block(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/block:allow",
        action_t::WARN => "/dev/syd/default/block:warn",
        action_t::FILTER => "/dev/syd/default/block:filter",
        action_t::DENY => "/dev/syd/default/block:deny",
        action_t::PANIC => "/dev/syd/default/block:panic",
        action_t::STOP => "/dev/syd/default/block:stop",
        action_t::KILL => "/dev/syd/default/block:kill",
        action_t::EXIT => "/dev/syd/default/block:exit",
    })
}

/// Set the default action for Memory Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_mem(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/mem:allow",
        action_t::WARN => "/dev/syd/default/mem:warn",
        action_t::FILTER => "/dev/syd/default/mem:filter",
        action_t::DENY => "/dev/syd/default/mem:deny",
        action_t::PANIC => "/dev/syd/default/mem:panic",
        action_t::STOP => "/dev/syd/default/mem:stop",
        action_t::KILL => "/dev/syd/default/mem:kill",
        action_t::EXIT => "/dev/syd/default/mem:exit",
    })
}

/// Set the default action for PID Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_pid(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/pid:allow",
        action_t::WARN => "/dev/syd/default/pid:warn",
        action_t::FILTER => "/dev/syd/default/pid:filter",
        action_t::DENY => "/dev/syd/default/pid:deny",
        action_t::PANIC => "/dev/syd/default/pid:panic",
        action_t::STOP => "/dev/syd/default/pid:stop",
        action_t::KILL => "/dev/syd/default/pid:kill",
        action_t::EXIT => "/dev/syd/default/pid:exit",
    })
}

/// Set the default action for Force Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_force(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/force:allow",
        action_t::WARN => "/dev/syd/default/force:warn",
        action_t::FILTER => "/dev/syd/default/force:filter",
        action_t::DENY => "/dev/syd/default/force:deny",
        action_t::PANIC => "/dev/syd/default/force:panic",
        action_t::STOP => "/dev/syd/default/force:stop",
        action_t::KILL => "/dev/syd/default/force:kill",
        action_t::EXIT => "/dev/syd/default/force:exit",
    })
}

/// Set the default action for SegvGuard
#[no_mangle]
pub extern "C" fn syd_default_segvguard(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/segvguard:allow",
        action_t::WARN => "/dev/syd/default/segvguard:warn",
        action_t::FILTER => "/dev/syd/default/segvguard:filter",
        action_t::DENY => "/dev/syd/default/segvguard:deny",
        action_t::PANIC => "/dev/syd/default/segvguard:panic",
        action_t::STOP => "/dev/syd/default/segvguard:stop",
        action_t::KILL => "/dev/syd/default/segvguard:kill",
        action_t::EXIT => "/dev/syd/default/segvguard:exit",
    })
}

/// Set the default action for TPE Sandboxing.
#[no_mangle]
pub extern "C" fn syd_default_tpe(action: action_t) -> c_int {
    // Convert action_t enum to corresponding action string.
    stat(match action {
        action_t::ALLOW => "/dev/syd/default/tpe:allow",
        action_t::WARN => "/dev/syd/default/tpe:warn",
        action_t::FILTER => "/dev/syd/default/tpe:filter",
        action_t::DENY => "/dev/syd/default/tpe:deny",
        action_t::PANIC => "/dev/syd/default/tpe:panic",
        action_t::STOP => "/dev/syd/default/tpe:stop",
        action_t::KILL => "/dev/syd/default/tpe:kill",
        action_t::EXIT => "/dev/syd/default/tpe:exit",
    })
}

/// Adds a request to the _ioctl_(2) denylist.
#[no_mangle]
pub extern "C" fn syd_ioctl_deny(request: u64) -> c_int {
    stat(&format!("/dev/syd/ioctl/deny+{request}"))
}

/// Adds an entry to the Integrity Force map for Force Sandboxing.
///
/// # Safety
///
/// This function is marked `unsafe` because it dereferences raw
/// pointers, which is inherently unsafe in Rust.
///
/// The caller must ensure the following conditions are met to safely
/// use this function:
///
/// 1. The `path` pointer must point to a valid, null-terminated C-style
///    string.
/// 2. The `hash` pointer must point to a valid, null-terminated C-style
///    string.
#[no_mangle]
pub unsafe extern "C" fn syd_force_add(
    path: *const c_char,
    hash: *const c_char,
    action: action_t,
) -> c_int {
    if path.is_null() || hash.is_null() {
        return -EFAULT;
    }

    // SAFETY: Trust that `path` and `hash` are a null-terminated strings.
    let path = unsafe { CStr::from_ptr(path) };
    // SAFETY: ditto
    let hash = unsafe { CStr::from_ptr(hash) };
    let path = match path.to_str() {
        Ok(s) => s,
        Err(_) => return -EINVAL,
    };
    let hash = match hash.to_str() {
        Ok(s) => s,
        Err(_) => return -EINVAL,
    };

    // Convert action_t enum to corresponding action string.
    let action = match action {
        action_t::WARN => "warn",
        action_t::STOP => "stop",
        action_t::KILL => "kill",
        _ => return -EINVAL,
    };

    // Call the stat function with the formatted string.
    stat(format!("/dev/syd/force+{path}:{hash}:{action}"))
}

/// Removes an entry from the Integrity Force map for Force Sandboxing.
/// # Safety
///
/// This function is marked `unsafe` because it dereferences raw
/// pointers, which is inherently unsafe in Rust.
///
/// The caller must ensure the following conditions are met to safely
/// use this function:
///
/// 1. The `path` pointer must point to a valid, null-terminated C-style
///    string.
#[no_mangle]
pub unsafe extern "C" fn syd_force_del(path: *const c_char) -> c_int {
    if path.is_null() {
        return -EFAULT;
    }

    // SAFETY: Trust that `path` is a null-terminated string.
    let path = unsafe { CStr::from_ptr(path) };
    let path = match path.to_str() {
        Ok(s) => s,
        Err(_) => return -EINVAL,
    };

    // Call the stat function with the formatted string.
    stat(format!("/dev/syd/force-{path}"))
}

/// Clears the Integrity Force map for Force Sandboxing.
#[no_mangle]
pub extern "C" fn syd_force_clr() -> c_int {
    stat("/dev/syd/force^")
}

/// Adds to the given actionlist of stat sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_stat_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/stat", glob, b'+'),
        action_t::WARN => esyd("warn/stat", glob, b'+'),
        action_t::FILTER => esyd("filter/stat", glob, b'+'),
        action_t::DENY => esyd("deny/stat", glob, b'+'),
        action_t::PANIC => esyd("panic/stat", glob, b'+'),
        action_t::STOP => esyd("stop/stat", glob, b'+'),
        action_t::KILL => esyd("kill/stat", glob, b'+'),
        action_t::EXIT => esyd("exit/stat", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// stat sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_stat_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/stat", glob, b'-'),
        action_t::WARN => esyd("warn/stat", glob, b'-'),
        action_t::FILTER => esyd("filter/stat", glob, b'-'),
        action_t::DENY => esyd("deny/stat", glob, b'-'),
        action_t::PANIC => esyd("panic/stat", glob, b'-'),
        action_t::STOP => esyd("stop/stat", glob, b'-'),
        action_t::KILL => esyd("kill/stat", glob, b'-'),
        action_t::EXIT => esyd("exit/stat", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of stat sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_stat_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/stat", glob, b'^'),
        action_t::WARN => esyd("warn/stat", glob, b'^'),
        action_t::FILTER => esyd("filter/stat", glob, b'^'),
        action_t::DENY => esyd("deny/stat", glob, b'^'),
        action_t::PANIC => esyd("panic/stat", glob, b'^'),
        action_t::STOP => esyd("stop/stat", glob, b'^'),
        action_t::KILL => esyd("kill/stat", glob, b'^'),
        action_t::EXIT => esyd("exit/stat", glob, b'^'),
    }
}

/// Adds to the given actionlist of read sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_read_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/read", glob, b'+'),
        action_t::WARN => esyd("warn/read", glob, b'+'),
        action_t::FILTER => esyd("filter/read", glob, b'+'),
        action_t::DENY => esyd("deny/read", glob, b'+'),
        action_t::PANIC => esyd("panic/read", glob, b'+'),
        action_t::STOP => esyd("stop/read", glob, b'+'),
        action_t::KILL => esyd("kill/read", glob, b'+'),
        action_t::EXIT => esyd("exit/read", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// read sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_read_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/read", glob, b'-'),
        action_t::WARN => esyd("warn/read", glob, b'-'),
        action_t::FILTER => esyd("filter/read", glob, b'-'),
        action_t::DENY => esyd("deny/read", glob, b'-'),
        action_t::PANIC => esyd("panic/read", glob, b'-'),
        action_t::STOP => esyd("stop/read", glob, b'-'),
        action_t::KILL => esyd("kill/read", glob, b'-'),
        action_t::EXIT => esyd("exit/read", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of read sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_read_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/read", glob, b'^'),
        action_t::WARN => esyd("warn/read", glob, b'^'),
        action_t::FILTER => esyd("filter/read", glob, b'^'),
        action_t::DENY => esyd("deny/read", glob, b'^'),
        action_t::PANIC => esyd("panic/read", glob, b'^'),
        action_t::STOP => esyd("stop/read", glob, b'^'),
        action_t::KILL => esyd("kill/read", glob, b'^'),
        action_t::EXIT => esyd("exit/read", glob, b'^'),
    }
}

/// Adds to the given actionlist of write sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_write_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/write", glob, b'+'),
        action_t::WARN => esyd("warn/write", glob, b'+'),
        action_t::FILTER => esyd("filter/write", glob, b'+'),
        action_t::DENY => esyd("deny/write", glob, b'+'),
        action_t::PANIC => esyd("panic/write", glob, b'+'),
        action_t::STOP => esyd("stop/write", glob, b'+'),
        action_t::KILL => esyd("kill/write", glob, b'+'),
        action_t::EXIT => esyd("exit/write", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// write sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_write_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/write", glob, b'-'),
        action_t::WARN => esyd("warn/write", glob, b'-'),
        action_t::FILTER => esyd("filter/write", glob, b'-'),
        action_t::DENY => esyd("deny/write", glob, b'-'),
        action_t::PANIC => esyd("panic/write", glob, b'-'),
        action_t::STOP => esyd("stop/write", glob, b'-'),
        action_t::KILL => esyd("kill/write", glob, b'-'),
        action_t::EXIT => esyd("exit/write", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of write sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_write_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/write", glob, b'^'),
        action_t::WARN => esyd("warn/write", glob, b'^'),
        action_t::FILTER => esyd("filter/write", glob, b'^'),
        action_t::DENY => esyd("deny/write", glob, b'^'),
        action_t::PANIC => esyd("panic/write", glob, b'^'),
        action_t::STOP => esyd("stop/write", glob, b'^'),
        action_t::KILL => esyd("kill/write", glob, b'^'),
        action_t::EXIT => esyd("exit/write", glob, b'^'),
    }
}

/// Adds to the given actionlist of exec sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_exec_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/exec", glob, b'+'),
        action_t::WARN => esyd("warn/exec", glob, b'+'),
        action_t::FILTER => esyd("filter/exec", glob, b'+'),
        action_t::DENY => esyd("deny/exec", glob, b'+'),
        action_t::PANIC => esyd("panic/exec", glob, b'+'),
        action_t::STOP => esyd("stop/exec", glob, b'+'),
        action_t::KILL => esyd("kill/exec", glob, b'+'),
        action_t::EXIT => esyd("exit/exec", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// exec sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_exec_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/exec", glob, b'-'),
        action_t::WARN => esyd("warn/exec", glob, b'-'),
        action_t::FILTER => esyd("filter/exec", glob, b'-'),
        action_t::DENY => esyd("deny/exec", glob, b'-'),
        action_t::PANIC => esyd("panic/exec", glob, b'-'),
        action_t::STOP => esyd("stop/exec", glob, b'-'),
        action_t::KILL => esyd("kill/exec", glob, b'-'),
        action_t::EXIT => esyd("exit/exec", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of exec sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_exec_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/exec", glob, b'^'),
        action_t::WARN => esyd("warn/exec", glob, b'^'),
        action_t::FILTER => esyd("filter/exec", glob, b'^'),
        action_t::DENY => esyd("deny/exec", glob, b'^'),
        action_t::PANIC => esyd("panic/exec", glob, b'^'),
        action_t::STOP => esyd("stop/exec", glob, b'^'),
        action_t::KILL => esyd("kill/exec", glob, b'^'),
        action_t::EXIT => esyd("exit/exec", glob, b'^'),
    }
}

/// Adds to the given actionlist of ioctl sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_ioctl_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/ioctl", glob, b'+'),
        action_t::WARN => esyd("warn/ioctl", glob, b'+'),
        action_t::FILTER => esyd("filter/ioctl", glob, b'+'),
        action_t::DENY => esyd("deny/ioctl", glob, b'+'),
        action_t::PANIC => esyd("panic/ioctl", glob, b'+'),
        action_t::STOP => esyd("stop/ioctl", glob, b'+'),
        action_t::KILL => esyd("kill/ioctl", glob, b'+'),
        action_t::EXIT => esyd("exit/ioctl", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// ioctl sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_ioctl_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/ioctl", glob, b'-'),
        action_t::WARN => esyd("warn/ioctl", glob, b'-'),
        action_t::FILTER => esyd("filter/ioctl", glob, b'-'),
        action_t::DENY => esyd("deny/ioctl", glob, b'-'),
        action_t::PANIC => esyd("panic/ioctl", glob, b'-'),
        action_t::STOP => esyd("stop/ioctl", glob, b'-'),
        action_t::KILL => esyd("kill/ioctl", glob, b'-'),
        action_t::EXIT => esyd("exit/ioctl", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of ioctl sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_ioctl_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/ioctl", glob, b'^'),
        action_t::WARN => esyd("warn/ioctl", glob, b'^'),
        action_t::FILTER => esyd("filter/ioctl", glob, b'^'),
        action_t::DENY => esyd("deny/ioctl", glob, b'^'),
        action_t::PANIC => esyd("panic/ioctl", glob, b'^'),
        action_t::STOP => esyd("stop/ioctl", glob, b'^'),
        action_t::KILL => esyd("kill/ioctl", glob, b'^'),
        action_t::EXIT => esyd("exit/ioctl", glob, b'^'),
    }
}

/// Adds to the given actionlist of create sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_create_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/create", glob, b'+'),
        action_t::WARN => esyd("warn/create", glob, b'+'),
        action_t::FILTER => esyd("filter/create", glob, b'+'),
        action_t::DENY => esyd("deny/create", glob, b'+'),
        action_t::PANIC => esyd("panic/create", glob, b'+'),
        action_t::STOP => esyd("stop/create", glob, b'+'),
        action_t::KILL => esyd("kill/create", glob, b'+'),
        action_t::EXIT => esyd("exit/create", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// create sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_create_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/create", glob, b'-'),
        action_t::WARN => esyd("warn/create", glob, b'-'),
        action_t::FILTER => esyd("filter/create", glob, b'-'),
        action_t::DENY => esyd("deny/create", glob, b'-'),
        action_t::PANIC => esyd("panic/create", glob, b'-'),
        action_t::STOP => esyd("stop/create", glob, b'-'),
        action_t::KILL => esyd("kill/create", glob, b'-'),
        action_t::EXIT => esyd("exit/create", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of create sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_create_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/create", glob, b'^'),
        action_t::WARN => esyd("warn/create", glob, b'^'),
        action_t::FILTER => esyd("filter/create", glob, b'^'),
        action_t::DENY => esyd("deny/create", glob, b'^'),
        action_t::PANIC => esyd("panic/create", glob, b'^'),
        action_t::STOP => esyd("stop/create", glob, b'^'),
        action_t::KILL => esyd("kill/create", glob, b'^'),
        action_t::EXIT => esyd("exit/create", glob, b'^'),
    }
}

/// Adds to the given actionlist of delete sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_delete_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/delete", glob, b'+'),
        action_t::WARN => esyd("warn/delete", glob, b'+'),
        action_t::FILTER => esyd("filter/delete", glob, b'+'),
        action_t::DENY => esyd("deny/delete", glob, b'+'),
        action_t::PANIC => esyd("panic/delete", glob, b'+'),
        action_t::STOP => esyd("stop/delete", glob, b'+'),
        action_t::KILL => esyd("kill/delete", glob, b'+'),
        action_t::EXIT => esyd("exit/delete", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// delete sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_delete_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/delete", glob, b'-'),
        action_t::WARN => esyd("warn/delete", glob, b'-'),
        action_t::FILTER => esyd("filter/delete", glob, b'-'),
        action_t::DENY => esyd("deny/delete", glob, b'-'),
        action_t::PANIC => esyd("panic/delete", glob, b'-'),
        action_t::STOP => esyd("stop/delete", glob, b'-'),
        action_t::KILL => esyd("kill/delete", glob, b'-'),
        action_t::EXIT => esyd("exit/delete", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of delete sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_delete_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/delete", glob, b'^'),
        action_t::WARN => esyd("warn/delete", glob, b'^'),
        action_t::FILTER => esyd("filter/delete", glob, b'^'),
        action_t::DENY => esyd("deny/delete", glob, b'^'),
        action_t::PANIC => esyd("panic/delete", glob, b'^'),
        action_t::STOP => esyd("stop/delete", glob, b'^'),
        action_t::KILL => esyd("kill/delete", glob, b'^'),
        action_t::EXIT => esyd("exit/delete", glob, b'^'),
    }
}

/// Adds to the given actionlist of rename sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_rename_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/rename", glob, b'+'),
        action_t::WARN => esyd("warn/rename", glob, b'+'),
        action_t::FILTER => esyd("filter/rename", glob, b'+'),
        action_t::DENY => esyd("deny/rename", glob, b'+'),
        action_t::PANIC => esyd("panic/rename", glob, b'+'),
        action_t::STOP => esyd("stop/rename", glob, b'+'),
        action_t::KILL => esyd("kill/rename", glob, b'+'),
        action_t::EXIT => esyd("exit/rename", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// rename sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_rename_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/rename", glob, b'-'),
        action_t::WARN => esyd("warn/rename", glob, b'-'),
        action_t::FILTER => esyd("filter/rename", glob, b'-'),
        action_t::DENY => esyd("deny/rename", glob, b'-'),
        action_t::PANIC => esyd("panic/rename", glob, b'-'),
        action_t::STOP => esyd("stop/rename", glob, b'-'),
        action_t::KILL => esyd("kill/rename", glob, b'-'),
        action_t::EXIT => esyd("exit/rename", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of rename sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_rename_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/rename", glob, b'^'),
        action_t::WARN => esyd("warn/rename", glob, b'^'),
        action_t::FILTER => esyd("filter/rename", glob, b'^'),
        action_t::DENY => esyd("deny/rename", glob, b'^'),
        action_t::PANIC => esyd("panic/rename", glob, b'^'),
        action_t::STOP => esyd("stop/rename", glob, b'^'),
        action_t::KILL => esyd("kill/rename", glob, b'^'),
        action_t::EXIT => esyd("exit/rename", glob, b'^'),
    }
}

/// Adds to the given actionlist of symlink sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_symlink_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/symlink", glob, b'+'),
        action_t::WARN => esyd("warn/symlink", glob, b'+'),
        action_t::FILTER => esyd("filter/symlink", glob, b'+'),
        action_t::DENY => esyd("deny/symlink", glob, b'+'),
        action_t::PANIC => esyd("panic/symlink", glob, b'+'),
        action_t::STOP => esyd("stop/symlink", glob, b'+'),
        action_t::KILL => esyd("kill/symlink", glob, b'+'),
        action_t::EXIT => esyd("exit/symlink", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// symlink sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_symlink_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/symlink", glob, b'-'),
        action_t::WARN => esyd("warn/symlink", glob, b'-'),
        action_t::FILTER => esyd("filter/symlink", glob, b'-'),
        action_t::DENY => esyd("deny/symlink", glob, b'-'),
        action_t::PANIC => esyd("panic/symlink", glob, b'-'),
        action_t::STOP => esyd("stop/symlink", glob, b'-'),
        action_t::KILL => esyd("kill/symlink", glob, b'-'),
        action_t::EXIT => esyd("exit/symlink", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of symlink sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_symlink_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/symlink", glob, b'^'),
        action_t::WARN => esyd("warn/symlink", glob, b'^'),
        action_t::FILTER => esyd("filter/symlink", glob, b'^'),
        action_t::DENY => esyd("deny/symlink", glob, b'^'),
        action_t::PANIC => esyd("panic/symlink", glob, b'^'),
        action_t::STOP => esyd("stop/symlink", glob, b'^'),
        action_t::KILL => esyd("kill/symlink", glob, b'^'),
        action_t::EXIT => esyd("exit/symlink", glob, b'^'),
    }
}

/// Adds to the given actionlist of truncate sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_truncate_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/truncate", glob, b'+'),
        action_t::WARN => esyd("warn/truncate", glob, b'+'),
        action_t::FILTER => esyd("filter/truncate", glob, b'+'),
        action_t::DENY => esyd("deny/truncate", glob, b'+'),
        action_t::PANIC => esyd("panic/truncate", glob, b'+'),
        action_t::STOP => esyd("stop/truncate", glob, b'+'),
        action_t::KILL => esyd("kill/truncate", glob, b'+'),
        action_t::EXIT => esyd("exit/truncate", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// truncate sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_truncate_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/truncate", glob, b'-'),
        action_t::WARN => esyd("warn/truncate", glob, b'-'),
        action_t::FILTER => esyd("filter/truncate", glob, b'-'),
        action_t::DENY => esyd("deny/truncate", glob, b'-'),
        action_t::PANIC => esyd("panic/truncate", glob, b'-'),
        action_t::STOP => esyd("stop/truncate", glob, b'-'),
        action_t::KILL => esyd("kill/truncate", glob, b'-'),
        action_t::EXIT => esyd("exit/truncate", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of truncate sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_truncate_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/truncate", glob, b'^'),
        action_t::WARN => esyd("warn/truncate", glob, b'^'),
        action_t::FILTER => esyd("filter/truncate", glob, b'^'),
        action_t::DENY => esyd("deny/truncate", glob, b'^'),
        action_t::PANIC => esyd("panic/truncate", glob, b'^'),
        action_t::STOP => esyd("stop/truncate", glob, b'^'),
        action_t::KILL => esyd("kill/truncate", glob, b'^'),
        action_t::EXIT => esyd("exit/truncate", glob, b'^'),
    }
}

/// Adds to the given actionlist of chdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chdir_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chdir", glob, b'+'),
        action_t::WARN => esyd("warn/chdir", glob, b'+'),
        action_t::FILTER => esyd("filter/chdir", glob, b'+'),
        action_t::DENY => esyd("deny/chdir", glob, b'+'),
        action_t::PANIC => esyd("panic/chdir", glob, b'+'),
        action_t::STOP => esyd("stop/chdir", glob, b'+'),
        action_t::KILL => esyd("kill/chdir", glob, b'+'),
        action_t::EXIT => esyd("exit/chdir", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// chdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chdir_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chdir", glob, b'-'),
        action_t::WARN => esyd("warn/chdir", glob, b'-'),
        action_t::FILTER => esyd("filter/chdir", glob, b'-'),
        action_t::DENY => esyd("deny/chdir", glob, b'-'),
        action_t::PANIC => esyd("panic/chdir", glob, b'-'),
        action_t::STOP => esyd("stop/chdir", glob, b'-'),
        action_t::KILL => esyd("kill/chdir", glob, b'-'),
        action_t::EXIT => esyd("exit/chdir", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of chdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chdir_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chdir", glob, b'^'),
        action_t::WARN => esyd("warn/chdir", glob, b'^'),
        action_t::FILTER => esyd("filter/chdir", glob, b'^'),
        action_t::DENY => esyd("deny/chdir", glob, b'^'),
        action_t::PANIC => esyd("panic/chdir", glob, b'^'),
        action_t::STOP => esyd("stop/chdir", glob, b'^'),
        action_t::KILL => esyd("kill/chdir", glob, b'^'),
        action_t::EXIT => esyd("exit/chdir", glob, b'^'),
    }
}

/// Adds to the given actionlist of readdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_readdir_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/readdir", glob, b'+'),
        action_t::WARN => esyd("warn/readdir", glob, b'+'),
        action_t::FILTER => esyd("filter/readdir", glob, b'+'),
        action_t::DENY => esyd("deny/readdir", glob, b'+'),
        action_t::PANIC => esyd("panic/readdir", glob, b'+'),
        action_t::STOP => esyd("stop/readdir", glob, b'+'),
        action_t::KILL => esyd("kill/readdir", glob, b'+'),
        action_t::EXIT => esyd("exit/readdir", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// readdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_readdir_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/readdir", glob, b'-'),
        action_t::WARN => esyd("warn/readdir", glob, b'-'),
        action_t::FILTER => esyd("filter/readdir", glob, b'-'),
        action_t::DENY => esyd("deny/readdir", glob, b'-'),
        action_t::PANIC => esyd("panic/readdir", glob, b'-'),
        action_t::STOP => esyd("stop/readdir", glob, b'-'),
        action_t::KILL => esyd("kill/readdir", glob, b'-'),
        action_t::EXIT => esyd("exit/readdir", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of readdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_readdir_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/readdir", glob, b'^'),
        action_t::WARN => esyd("warn/readdir", glob, b'^'),
        action_t::FILTER => esyd("filter/readdir", glob, b'^'),
        action_t::DENY => esyd("deny/readdir", glob, b'^'),
        action_t::PANIC => esyd("panic/readdir", glob, b'^'),
        action_t::STOP => esyd("stop/readdir", glob, b'^'),
        action_t::KILL => esyd("kill/readdir", glob, b'^'),
        action_t::EXIT => esyd("exit/readdir", glob, b'^'),
    }
}

/// Adds to the given actionlist of mkdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mkdir_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/mkdir", glob, b'+'),
        action_t::WARN => esyd("warn/mkdir", glob, b'+'),
        action_t::FILTER => esyd("filter/mkdir", glob, b'+'),
        action_t::DENY => esyd("deny/mkdir", glob, b'+'),
        action_t::PANIC => esyd("panic/mkdir", glob, b'+'),
        action_t::STOP => esyd("stop/mkdir", glob, b'+'),
        action_t::KILL => esyd("kill/mkdir", glob, b'+'),
        action_t::EXIT => esyd("exit/mkdir", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// mkdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mkdir_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/mkdir", glob, b'-'),
        action_t::WARN => esyd("warn/mkdir", glob, b'-'),
        action_t::FILTER => esyd("filter/mkdir", glob, b'-'),
        action_t::DENY => esyd("deny/mkdir", glob, b'-'),
        action_t::PANIC => esyd("panic/mkdir", glob, b'-'),
        action_t::STOP => esyd("stop/mkdir", glob, b'-'),
        action_t::KILL => esyd("kill/mkdir", glob, b'-'),
        action_t::EXIT => esyd("exit/mkdir", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of mkdir sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mkdir_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/mkdir", glob, b'^'),
        action_t::WARN => esyd("warn/mkdir", glob, b'^'),
        action_t::FILTER => esyd("filter/mkdir", glob, b'^'),
        action_t::DENY => esyd("deny/mkdir", glob, b'^'),
        action_t::PANIC => esyd("panic/mkdir", glob, b'^'),
        action_t::STOP => esyd("stop/mkdir", glob, b'^'),
        action_t::KILL => esyd("kill/mkdir", glob, b'^'),
        action_t::EXIT => esyd("exit/mkdir", glob, b'^'),
    }
}

/// Adds to the given actionlist of chown sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chown_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chown", glob, b'+'),
        action_t::WARN => esyd("warn/chown", glob, b'+'),
        action_t::FILTER => esyd("filter/chown", glob, b'+'),
        action_t::DENY => esyd("deny/chown", glob, b'+'),
        action_t::PANIC => esyd("panic/chown", glob, b'+'),
        action_t::STOP => esyd("stop/chown", glob, b'+'),
        action_t::KILL => esyd("kill/chown", glob, b'+'),
        action_t::EXIT => esyd("exit/chown", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// chown sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chown_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chown", glob, b'-'),
        action_t::WARN => esyd("warn/chown", glob, b'-'),
        action_t::FILTER => esyd("filter/chown", glob, b'-'),
        action_t::DENY => esyd("deny/chown", glob, b'-'),
        action_t::PANIC => esyd("panic/chown", glob, b'-'),
        action_t::STOP => esyd("stop/chown", glob, b'-'),
        action_t::KILL => esyd("kill/chown", glob, b'-'),
        action_t::EXIT => esyd("exit/chown", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of chown sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chown_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chown", glob, b'^'),
        action_t::WARN => esyd("warn/chown", glob, b'^'),
        action_t::FILTER => esyd("filter/chown", glob, b'^'),
        action_t::DENY => esyd("deny/chown", glob, b'^'),
        action_t::PANIC => esyd("panic/chown", glob, b'^'),
        action_t::STOP => esyd("stop/chown", glob, b'^'),
        action_t::KILL => esyd("kill/chown", glob, b'^'),
        action_t::EXIT => esyd("exit/chown", glob, b'^'),
    }
}

/// Adds to the given actionlist of chgrp sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chgrp_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chgrp", glob, b'+'),
        action_t::WARN => esyd("warn/chgrp", glob, b'+'),
        action_t::FILTER => esyd("filter/chgrp", glob, b'+'),
        action_t::DENY => esyd("deny/chgrp", glob, b'+'),
        action_t::PANIC => esyd("panic/chgrp", glob, b'+'),
        action_t::STOP => esyd("stop/chgrp", glob, b'+'),
        action_t::KILL => esyd("kill/chgrp", glob, b'+'),
        action_t::EXIT => esyd("exit/chgrp", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// chgrp sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chgrp_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chgrp", glob, b'-'),
        action_t::WARN => esyd("warn/chgrp", glob, b'-'),
        action_t::FILTER => esyd("filter/chgrp", glob, b'-'),
        action_t::DENY => esyd("deny/chgrp", glob, b'-'),
        action_t::PANIC => esyd("panic/chgrp", glob, b'-'),
        action_t::STOP => esyd("stop/chgrp", glob, b'-'),
        action_t::KILL => esyd("kill/chgrp", glob, b'-'),
        action_t::EXIT => esyd("exit/chgrp", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of chgrp sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chgrp_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chgrp", glob, b'^'),
        action_t::WARN => esyd("warn/chgrp", glob, b'^'),
        action_t::FILTER => esyd("filter/chgrp", glob, b'^'),
        action_t::DENY => esyd("deny/chgrp", glob, b'^'),
        action_t::PANIC => esyd("panic/chgrp", glob, b'^'),
        action_t::STOP => esyd("stop/chgrp", glob, b'^'),
        action_t::KILL => esyd("kill/chgrp", glob, b'^'),
        action_t::EXIT => esyd("exit/chgrp", glob, b'^'),
    }
}

/// Adds to the given actionlist of chmod sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chmod_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chmod", glob, b'+'),
        action_t::WARN => esyd("warn/chmod", glob, b'+'),
        action_t::FILTER => esyd("filter/chmod", glob, b'+'),
        action_t::DENY => esyd("deny/chmod", glob, b'+'),
        action_t::PANIC => esyd("panic/chmod", glob, b'+'),
        action_t::STOP => esyd("stop/chmod", glob, b'+'),
        action_t::KILL => esyd("kill/chmod", glob, b'+'),
        action_t::EXIT => esyd("exit/chmod", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// chmod sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chmod_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chmod", glob, b'-'),
        action_t::WARN => esyd("warn/chmod", glob, b'-'),
        action_t::FILTER => esyd("filter/chmod", glob, b'-'),
        action_t::DENY => esyd("deny/chmod", glob, b'-'),
        action_t::PANIC => esyd("panic/chmod", glob, b'-'),
        action_t::STOP => esyd("stop/chmod", glob, b'-'),
        action_t::KILL => esyd("kill/chmod", glob, b'-'),
        action_t::EXIT => esyd("exit/chmod", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of chmod sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chmod_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chmod", glob, b'^'),
        action_t::WARN => esyd("warn/chmod", glob, b'^'),
        action_t::FILTER => esyd("filter/chmod", glob, b'^'),
        action_t::DENY => esyd("deny/chmod", glob, b'^'),
        action_t::PANIC => esyd("panic/chmod", glob, b'^'),
        action_t::STOP => esyd("stop/chmod", glob, b'^'),
        action_t::KILL => esyd("kill/chmod", glob, b'^'),
        action_t::EXIT => esyd("exit/chmod", glob, b'^'),
    }
}

/// Adds to the given actionlist of chattr sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chattr_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chattr", glob, b'+'),
        action_t::WARN => esyd("warn/chattr", glob, b'+'),
        action_t::FILTER => esyd("filter/chattr", glob, b'+'),
        action_t::DENY => esyd("deny/chattr", glob, b'+'),
        action_t::PANIC => esyd("panic/chattr", glob, b'+'),
        action_t::STOP => esyd("stop/chattr", glob, b'+'),
        action_t::KILL => esyd("kill/chattr", glob, b'+'),
        action_t::EXIT => esyd("exit/chattr", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// chattr sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chattr_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chattr", glob, b'-'),
        action_t::WARN => esyd("warn/chattr", glob, b'-'),
        action_t::FILTER => esyd("filter/chattr", glob, b'-'),
        action_t::DENY => esyd("deny/chattr", glob, b'-'),
        action_t::PANIC => esyd("panic/chattr", glob, b'-'),
        action_t::STOP => esyd("stop/chattr", glob, b'-'),
        action_t::KILL => esyd("kill/chattr", glob, b'-'),
        action_t::EXIT => esyd("exit/chattr", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of chattr sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chattr_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chattr", glob, b'^'),
        action_t::WARN => esyd("warn/chattr", glob, b'^'),
        action_t::FILTER => esyd("filter/chattr", glob, b'^'),
        action_t::DENY => esyd("deny/chattr", glob, b'^'),
        action_t::PANIC => esyd("panic/chattr", glob, b'^'),
        action_t::STOP => esyd("stop/chattr", glob, b'^'),
        action_t::KILL => esyd("kill/chattr", glob, b'^'),
        action_t::EXIT => esyd("exit/chattr", glob, b'^'),
    }
}

/// Adds to the given actionlist of chroot sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chroot_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chroot", glob, b'+'),
        action_t::WARN => esyd("warn/chroot", glob, b'+'),
        action_t::FILTER => esyd("filter/chroot", glob, b'+'),
        action_t::DENY => esyd("deny/chroot", glob, b'+'),
        action_t::PANIC => esyd("panic/chroot", glob, b'+'),
        action_t::STOP => esyd("stop/chroot", glob, b'+'),
        action_t::KILL => esyd("kill/chroot", glob, b'+'),
        action_t::EXIT => esyd("exit/chroot", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// chroot sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chroot_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chroot", glob, b'-'),
        action_t::WARN => esyd("warn/chroot", glob, b'-'),
        action_t::FILTER => esyd("filter/chroot", glob, b'-'),
        action_t::DENY => esyd("deny/chroot", glob, b'-'),
        action_t::PANIC => esyd("panic/chroot", glob, b'-'),
        action_t::STOP => esyd("stop/chroot", glob, b'-'),
        action_t::KILL => esyd("kill/chroot", glob, b'-'),
        action_t::EXIT => esyd("exit/chroot", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of chroot sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_chroot_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/chroot", glob, b'^'),
        action_t::WARN => esyd("warn/chroot", glob, b'^'),
        action_t::FILTER => esyd("filter/chroot", glob, b'^'),
        action_t::DENY => esyd("deny/chroot", glob, b'^'),
        action_t::PANIC => esyd("panic/chroot", glob, b'^'),
        action_t::STOP => esyd("stop/chroot", glob, b'^'),
        action_t::KILL => esyd("kill/chroot", glob, b'^'),
        action_t::EXIT => esyd("exit/chroot", glob, b'^'),
    }
}

/// Adds to the given actionlist of utime sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_utime_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/utime", glob, b'+'),
        action_t::WARN => esyd("warn/utime", glob, b'+'),
        action_t::FILTER => esyd("filter/utime", glob, b'+'),
        action_t::DENY => esyd("deny/utime", glob, b'+'),
        action_t::PANIC => esyd("panic/utime", glob, b'+'),
        action_t::STOP => esyd("stop/utime", glob, b'+'),
        action_t::KILL => esyd("kill/utime", glob, b'+'),
        action_t::EXIT => esyd("exit/utime", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// utime sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_utime_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/utime", glob, b'-'),
        action_t::WARN => esyd("warn/utime", glob, b'-'),
        action_t::FILTER => esyd("filter/utime", glob, b'-'),
        action_t::DENY => esyd("deny/utime", glob, b'-'),
        action_t::PANIC => esyd("panic/utime", glob, b'-'),
        action_t::STOP => esyd("stop/utime", glob, b'-'),
        action_t::KILL => esyd("kill/utime", glob, b'-'),
        action_t::EXIT => esyd("exit/utime", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of utime sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_utime_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/utime", glob, b'^'),
        action_t::WARN => esyd("warn/utime", glob, b'^'),
        action_t::FILTER => esyd("filter/utime", glob, b'^'),
        action_t::DENY => esyd("deny/utime", glob, b'^'),
        action_t::PANIC => esyd("panic/utime", glob, b'^'),
        action_t::STOP => esyd("stop/utime", glob, b'^'),
        action_t::KILL => esyd("kill/utime", glob, b'^'),
        action_t::EXIT => esyd("exit/utime", glob, b'^'),
    }
}

/// Adds to the given actionlist of mkdev sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mkdev_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/mkdev", glob, b'+'),
        action_t::WARN => esyd("warn/mkdev", glob, b'+'),
        action_t::FILTER => esyd("filter/mkdev", glob, b'+'),
        action_t::DENY => esyd("deny/mkdev", glob, b'+'),
        action_t::PANIC => esyd("panic/mkdev", glob, b'+'),
        action_t::STOP => esyd("stop/mkdev", glob, b'+'),
        action_t::KILL => esyd("kill/mkdev", glob, b'+'),
        action_t::EXIT => esyd("exit/mkdev", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// mkdev sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mkdev_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/mkdev", glob, b'-'),
        action_t::WARN => esyd("warn/mkdev", glob, b'-'),
        action_t::FILTER => esyd("filter/mkdev", glob, b'-'),
        action_t::DENY => esyd("deny/mkdev", glob, b'-'),
        action_t::PANIC => esyd("panic/mkdev", glob, b'-'),
        action_t::STOP => esyd("stop/mkdev", glob, b'-'),
        action_t::KILL => esyd("kill/mkdev", glob, b'-'),
        action_t::EXIT => esyd("exit/mkdev", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of mkdev sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mkdev_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/mkdev", glob, b'^'),
        action_t::WARN => esyd("warn/mkdev", glob, b'^'),
        action_t::FILTER => esyd("filter/mkdev", glob, b'^'),
        action_t::DENY => esyd("deny/mkdev", glob, b'^'),
        action_t::PANIC => esyd("panic/mkdev", glob, b'^'),
        action_t::STOP => esyd("stop/mkdev", glob, b'^'),
        action_t::KILL => esyd("kill/mkdev", glob, b'^'),
        action_t::EXIT => esyd("exit/mkdev", glob, b'^'),
    }
}

/// Adds to the given actionlist of mkfifo sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mkfifo_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/mkfifo", glob, b'+'),
        action_t::WARN => esyd("warn/mkfifo", glob, b'+'),
        action_t::FILTER => esyd("filter/mkfifo", glob, b'+'),
        action_t::DENY => esyd("deny/mkfifo", glob, b'+'),
        action_t::PANIC => esyd("panic/mkfifo", glob, b'+'),
        action_t::STOP => esyd("stop/mkfifo", glob, b'+'),
        action_t::KILL => esyd("kill/mkfifo", glob, b'+'),
        action_t::EXIT => esyd("exit/mkfifo", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// mkfifo sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mkfifo_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/mkfifo", glob, b'-'),
        action_t::WARN => esyd("warn/mkfifo", glob, b'-'),
        action_t::FILTER => esyd("filter/mkfifo", glob, b'-'),
        action_t::DENY => esyd("deny/mkfifo", glob, b'-'),
        action_t::PANIC => esyd("panic/mkfifo", glob, b'-'),
        action_t::STOP => esyd("stop/mkfifo", glob, b'-'),
        action_t::KILL => esyd("kill/mkfifo", glob, b'-'),
        action_t::EXIT => esyd("exit/mkfifo", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of mkfifo sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mkfifo_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/mkfifo", glob, b'^'),
        action_t::WARN => esyd("warn/mkfifo", glob, b'^'),
        action_t::FILTER => esyd("filter/mkfifo", glob, b'^'),
        action_t::DENY => esyd("deny/mkfifo", glob, b'^'),
        action_t::PANIC => esyd("panic/mkfifo", glob, b'^'),
        action_t::STOP => esyd("stop/mkfifo", glob, b'^'),
        action_t::KILL => esyd("kill/mkfifo", glob, b'^'),
        action_t::EXIT => esyd("exit/mkfifo", glob, b'^'),
    }
}

/// Adds to the given actionlist of mktemp sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mktemp_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/mktemp", glob, b'+'),
        action_t::WARN => esyd("warn/mktemp", glob, b'+'),
        action_t::FILTER => esyd("filter/mktemp", glob, b'+'),
        action_t::DENY => esyd("deny/mktemp", glob, b'+'),
        action_t::PANIC => esyd("panic/mktemp", glob, b'+'),
        action_t::STOP => esyd("stop/mktemp", glob, b'+'),
        action_t::KILL => esyd("kill/mktemp", glob, b'+'),
        action_t::EXIT => esyd("exit/mktemp", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// mktemp sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mktemp_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/mktemp", glob, b'-'),
        action_t::WARN => esyd("warn/mktemp", glob, b'-'),
        action_t::FILTER => esyd("filter/mktemp", glob, b'-'),
        action_t::DENY => esyd("deny/mktemp", glob, b'-'),
        action_t::PANIC => esyd("panic/mktemp", glob, b'-'),
        action_t::STOP => esyd("stop/mktemp", glob, b'-'),
        action_t::KILL => esyd("kill/mktemp", glob, b'-'),
        action_t::EXIT => esyd("exit/mktemp", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of mktemp sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mktemp_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/mktemp", glob, b'^'),
        action_t::WARN => esyd("warn/mktemp", glob, b'^'),
        action_t::FILTER => esyd("filter/mktemp", glob, b'^'),
        action_t::DENY => esyd("deny/mktemp", glob, b'^'),
        action_t::PANIC => esyd("panic/mktemp", glob, b'^'),
        action_t::STOP => esyd("stop/mktemp", glob, b'^'),
        action_t::KILL => esyd("kill/mktemp", glob, b'^'),
        action_t::EXIT => esyd("exit/mktemp", glob, b'^'),
    }
}

/// Adds to the given actionlist of net/bind sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_net_bind_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/net/bind", glob, b'+'),
        action_t::WARN => esyd("warn/net/bind", glob, b'+'),
        action_t::FILTER => esyd("filter/net/bind", glob, b'+'),
        action_t::DENY => esyd("deny/net/bind", glob, b'+'),
        action_t::PANIC => esyd("panic/net/bind", glob, b'+'),
        action_t::STOP => esyd("stop/net/bind", glob, b'+'),
        action_t::KILL => esyd("kill/net/bind", glob, b'+'),
        action_t::EXIT => esyd("exit/net/bind", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// net/bind sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_net_bind_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/net/bind", glob, b'-'),
        action_t::WARN => esyd("warn/net/bind", glob, b'-'),
        action_t::FILTER => esyd("filter/net/bind", glob, b'-'),
        action_t::DENY => esyd("deny/net/bind", glob, b'-'),
        action_t::PANIC => esyd("panic/net/bind", glob, b'-'),
        action_t::STOP => esyd("stop/net/bind", glob, b'-'),
        action_t::KILL => esyd("kill/net/bind", glob, b'-'),
        action_t::EXIT => esyd("exit/net/bind", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of net/bind sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_net_bind_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/net/bind", glob, b'^'),
        action_t::WARN => esyd("warn/net/bind", glob, b'^'),
        action_t::FILTER => esyd("filter/net/bind", glob, b'^'),
        action_t::DENY => esyd("deny/net/bind", glob, b'^'),
        action_t::PANIC => esyd("panic/net/bind", glob, b'^'),
        action_t::STOP => esyd("stop/net/bind", glob, b'^'),
        action_t::KILL => esyd("kill/net/bind", glob, b'^'),
        action_t::EXIT => esyd("exit/net/bind", glob, b'^'),
    }
}

/// Adds to the given actionlist of net/connect sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_net_connect_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/net/connect", glob, b'+'),
        action_t::WARN => esyd("warn/net/connect", glob, b'+'),
        action_t::FILTER => esyd("filter/net/connect", glob, b'+'),
        action_t::DENY => esyd("deny/net/connect", glob, b'+'),
        action_t::PANIC => esyd("panic/net/connect", glob, b'+'),
        action_t::STOP => esyd("stop/net/connect", glob, b'+'),
        action_t::KILL => esyd("kill/net/connect", glob, b'+'),
        action_t::EXIT => esyd("exit/net/connect", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// net/connect sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_net_connect_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/net/connect", glob, b'-'),
        action_t::WARN => esyd("warn/net/connect", glob, b'-'),
        action_t::FILTER => esyd("filter/net/connect", glob, b'-'),
        action_t::DENY => esyd("deny/net/connect", glob, b'-'),
        action_t::PANIC => esyd("panic/net/connect", glob, b'-'),
        action_t::STOP => esyd("stop/net/connect", glob, b'-'),
        action_t::KILL => esyd("kill/net/connect", glob, b'-'),
        action_t::EXIT => esyd("exit/net/connect", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of net/connect sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_net_connect_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/net/connect", glob, b'^'),
        action_t::WARN => esyd("warn/net/connect", glob, b'^'),
        action_t::FILTER => esyd("filter/net/connect", glob, b'^'),
        action_t::DENY => esyd("deny/net/connect", glob, b'^'),
        action_t::PANIC => esyd("panic/net/connect", glob, b'^'),
        action_t::STOP => esyd("stop/net/connect", glob, b'^'),
        action_t::KILL => esyd("kill/net/connect", glob, b'^'),
        action_t::EXIT => esyd("exit/net/connect", glob, b'^'),
    }
}

/// Adds to the given actionlist of net/sendfd sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_net_sendfd_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/net/sendfd", glob, b'+'),
        action_t::WARN => esyd("warn/net/sendfd", glob, b'+'),
        action_t::FILTER => esyd("filter/net/sendfd", glob, b'+'),
        action_t::DENY => esyd("deny/net/sendfd", glob, b'+'),
        action_t::PANIC => esyd("panic/net/sendfd", glob, b'+'),
        action_t::STOP => esyd("stop/net/sendfd", glob, b'+'),
        action_t::KILL => esyd("kill/net/sendfd", glob, b'+'),
        action_t::EXIT => esyd("exit/net/sendfd", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// net/sendfd sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_net_sendfd_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/net/sendfd", glob, b'-'),
        action_t::WARN => esyd("warn/net/sendfd", glob, b'-'),
        action_t::FILTER => esyd("filter/net/sendfd", glob, b'-'),
        action_t::DENY => esyd("deny/net/sendfd", glob, b'-'),
        action_t::PANIC => esyd("panic/net/sendfd", glob, b'-'),
        action_t::STOP => esyd("stop/net/sendfd", glob, b'-'),
        action_t::KILL => esyd("kill/net/sendfd", glob, b'-'),
        action_t::EXIT => esyd("exit/net/sendfd", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of net/sendfd sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_net_sendfd_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/net/sendfd", glob, b'^'),
        action_t::WARN => esyd("warn/net/sendfd", glob, b'^'),
        action_t::FILTER => esyd("filter/net/sendfd", glob, b'^'),
        action_t::DENY => esyd("deny/net/sendfd", glob, b'^'),
        action_t::PANIC => esyd("panic/net/sendfd", glob, b'^'),
        action_t::STOP => esyd("stop/net/sendfd", glob, b'^'),
        action_t::KILL => esyd("kill/net/sendfd", glob, b'^'),
        action_t::EXIT => esyd("exit/net/sendfd", glob, b'^'),
    }
}

/// Adds to the given actionlist of net/link sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_net_link_add(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/net/link", glob, b'+'),
        action_t::WARN => esyd("warn/net/link", glob, b'+'),
        action_t::FILTER => esyd("filter/net/link", glob, b'+'),
        action_t::DENY => esyd("deny/net/link", glob, b'+'),
        action_t::PANIC => esyd("panic/net/link", glob, b'+'),
        action_t::STOP => esyd("stop/net/link", glob, b'+'),
        action_t::KILL => esyd("kill/net/link", glob, b'+'),
        action_t::EXIT => esyd("exit/net/link", glob, b'+'),
    }
}

/// Removes the first instance from the end of the given actionlist of
/// net/link sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_net_link_del(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/net/link", glob, b'-'),
        action_t::WARN => esyd("warn/net/link", glob, b'-'),
        action_t::FILTER => esyd("filter/net/link", glob, b'-'),
        action_t::DENY => esyd("deny/net/link", glob, b'-'),
        action_t::PANIC => esyd("panic/net/link", glob, b'-'),
        action_t::STOP => esyd("stop/net/link", glob, b'-'),
        action_t::KILL => esyd("kill/net/link", glob, b'-'),
        action_t::EXIT => esyd("exit/net/link", glob, b'-'),
    }
}

/// Removes all matching patterns from the given actionlist of net/link sandboxing.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_net_link_rem(action: action_t, glob: *const c_char) -> c_int {
    match action {
        action_t::ALLOW => esyd("allow/net/link", glob, b'^'),
        action_t::WARN => esyd("warn/net/link", glob, b'^'),
        action_t::FILTER => esyd("filter/net/link", glob, b'^'),
        action_t::DENY => esyd("deny/net/link", glob, b'^'),
        action_t::PANIC => esyd("panic/net/link", glob, b'^'),
        action_t::STOP => esyd("stop/net/link", glob, b'^'),
        action_t::KILL => esyd("kill/net/link", glob, b'^'),
        action_t::EXIT => esyd("exit/net/link", glob, b'^'),
    }
}

/// Set syd maximum per-process memory usage limit for memory sandboxing.
///
/// parse-size crate is used to parse the value so formatted strings are OK.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mem_max(size: *const c_char) -> c_int {
    esyd("mem/max", size, b':')
}

/// Set syd maximum per-process virtual memory usage limit for memory sandboxing.
///
/// parse-size crate is used to parse the value so formatted strings are OK.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_mem_vm_max(size: *const c_char) -> c_int {
    esyd("mem/vm_max", size, b':')
}

/// Set syd maximum process id limit for PID sandboxing
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_pid_max(size: usize) -> c_int {
    let mut path = OsString::from("/dev/syd/pid/max:");

    let mut buf = itoa::Buffer::new();
    let max_str = OsStr::from_bytes(buf.format(size).as_bytes());
    path.push(max_str);

    stat(path)
}

/// Specify SegvGuard entry expiry timeout in seconds.
/// Setting this timeout to 0 effectively disables SegvGuard.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_segvguard_expiry(timeout: u64) -> c_int {
    let mut path = OsString::from("/dev/syd/segvguard/expiry:");

    let mut buf = itoa::Buffer::new();
    let exp_str = OsStr::from_bytes(buf.format(timeout).as_bytes());
    path.push(exp_str);

    stat(path)
}

/// Specify SegvGuard entry suspension timeout in seconds.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_segvguard_suspension(timeout: u64) -> c_int {
    let mut path = OsString::from("/dev/syd/segvguard/suspension:");

    let mut buf = itoa::Buffer::new();
    let exp_str = OsStr::from_bytes(buf.format(timeout).as_bytes());
    path.push(exp_str);

    stat(path)
}

/// Specify SegvGuard max number of crashes before suspension.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub extern "C" fn syd_segvguard_maxcrashes(max: u8) -> c_int {
    let mut path = OsString::from("/dev/syd/segvguard/maxcrashes:");

    let mut buf = itoa::Buffer::new();
    let max_str = OsStr::from_bytes(buf.format(max).as_bytes());
    path.push(max_str);

    stat(path)
}

/// Execute a command outside the sandbox without sandboxing
///
/// # Safety
///
/// This function is marked `unsafe` because it dereferences raw
/// pointers, which is inherently unsafe in Rust.
///
/// The caller must ensure the following conditions are met to safely
/// use this function:
///
/// 1. The `file` pointer must point to a valid, null-terminated C-style
///    string.
///
/// 2. The `argv` pointer must point to an array of pointers, where each
///    pointer refers to a valid, null-terminated C-style string. The
///    last pointer in the array must be null, indicating the end of the
///    array.
///
/// 3. The memory pointed to by `file` and `argv` must remain valid for
///    the duration of the call.
///
/// Failing to uphold these guarantees can lead to undefined behavior,
/// including memory corruption and data races.
///
/// Returns 0 on success, negated errno on failure.
#[no_mangle]
pub unsafe extern "C" fn syd_exec(file: *const c_char, argv: *const *const c_char) -> c_int {
    if file.is_null() || argv.is_null() {
        return -EFAULT;
    }

    // SAFETY: Trust that `file` is a null-terminated string.
    let file = CStr::from_ptr(file);
    let file = OsStr::from_bytes(file.to_bytes());

    let mut path = OsString::from("/dev/syd/cmd/exec!");
    path.push(file);

    let mut idx: isize = 0;
    while !(*argv.offset(idx)).is_null() {
        // SAFETY: Trust that each `argv` element is a null-terminated string.
        let arg = CStr::from_ptr(*argv.offset(idx));
        let arg = OsStr::from_bytes(arg.to_bytes());

        path.push(OsStr::from_bytes(&[b'\x1F'])); // ASCII Unit Separator
        path.push(arg);

        idx = idx.saturating_add(1);
    }

    let path = PathBuf::from(path);
    stat(path)
}
