syd/
lib.rs

1//
2// libsyd: Rust-based C library for syd interaction via /dev/syd
3// lib/src/lib.rs: syd API C Library
4//
5// Copyright (c) 2023, 2024, 2025 Ali Polatel <alip@chesswob.org>
6//
7// SPDX-License-Identifier: LGPL-3.0
8
9//! # libsyd - syd API Rust Library
10//!
11//! `libsyd` is a C library written in Rust that implements the syd
12//! stat API, providing an interface to the `/dev/syd` of syd. It
13//! allows for runtime configuration and interaction with the syd
14//! sandboxing environment.
15//!
16//! ## Overview
17//! The library is designed to interact with the syd sandboxing
18//! environment, offering functionalities to check and modify the state
19//! of the sandbox lock, and perform system calls to `/dev/syd`.
20//!
21//! For more detailed information and usage instructions, refer to the syd
22//! manual, available at [syd Manual](http://man.exherbo.org/syd.2.html).
23//!
24//! ## Author
25//! Ali Polatel <alip@chesswob.org>
26
27// We like safe, clean and simple code with documentation.
28#![deny(missing_docs)]
29#![deny(clippy::allow_attributes_without_reason)]
30#![deny(clippy::arithmetic_side_effects)]
31#![deny(clippy::as_ptr_cast_mut)]
32#![deny(clippy::as_underscore)]
33#![deny(clippy::assertions_on_result_states)]
34#![deny(clippy::borrow_as_ptr)]
35#![deny(clippy::branches_sharing_code)]
36#![deny(clippy::case_sensitive_file_extension_comparisons)]
37#![deny(clippy::cast_lossless)]
38#![deny(clippy::cast_possible_truncation)]
39#![deny(clippy::cast_possible_wrap)]
40#![deny(clippy::cast_precision_loss)]
41#![deny(clippy::cast_ptr_alignment)]
42#![deny(clippy::cast_sign_loss)]
43#![deny(clippy::checked_conversions)]
44#![deny(clippy::clear_with_drain)]
45#![deny(clippy::clone_on_ref_ptr)]
46#![deny(clippy::cloned_instead_of_copied)]
47#![deny(clippy::cognitive_complexity)]
48#![deny(clippy::collection_is_never_read)]
49#![deny(clippy::copy_iterator)]
50#![deny(clippy::create_dir)]
51#![deny(clippy::dbg_macro)]
52#![deny(clippy::debug_assert_with_mut_call)]
53#![deny(clippy::decimal_literal_representation)]
54#![deny(clippy::default_trait_access)]
55#![deny(clippy::default_union_representation)]
56#![deny(clippy::derive_partial_eq_without_eq)]
57#![deny(clippy::doc_link_with_quotes)]
58#![deny(clippy::doc_markdown)]
59#![deny(clippy::explicit_into_iter_loop)]
60#![deny(clippy::explicit_iter_loop)]
61#![deny(clippy::fallible_impl_from)]
62#![deny(clippy::missing_safety_doc)]
63#![deny(clippy::undocumented_unsafe_blocks)]
64
65use std::{
66    ffi::{CStr, OsStr, OsString},
67    fmt,
68    fs::{symlink_metadata, Metadata},
69    os::{
70        fd::RawFd,
71        linux::fs::MetadataExt as LinuxMetadataExt,
72        raw::{c_char, c_int},
73        unix::{
74            ffi::OsStrExt,
75            fs::{FileTypeExt, MetadataExt as UnixMetadataExt},
76        },
77    },
78    path::{Path, PathBuf},
79};
80
81/// `lock_state_t_t` type represents possible states for the sandbox lock.
82#[expect(non_camel_case_types)]
83pub type lock_state_t = u8;
84
85/// The sandbox lock is off, allowing all sandbox commands.
86pub const LOCK_OFF: lock_state_t = 0;
87/// The sandbox lock is set to on for all processes except the initial
88/// process (syd exec child).
89pub const LOCK_EXEC: lock_state_t = 1;
90/// The sandbox lock is on, disallowing all sandbox commands.
91pub const LOCK_ON: lock_state_t = 2;
92
93// An enumeration of the possible states for the sandbox lock.
94#[repr(u8)]
95#[derive(Copy, Clone, Debug)]
96enum LockState {
97    // The sandbox lock is off, allowing all sandbox commands.
98    Off = LOCK_OFF,
99    // The sandbox lock is set to on for all processes except the initial
100    // process (syd exec child).
101    Exec = LOCK_EXEC,
102    // The sandbox lock is on, disallowing all sandbox commands.
103    On = LOCK_ON,
104}
105
106impl TryFrom<lock_state_t> for LockState {
107    type Error = ();
108
109    fn try_from(value: lock_state_t) -> Result<Self, Self::Error> {
110        match value {
111            LOCK_OFF => Ok(LockState::Off),
112            LOCK_EXEC => Ok(LockState::Exec),
113            LOCK_ON => Ok(LockState::On),
114            _ => Err(()),
115        }
116    }
117}
118
119impl fmt::Display for LockState {
120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121        let state_str = match self {
122            LockState::Off => "off",
123            LockState::Exec => "exec",
124            LockState::On => "on",
125        };
126        write!(f, "{state_str}")
127    }
128}
129
130/// `action_t` type represents possible sandboxing action values.
131#[expect(non_camel_case_types)]
132pub type action_t = u8;
133
134/// Allow system call.
135pub const ACTION_ALLOW: action_t = 0;
136/// Allow system call and warn.
137pub const ACTION_WARN: action_t = 1;
138/// Deny system call silently.
139pub const ACTION_FILTER: action_t = 2;
140/// Deny system call and warn.
141pub const ACTION_DENY: action_t = 3;
142/// Deny system call, warn and panic the current Syd thread.
143pub const ACTION_PANIC: action_t = 4;
144/// Deny system call, warn and stop the offending process.
145pub const ACTION_STOP: action_t = 5;
146/// Deny system call, warn and abort the offending process.
147pub const ACTION_ABORT: action_t = 6;
148/// Deny system call, warn and kill the offending process.
149pub const ACTION_KILL: action_t = 7;
150/// Warn, and exit Syd immediately with deny errno as exit value.
151pub const ACTION_EXIT: action_t = 8;
152
153// An enumeration of the possible actions for sandboxing.
154#[repr(u8)]
155#[derive(Copy, Clone, Debug)]
156enum Action {
157    // Allow system call.
158    Allow = ACTION_ALLOW,
159    // Allow system call and warn.
160    Warn = ACTION_WARN,
161    // Deny system call silently.
162    Filter = ACTION_FILTER,
163    // Deny system call and warn.
164    Deny = ACTION_DENY,
165    // Deny system call, warn and panic the current Syd thread.
166    Panic = ACTION_PANIC,
167    // Deny system call, warn and stop the offending process.
168    Stop = ACTION_STOP,
169    // Deny system call, warn and abort offending process.
170    Abort = ACTION_ABORT,
171    // Deny system call, warn and kill the offending process.
172    Kill = ACTION_KILL,
173    // Warn, and exit Syd immediately with deny errno as exit value.
174    Exit = ACTION_EXIT,
175}
176
177impl TryFrom<action_t> for Action {
178    type Error = ();
179
180    fn try_from(value: action_t) -> Result<Self, Self::Error> {
181        match value {
182            ACTION_ALLOW => Ok(Action::Allow),
183            ACTION_WARN => Ok(Action::Warn),
184            ACTION_FILTER => Ok(Action::Filter),
185            ACTION_DENY => Ok(Action::Deny),
186            ACTION_PANIC => Ok(Action::Panic),
187            ACTION_STOP => Ok(Action::Stop),
188            ACTION_ABORT => Ok(Action::Abort),
189            ACTION_KILL => Ok(Action::Kill),
190            ACTION_EXIT => Ok(Action::Exit),
191            _ => Err(()),
192        }
193    }
194}
195
196impl fmt::Display for Action {
197    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198        let action_str = match self {
199            Action::Allow => "allow",
200            Action::Warn => "warn",
201            Action::Filter => "filter",
202            Action::Deny => "deny",
203            Action::Panic => "panic",
204            Action::Stop => "stop",
205            Action::Abort => "abort",
206            Action::Kill => "kill",
207            Action::Exit => "exit",
208        };
209        write!(f, "{action_str}")
210    }
211}
212
213const EFAULT: i32 = 14;
214const EINVAL: i32 = 22;
215const LIB_MAJOR: &'static str = env!("CARGO_PKG_VERSION_MAJOR");
216const SYD_ATIME: i64 = 505958400;
217const SYD_CTIME: i64 = -2036448000;
218const SYD_MTIME: i64 = -842745600;
219
220fn check_stat(stat: &Metadata) -> bool {
221    let lib_major = if let Ok(lib_major) = LIB_MAJOR.parse() {
222        lib_major
223    } else {
224        return false;
225    };
226
227    // Check file type.
228    if !stat.file_type().is_char_device() {
229        return false;
230    }
231
232    // Check timestamps.
233    if stat.st_atime() != SYD_ATIME {
234        return false;
235    }
236    if stat.st_ctime() != SYD_CTIME {
237        return false;
238    }
239    if stat.st_mtime() != SYD_MTIME {
240        return false;
241    }
242
243    let rdev = stat.rdev();
244
245    let api_major = (rdev >> 8) & 0xff;
246    let api_minor = rdev & 0xff;
247
248    // Device type represents syd(2) API version.
249    // See RETURN VALUE section in syd(2) manual page.
250    api_major == lib_major && api_minor >= 1
251}
252
253fn stat<P: AsRef<Path>>(path: P) -> c_int {
254    match symlink_metadata(path) {
255        Ok(stat) if check_stat(&stat) => 0,
256        Ok(_) => -EINVAL,
257        Err(error) => match error.raw_os_error() {
258            Some(e) => e.checked_neg().unwrap_or(-EINVAL),
259            None => -EINVAL,
260        },
261    }
262}
263
264fn esyd<P: AsRef<Path>>(rule: P, elem: *const c_char, op: u8) -> c_int {
265    if !matches!(op, b'+' | b'-' | b'^' | b':') {
266        return -EINVAL;
267    }
268
269    if elem.is_null() {
270        return -EFAULT;
271    }
272
273    // SAFETY: Trust that `elem` is a null-terminated string.
274    let elem = unsafe { CStr::from_ptr(elem) };
275    let elem = OsStr::from_bytes(elem.to_bytes());
276
277    // Manually concatenate the path segments
278    let mut path = OsString::from("/dev/syd/");
279    path.push(rule.as_ref());
280    path.push(OsStr::from_bytes(&[op]));
281    path.push(elem);
282
283    // Convert the OsString to PathBuf
284    let path = PathBuf::from(path);
285
286    stat(path)
287}
288
289/// Performs a syd API check
290///
291/// The caller is advised to perform this check before
292/// calling any other syd API calls.
293///
294/// Returns API number on success, negated errno on failure.
295#[no_mangle]
296pub extern "C" fn syd_api() -> c_int {
297    match stat("/dev/syd/3") {
298        0 => 3,
299        n => n,
300    }
301}
302
303/// Performs an lstat system call on the file "/dev/syd".
304///
305/// Returns 0 on success, negated errno on failure.
306#[no_mangle]
307pub extern "C" fn syd_check() -> c_int {
308    stat("/dev/syd")
309}
310
311/// Causes syd to exit immediately with code 127
312///
313/// Returns 0 on success, negated errno on failure.
314#[no_mangle]
315pub extern "C" fn syd_panic() -> c_int {
316    stat("/dev/syd/panic")
317}
318
319/// Causes syd to reset sandboxing to the default state.
320/// Allowlists, denylists and filters are going to be cleared.
321///
322/// Returns 0 on success, negated errno on failure.
323#[no_mangle]
324pub extern "C" fn syd_reset() -> c_int {
325    stat("/dev/syd/reset")
326}
327
328/// Causes syd to read configuration from the given file descriptor.
329///
330/// Returns 0 on success, negated errno on failure.
331#[no_mangle]
332pub extern "C" fn syd_load(fd: c_int) -> c_int {
333    let fd = match RawFd::try_from(fd) {
334        Ok(fd) if fd < 0 => return -EINVAL,
335        Ok(fd) => fd,
336        Err(_) => return -EINVAL,
337    };
338    stat(&format!("/dev/syd/load/{fd}"))
339}
340
341/// Sets the state of the sandbox lock.
342///
343/// state: The desired state of the sandbox lock.
344///
345/// Returns 0 on success, negated errno on failure.
346#[no_mangle]
347pub extern "C" fn syd_lock(state: lock_state_t) -> c_int {
348    // Convert lock_state_t enum to corresponding lock state string.
349    let state = match LockState::try_from(state) {
350        Ok(state) => state,
351        Err(_) => return -EINVAL,
352    };
353
354    stat(&format!("/dev/syd/lock:{state}"))
355}
356
357/// Checks if walk sandboxing is enabled.
358///
359/// Returns true if walk sandboxing is enabled, false otherwise.
360#[no_mangle]
361pub extern "C" fn syd_enabled_walk() -> bool {
362    stat("/dev/syd/sandbox/walk?") == 0
363}
364
365/// Enable walk sandboxing.
366///
367/// Returns 0 on success, negated errno on failure.
368#[no_mangle]
369pub extern "C" fn syd_enable_walk() -> c_int {
370    stat("/dev/syd/sandbox/walk:on")
371}
372
373/// Disable walk sandboxing.
374///
375/// Returns 0 on success, negated errno on failure.
376#[no_mangle]
377pub extern "C" fn syd_disable_walk() -> c_int {
378    stat("/dev/syd/sandbox/walk:off")
379}
380
381/// Checks if stat sandboxing is enabled.
382///
383/// Returns true if stat sandboxing is enabled, false otherwise.
384#[no_mangle]
385pub extern "C" fn syd_enabled_stat() -> bool {
386    stat("/dev/syd/sandbox/stat?") == 0
387}
388
389/// Enable stat sandboxing.
390///
391/// Returns 0 on success, negated errno on failure.
392#[no_mangle]
393pub extern "C" fn syd_enable_stat() -> c_int {
394    stat("/dev/syd/sandbox/stat:on")
395}
396
397/// Disable stat sandboxing.
398///
399/// Returns 0 on success, negated errno on failure.
400#[no_mangle]
401pub extern "C" fn syd_disable_stat() -> c_int {
402    stat("/dev/syd/sandbox/stat:off")
403}
404
405/// Checks if read sandboxing is enabled.
406///
407/// Returns true if read sandboxing is enabled, false otherwise.
408#[no_mangle]
409pub extern "C" fn syd_enabled_read() -> bool {
410    stat("/dev/syd/sandbox/read?") == 0
411}
412
413/// Enable read sandboxing.
414///
415/// Returns 0 on success, negated errno on failure.
416#[no_mangle]
417pub extern "C" fn syd_enable_read() -> c_int {
418    stat("/dev/syd/sandbox/read:on")
419}
420
421/// Disable read sandboxing.
422///
423/// Returns 0 on success, negated errno on failure.
424#[no_mangle]
425pub extern "C" fn syd_disable_read() -> c_int {
426    stat("/dev/syd/sandbox/read:off")
427}
428
429/// Checks if write sandboxing is enabled.
430///
431/// Returns true if write sandboxing is enabled, false otherwise.
432#[no_mangle]
433pub extern "C" fn syd_enabled_write() -> bool {
434    stat("/dev/syd/sandbox/write?") == 0
435}
436
437/// Enable write sandboxing.
438///
439/// Returns 0 on success, negated errno on failure.
440#[no_mangle]
441pub extern "C" fn syd_enable_write() -> c_int {
442    stat("/dev/syd/sandbox/write:on")
443}
444
445/// Disable write sandboxing.
446///
447/// Returns 0 on success, negated errno on failure.
448#[no_mangle]
449pub extern "C" fn syd_disable_write() -> c_int {
450    stat("/dev/syd/sandbox/write:off")
451}
452
453/// Checks if exec sandboxing is enabled.
454///
455/// Returns true if exec sandboxing is enabled, false otherwise.
456#[no_mangle]
457pub extern "C" fn syd_enabled_exec() -> bool {
458    stat("/dev/syd/sandbox/exec?") == 0
459}
460
461/// Enable exec sandboxing.
462///
463/// Returns 0 on success, negated errno on failure.
464#[no_mangle]
465pub extern "C" fn syd_enable_exec() -> c_int {
466    stat("/dev/syd/sandbox/exec:on")
467}
468
469/// Disable exec sandboxing.
470///
471/// Returns 0 on success, negated errno on failure.
472#[no_mangle]
473pub extern "C" fn syd_disable_exec() -> c_int {
474    stat("/dev/syd/sandbox/exec:off")
475}
476
477/// Checks if ioctl sandboxing is enabled.
478///
479/// Returns true if ioctl sandboxing is enabled, false otherwise.
480#[no_mangle]
481pub extern "C" fn syd_enabled_ioctl() -> bool {
482    stat("/dev/syd/sandbox/ioctl?") == 0
483}
484
485/// Enable ioctl sandboxing.
486///
487/// Returns 0 on success, negated errno on failure.
488#[no_mangle]
489pub extern "C" fn syd_enable_ioctl() -> c_int {
490    stat("/dev/syd/sandbox/ioctl:on")
491}
492
493/// Disable ioctl sandboxing.
494///
495/// Returns 0 on success, negated errno on failure.
496#[no_mangle]
497pub extern "C" fn syd_disable_ioctl() -> c_int {
498    stat("/dev/syd/sandbox/ioctl:off")
499}
500
501/// Checks if create sandboxing is enabled.
502///
503/// Returns true if create sandboxing is enabled, false otherwise.
504#[no_mangle]
505pub extern "C" fn syd_enabled_create() -> bool {
506    stat("/dev/syd/sandbox/create?") == 0
507}
508
509/// Enable create sandboxing.
510///
511/// Returns 0 on success, negated errno on failure.
512#[no_mangle]
513pub extern "C" fn syd_enable_create() -> c_int {
514    stat("/dev/syd/sandbox/create:on")
515}
516
517/// Disable create sandboxing.
518///
519/// Returns 0 on success, negated errno on failure.
520#[no_mangle]
521pub extern "C" fn syd_disable_create() -> c_int {
522    stat("/dev/syd/sandbox/create:off")
523}
524
525/// Checks if delete sandboxing is enabled.
526///
527/// Returns true if delete sandboxing is enabled, false otherwise.
528#[no_mangle]
529pub extern "C" fn syd_enabled_delete() -> bool {
530    stat("/dev/syd/sandbox/delete?") == 0
531}
532
533/// Enable delete sandboxing.
534///
535/// Returns 0 on success, negated errno on failure.
536#[no_mangle]
537pub extern "C" fn syd_enable_delete() -> c_int {
538    stat("/dev/syd/sandbox/delete:on")
539}
540
541/// Disable delete sandboxing.
542///
543/// Returns 0 on success, negated errno on failure.
544#[no_mangle]
545pub extern "C" fn syd_disable_delete() -> c_int {
546    stat("/dev/syd/sandbox/delete:off")
547}
548
549/// Checks if rename sandboxing is enabled.
550///
551/// Returns true if rename sandboxing is enabled, false otherwise.
552#[no_mangle]
553pub extern "C" fn syd_enabled_rename() -> bool {
554    stat("/dev/syd/sandbox/rename?") == 0
555}
556
557/// Enable rename sandboxing.
558///
559/// Returns 0 on success, negated errno on failure.
560#[no_mangle]
561pub extern "C" fn syd_enable_rename() -> c_int {
562    stat("/dev/syd/sandbox/rename:on")
563}
564
565/// Disable rename sandboxing.
566///
567/// Returns 0 on success, negated errno on failure.
568#[no_mangle]
569pub extern "C" fn syd_disable_rename() -> c_int {
570    stat("/dev/syd/sandbox/rename:off")
571}
572
573/// Checks if symlink sandboxing is enabled.
574///
575/// Returns true if symlink sandboxing is enabled, false otherwise.
576#[no_mangle]
577pub extern "C" fn syd_enabled_symlink() -> bool {
578    stat("/dev/syd/sandbox/symlink?") == 0
579}
580
581/// Enable symlink sandboxing.
582///
583/// Returns 0 on success, negated errno on failure.
584#[no_mangle]
585pub extern "C" fn syd_enable_symlink() -> c_int {
586    stat("/dev/syd/sandbox/symlink:on")
587}
588
589/// Disable symlink sandboxing.
590///
591/// Returns 0 on success, negated errno on failure.
592#[no_mangle]
593pub extern "C" fn syd_disable_symlink() -> c_int {
594    stat("/dev/syd/sandbox/symlink:off")
595}
596
597/// Checks if truncate sandboxing is enabled.
598///
599/// Returns true if truncate sandboxing is enabled, false otherwise.
600#[no_mangle]
601pub extern "C" fn syd_enabled_truncate() -> bool {
602    stat("/dev/syd/sandbox/truncate?") == 0
603}
604
605/// Enable truncate sandboxing.
606///
607/// Returns 0 on success, negated errno on failure.
608#[no_mangle]
609pub extern "C" fn syd_enable_truncate() -> c_int {
610    stat("/dev/syd/sandbox/truncate:on")
611}
612
613/// Disable truncate sandboxing.
614///
615/// Returns 0 on success, negated errno on failure.
616#[no_mangle]
617pub extern "C" fn syd_disable_truncate() -> c_int {
618    stat("/dev/syd/sandbox/truncate:off")
619}
620
621/// Checks if chdir sandboxing is enabled.
622///
623/// Returns true if chdir sandboxing is enabled, false otherwise.
624#[no_mangle]
625pub extern "C" fn syd_enabled_chdir() -> bool {
626    stat("/dev/syd/sandbox/chdir?") == 0
627}
628
629/// Enable chdir sandboxing.
630///
631/// Returns 0 on success, negated errno on failure.
632#[no_mangle]
633pub extern "C" fn syd_enable_chdir() -> c_int {
634    stat("/dev/syd/sandbox/chdir:on")
635}
636
637/// Disable chdir sandboxing.
638///
639/// Returns 0 on success, negated errno on failure.
640#[no_mangle]
641pub extern "C" fn syd_disable_chdir() -> c_int {
642    stat("/dev/syd/sandbox/chdir:off")
643}
644
645/// Checks if readdir sandboxing is enabled.
646///
647/// Returns true if readdir sandboxing is enabled, false otherwise.
648#[no_mangle]
649pub extern "C" fn syd_enabled_readdir() -> bool {
650    stat("/dev/syd/sandbox/readdir?") == 0
651}
652
653/// Enable readdir sandboxing.
654///
655/// Returns 0 on success, negated errno on failure.
656#[no_mangle]
657pub extern "C" fn syd_enable_readdir() -> c_int {
658    stat("/dev/syd/sandbox/readdir:on")
659}
660
661/// Disable readdir sandboxing.
662///
663/// Returns 0 on success, negated errno on failure.
664#[no_mangle]
665pub extern "C" fn syd_disable_readdir() -> c_int {
666    stat("/dev/syd/sandbox/readdir:off")
667}
668
669/// Checks if mkdir sandboxing is enabled.
670///
671/// Returns true if mkdir sandboxing is enabled, false otherwise.
672#[no_mangle]
673pub extern "C" fn syd_enabled_mkdir() -> bool {
674    stat("/dev/syd/sandbox/mkdir?") == 0
675}
676
677/// Enable mkdir sandboxing.
678///
679/// Returns 0 on success, negated errno on failure.
680#[no_mangle]
681pub extern "C" fn syd_enable_mkdir() -> c_int {
682    stat("/dev/syd/sandbox/mkdir:on")
683}
684
685/// Disable mkdir sandboxing.
686///
687/// Returns 0 on success, negated errno on failure.
688#[no_mangle]
689pub extern "C" fn syd_disable_mkdir() -> c_int {
690    stat("/dev/syd/sandbox/mkdir:off")
691}
692
693/// Checks if rmdir sandboxing is enabled.
694///
695/// Returns true if rmdir sandboxing is enabled, false otherwise.
696#[no_mangle]
697pub extern "C" fn syd_enabled_rmdir() -> bool {
698    stat("/dev/syd/sandbox/rmdir?") == 0
699}
700
701/// Enable rmdir sandboxing.
702///
703/// Returns 0 on success, negated errno on failure.
704#[no_mangle]
705pub extern "C" fn syd_enable_rmdir() -> c_int {
706    stat("/dev/syd/sandbox/rmdir:on")
707}
708
709/// Disable rmdir sandboxing.
710///
711/// Returns 0 on success, negated errno on failure.
712#[no_mangle]
713pub extern "C" fn syd_disable_rmdir() -> c_int {
714    stat("/dev/syd/sandbox/rmdir:off")
715}
716
717/// Checks if chown sandboxing is enabled.
718///
719/// Returns true if chown sandboxing is enabled, false otherwise.
720#[no_mangle]
721pub extern "C" fn syd_enabled_chown() -> bool {
722    stat("/dev/syd/sandbox/chown?") == 0
723}
724
725/// Enable chown sandboxing.
726///
727/// Returns 0 on success, negated errno on failure.
728#[no_mangle]
729pub extern "C" fn syd_enable_chown() -> c_int {
730    stat("/dev/syd/sandbox/chown:on")
731}
732
733/// Disable chown sandboxing.
734///
735/// Returns 0 on success, negated errno on failure.
736#[no_mangle]
737pub extern "C" fn syd_disable_chown() -> c_int {
738    stat("/dev/syd/sandbox/chown:off")
739}
740
741/// Checks if chgrp sandboxing is enabled.
742///
743/// Returns true if chgrp sandboxing is enabled, false otherwise.
744#[no_mangle]
745pub extern "C" fn syd_enabled_chgrp() -> bool {
746    stat("/dev/syd/sandbox/chgrp?") == 0
747}
748
749/// Enable chgrp sandboxing.
750///
751/// Returns 0 on success, negated errno on failure.
752#[no_mangle]
753pub extern "C" fn syd_enable_chgrp() -> c_int {
754    stat("/dev/syd/sandbox/chgrp:on")
755}
756
757/// Disable chgrp sandboxing.
758///
759/// Returns 0 on success, negated errno on failure.
760#[no_mangle]
761pub extern "C" fn syd_disable_chgrp() -> c_int {
762    stat("/dev/syd/sandbox/chgrp:off")
763}
764
765/// Checks if chmod sandboxing is enabled.
766///
767/// Returns true if chmod sandboxing is enabled, false otherwise.
768#[no_mangle]
769pub extern "C" fn syd_enabled_chmod() -> bool {
770    stat("/dev/syd/sandbox/chmod?") == 0
771}
772
773/// Enable chmod sandboxing.
774///
775/// Returns 0 on success, negated errno on failure.
776#[no_mangle]
777pub extern "C" fn syd_enable_chmod() -> c_int {
778    stat("/dev/syd/sandbox/chmod:on")
779}
780
781/// Disable chmod sandboxing.
782///
783/// Returns 0 on success, negated errno on failure.
784#[no_mangle]
785pub extern "C" fn syd_disable_chmod() -> c_int {
786    stat("/dev/syd/sandbox/chmod:off")
787}
788
789/// Checks if chattr sandboxing is enabled.
790///
791/// Returns true if chattr sandboxing is enabled, false otherwise.
792#[no_mangle]
793pub extern "C" fn syd_enabled_chattr() -> bool {
794    stat("/dev/syd/sandbox/chattr?") == 0
795}
796
797/// Enable chattr sandboxing.
798///
799/// Returns 0 on success, negated errno on failure.
800#[no_mangle]
801pub extern "C" fn syd_enable_chattr() -> c_int {
802    stat("/dev/syd/sandbox/chattr:on")
803}
804
805/// Disable chattr sandboxing.
806///
807/// Returns 0 on success, negated errno on failure.
808#[no_mangle]
809pub extern "C" fn syd_disable_chattr() -> c_int {
810    stat("/dev/syd/sandbox/chattr:off")
811}
812
813/// Checks if chroot sandboxing is enabled.
814///
815/// Returns true if chroot sandboxing is enabled, false otherwise.
816#[no_mangle]
817pub extern "C" fn syd_enabled_chroot() -> bool {
818    stat("/dev/syd/sandbox/chroot?") == 0
819}
820
821/// Enable chroot sandboxing.
822///
823/// Returns 0 on success, negated errno on failure.
824#[no_mangle]
825pub extern "C" fn syd_enable_chroot() -> c_int {
826    stat("/dev/syd/sandbox/chroot:on")
827}
828
829/// Disable chroot sandboxing.
830///
831/// Returns 0 on success, negated errno on failure.
832#[no_mangle]
833pub extern "C" fn syd_disable_chroot() -> c_int {
834    stat("/dev/syd/sandbox/chroot:off")
835}
836
837/// Checks if utime sandboxing is enabled.
838///
839/// Returns true if utime sandboxing is enabled, false otherwise.
840#[no_mangle]
841pub extern "C" fn syd_enabled_utime() -> bool {
842    stat("/dev/syd/sandbox/utime?") == 0
843}
844
845/// Enable utime sandboxing.
846///
847/// Returns 0 on success, negated errno on failure.
848#[no_mangle]
849pub extern "C" fn syd_enable_utime() -> c_int {
850    stat("/dev/syd/sandbox/utime:on")
851}
852
853/// Disable utime sandboxing.
854///
855/// Returns 0 on success, negated errno on failure.
856#[no_mangle]
857pub extern "C" fn syd_disable_utime() -> c_int {
858    stat("/dev/syd/sandbox/utime:off")
859}
860
861/// Checks if mkbdev sandboxing is enabled.
862///
863/// Returns true if mkbdev sandboxing is enabled, false otherwise.
864#[no_mangle]
865pub extern "C" fn syd_enabled_mkbdev() -> bool {
866    stat("/dev/syd/sandbox/mkbdev?") == 0
867}
868
869/// Enable mkbdev sandboxing.
870///
871/// Returns 0 on success, negated errno on failure.
872#[no_mangle]
873pub extern "C" fn syd_enable_mkbdev() -> c_int {
874    stat("/dev/syd/sandbox/mkbdev:on")
875}
876
877/// Disable mkbdev sandboxing.
878///
879/// Returns 0 on success, negated errno on failure.
880#[no_mangle]
881pub extern "C" fn syd_disable_mkbdev() -> c_int {
882    stat("/dev/syd/sandbox/mkbdev:off")
883}
884
885/// Checks if mkcdev sandboxing is enabled.
886///
887/// Returns true if mkcdev sandboxing is enabled, false otherwise.
888#[no_mangle]
889pub extern "C" fn syd_enabled_mkcdev() -> bool {
890    stat("/dev/syd/sandbox/mkcdev?") == 0
891}
892
893/// Enable mkcdev sandboxing.
894///
895/// Returns 0 on success, negated errno on failure.
896#[no_mangle]
897pub extern "C" fn syd_enable_mkcdev() -> c_int {
898    stat("/dev/syd/sandbox/mkcdev:on")
899}
900
901/// Disable mkcdev sandboxing.
902///
903/// Returns 0 on success, negated errno on failure.
904#[no_mangle]
905pub extern "C" fn syd_disable_mkcdev() -> c_int {
906    stat("/dev/syd/sandbox/mkcdev:off")
907}
908
909/// Checks if mkfifo sandboxing is enabled.
910///
911/// Returns true if mkfifo sandboxing is enabled, false otherwise.
912#[no_mangle]
913pub extern "C" fn syd_enabled_mkfifo() -> bool {
914    stat("/dev/syd/sandbox/mkfifo?") == 0
915}
916
917/// Enable mkfifo sandboxing.
918///
919/// Returns 0 on success, negated errno on failure.
920#[no_mangle]
921pub extern "C" fn syd_enable_mkfifo() -> c_int {
922    stat("/dev/syd/sandbox/mkfifo:on")
923}
924
925/// Disable mkfifo sandboxing.
926///
927/// Returns 0 on success, negated errno on failure.
928#[no_mangle]
929pub extern "C" fn syd_disable_mkfifo() -> c_int {
930    stat("/dev/syd/sandbox/mkfifo:off")
931}
932
933/// Checks if mktemp sandboxing is enabled.
934///
935/// Returns true if mktemp sandboxing is enabled, false otherwise.
936#[no_mangle]
937pub extern "C" fn syd_enabled_mktemp() -> bool {
938    stat("/dev/syd/sandbox/mktemp?") == 0
939}
940
941/// Enable mktemp sandboxing.
942///
943/// Returns 0 on success, negated errno on failure.
944#[no_mangle]
945pub extern "C" fn syd_enable_mktemp() -> c_int {
946    stat("/dev/syd/sandbox/mktemp:on")
947}
948
949/// Disable mktemp sandboxing.
950///
951/// Returns 0 on success, negated errno on failure.
952#[no_mangle]
953pub extern "C" fn syd_disable_mktemp() -> c_int {
954    stat("/dev/syd/sandbox/mktemp:off")
955}
956
957/// Checks if net sandboxing is enabled.
958///
959/// Returns true if net sandboxing is enabled, false otherwise.
960#[no_mangle]
961pub extern "C" fn syd_enabled_net() -> bool {
962    stat("/dev/syd/sandbox/net?") == 0
963}
964
965/// Enable net sandboxing.
966///
967/// Returns 0 on success, negated errno on failure.
968#[no_mangle]
969pub extern "C" fn syd_enable_net() -> c_int {
970    stat("/dev/syd/sandbox/net:on")
971}
972
973/// Disable net sandboxing.
974///
975/// Returns 0 on success, negated errno on failure.
976#[no_mangle]
977pub extern "C" fn syd_disable_net() -> c_int {
978    stat("/dev/syd/sandbox/net:off")
979}
980
981/// Checks if memory sandboxing is enabled.
982///
983/// Returns true if memory sandboxing is enabled, false otherwise.
984#[no_mangle]
985pub extern "C" fn syd_enabled_mem() -> bool {
986    stat("/dev/syd/sandbox/mem?") == 0
987}
988
989/// Enable memory sandboxing.
990///
991/// Returns 0 on success, negated errno on failure.
992#[no_mangle]
993pub extern "C" fn syd_enable_mem() -> c_int {
994    stat("/dev/syd/sandbox/mem:on")
995}
996
997/// Disable memory sandboxing.
998///
999/// Returns 0 on success, negated errno on failure.
1000#[no_mangle]
1001pub extern "C" fn syd_disable_mem() -> c_int {
1002    stat("/dev/syd/sandbox/mem:off")
1003}
1004
1005/// Checks if PID sandboxing is enabled.
1006///
1007/// Returns true if PID sandboxing is enabled, false otherwise.
1008#[no_mangle]
1009pub extern "C" fn syd_enabled_pid() -> bool {
1010    stat("/dev/syd/sandbox/pid?") == 0
1011}
1012
1013/// Enable PID sandboxing.
1014///
1015/// Returns 0 on success, negated errno on failure.
1016#[no_mangle]
1017pub extern "C" fn syd_enable_pid() -> c_int {
1018    stat("/dev/syd/sandbox/pid:on")
1019}
1020
1021/// Disable PID sandboxing.
1022///
1023/// Returns 0 on success, negated errno on failure.
1024#[no_mangle]
1025pub extern "C" fn syd_disable_pid() -> c_int {
1026    stat("/dev/syd/sandbox/pid:off")
1027}
1028
1029/// Checks if lock sandboxing is enabled.
1030///
1031/// Returns true if lock sandboxing is enabled, false otherwise.
1032#[no_mangle]
1033pub extern "C" fn syd_enabled_lock() -> bool {
1034    stat("/dev/syd/sandbox/lock?") == 0
1035}
1036
1037/// Checks if crypt sandboxing is enabled.
1038///
1039/// Returns true if crypt sandboxing is enabled, false otherwise.
1040#[no_mangle]
1041pub extern "C" fn syd_enabled_crypt() -> bool {
1042    stat("/dev/syd/sandbox/crypt?") == 0
1043}
1044
1045/// Checks if proxy sandboxing is enabled.
1046///
1047/// Returns true if proxy sandboxing is enabled, false otherwise.
1048#[no_mangle]
1049pub extern "C" fn syd_enabled_proxy() -> bool {
1050    stat("/dev/syd/sandbox/proxy?") == 0
1051}
1052
1053/// Checks if force sandboxing is enabled.
1054///
1055/// Returns true if force sandboxing is enabled, false otherwise.
1056#[no_mangle]
1057pub extern "C" fn syd_enabled_force() -> bool {
1058    stat("/dev/syd/sandbox/force?") == 0
1059}
1060
1061/// Enable force sandboxing.
1062///
1063/// Returns 0 on success, negated errno on failure.
1064#[no_mangle]
1065pub extern "C" fn syd_enable_force() -> c_int {
1066    stat("/dev/syd/sandbox/force:on")
1067}
1068
1069/// Disable force sandboxing.
1070///
1071/// Returns 0 on success, negated errno on failure.
1072#[no_mangle]
1073pub extern "C" fn syd_disable_force() -> c_int {
1074    stat("/dev/syd/sandbox/force:off")
1075}
1076
1077/// Checks if TPE sandboxing is enabled.
1078///
1079/// Returns true if TPE sandboxing is enabled, false otherwise.
1080#[no_mangle]
1081pub extern "C" fn syd_enabled_tpe() -> bool {
1082    stat("/dev/syd/sandbox/tpe?") == 0
1083}
1084
1085/// Enable TPE sandboxing.
1086///
1087/// Returns 0 on success, negated errno on failure.
1088#[no_mangle]
1089pub extern "C" fn syd_enable_tpe() -> c_int {
1090    stat("/dev/syd/sandbox/tpe:on")
1091}
1092
1093/// Disable TPE sandboxing.
1094///
1095/// Returns 0 on success, negated errno on failure.
1096#[no_mangle]
1097pub extern "C" fn syd_disable_tpe() -> c_int {
1098    stat("/dev/syd/sandbox/tpe:off")
1099}
1100
1101/// Set the default action for Walk Sandboxing.
1102#[no_mangle]
1103pub extern "C" fn syd_default_walk(action: action_t) -> c_int {
1104    // Convert action_t enum to corresponding action string.
1105    let action = match Action::try_from(action) {
1106        Ok(action) => action,
1107        Err(_) => return -EINVAL,
1108    };
1109    stat(&format!("/dev/syd/default/walk:{action}"))
1110}
1111
1112/// Set the default action for Stat Sandboxing.
1113#[no_mangle]
1114pub extern "C" fn syd_default_stat(action: action_t) -> c_int {
1115    // Convert action_t enum to corresponding action string.
1116    let action = match Action::try_from(action) {
1117        Ok(action) => action,
1118        Err(_) => return -EINVAL,
1119    };
1120    stat(&format!("/dev/syd/default/stat:{action}"))
1121}
1122
1123/// Set the default action for Read Sandboxing.
1124#[no_mangle]
1125pub extern "C" fn syd_default_read(action: action_t) -> c_int {
1126    // Convert action_t enum to corresponding action string.
1127    let action = match Action::try_from(action) {
1128        Ok(action) => action,
1129        Err(_) => return -EINVAL,
1130    };
1131    stat(&format!("/dev/syd/default/read:{action}"))
1132}
1133
1134/// Set the default action for Write Sandboxing.
1135#[no_mangle]
1136pub extern "C" fn syd_default_write(action: action_t) -> c_int {
1137    // Convert action_t enum to corresponding action string.
1138    let action = match Action::try_from(action) {
1139        Ok(action) => action,
1140        Err(_) => return -EINVAL,
1141    };
1142    stat(&format!("/dev/syd/default/write:{action}"))
1143}
1144
1145/// Set the default action for Exec Sandboxing.
1146#[no_mangle]
1147pub extern "C" fn syd_default_exec(action: action_t) -> c_int {
1148    // Convert action_t enum to corresponding action string.
1149    let action = match Action::try_from(action) {
1150        Ok(action) => action,
1151        Err(_) => return -EINVAL,
1152    };
1153    stat(&format!("/dev/syd/default/exec:{action}"))
1154}
1155
1156/// Set the default action for Ioctl Sandboxing.
1157#[no_mangle]
1158pub extern "C" fn syd_default_ioctl(action: action_t) -> c_int {
1159    // Convert action_t enum to corresponding action string.
1160    let action = match Action::try_from(action) {
1161        Ok(action) => action,
1162        Err(_) => return -EINVAL,
1163    };
1164    stat(&format!("/dev/syd/default/ioctl:{action}"))
1165}
1166
1167/// Set the default action for Create Sandboxing.
1168#[no_mangle]
1169pub extern "C" fn syd_default_create(action: action_t) -> c_int {
1170    // Convert action_t enum to corresponding action string.
1171    let action = match Action::try_from(action) {
1172        Ok(action) => action,
1173        Err(_) => return -EINVAL,
1174    };
1175    stat(&format!("/dev/syd/default/create:{action}"))
1176}
1177
1178/// Set the default action for Delete Sandboxing.
1179#[no_mangle]
1180pub extern "C" fn syd_default_delete(action: action_t) -> c_int {
1181    // Convert action_t enum to corresponding action string.
1182    let action = match Action::try_from(action) {
1183        Ok(action) => action,
1184        Err(_) => return -EINVAL,
1185    };
1186    stat(&format!("/dev/syd/default/delete:{action}"))
1187}
1188
1189/// Set the default action for Rename Sandboxing.
1190#[no_mangle]
1191pub extern "C" fn syd_default_rename(action: action_t) -> c_int {
1192    // Convert action_t enum to corresponding action string.
1193    let action = match Action::try_from(action) {
1194        Ok(action) => action,
1195        Err(_) => return -EINVAL,
1196    };
1197    stat(&format!("/dev/syd/default/rename:{action}"))
1198}
1199
1200/// Set the default action for Symlink Sandboxing.
1201#[no_mangle]
1202pub extern "C" fn syd_default_symlink(action: action_t) -> c_int {
1203    // Convert action_t enum to corresponding action string.
1204    let action = match Action::try_from(action) {
1205        Ok(action) => action,
1206        Err(_) => return -EINVAL,
1207    };
1208    stat(&format!("/dev/syd/default/symlink:{action}"))
1209}
1210
1211/// Set the default action for Truncate Sandboxing.
1212#[no_mangle]
1213pub extern "C" fn syd_default_truncate(action: action_t) -> c_int {
1214    // Convert action_t enum to corresponding action string.
1215    let action = match Action::try_from(action) {
1216        Ok(action) => action,
1217        Err(_) => return -EINVAL,
1218    };
1219    stat(&format!("/dev/syd/default/truncate:{action}"))
1220}
1221
1222/// Set the default action for Chdir Sandboxing.
1223#[no_mangle]
1224pub extern "C" fn syd_default_chdir(action: action_t) -> c_int {
1225    // Convert action_t enum to corresponding action string.
1226    let action = match Action::try_from(action) {
1227        Ok(action) => action,
1228        Err(_) => return -EINVAL,
1229    };
1230    stat(&format!("/dev/syd/default/chdir:{action}"))
1231}
1232
1233/// Set the default action for Readdir Sandboxing.
1234#[no_mangle]
1235pub extern "C" fn syd_default_readdir(action: action_t) -> c_int {
1236    // Convert action_t enum to corresponding action string.
1237    let action = match Action::try_from(action) {
1238        Ok(action) => action,
1239        Err(_) => return -EINVAL,
1240    };
1241    stat(&format!("/dev/syd/default/readdir:{action}"))
1242}
1243
1244/// Set the default action for Mkdir Sandboxing.
1245#[no_mangle]
1246pub extern "C" fn syd_default_mkdir(action: action_t) -> c_int {
1247    // Convert action_t enum to corresponding action string.
1248    let action = match Action::try_from(action) {
1249        Ok(action) => action,
1250        Err(_) => return -EINVAL,
1251    };
1252    stat(&format!("/dev/syd/default/mkdir:{action}"))
1253}
1254
1255/// Set the default action for Rmdir Sandboxing.
1256#[no_mangle]
1257pub extern "C" fn syd_default_rmdir(action: action_t) -> c_int {
1258    // Convert action_t enum to corresponding action string.
1259    let action = match Action::try_from(action) {
1260        Ok(action) => action,
1261        Err(_) => return -EINVAL,
1262    };
1263    stat(&format!("/dev/syd/default/rmdir:{action}"))
1264}
1265
1266/// Set the default action for Chown Sandboxing.
1267#[no_mangle]
1268pub extern "C" fn syd_default_chown(action: action_t) -> c_int {
1269    // Convert action_t enum to corresponding action string.
1270    let action = match Action::try_from(action) {
1271        Ok(action) => action,
1272        Err(_) => return -EINVAL,
1273    };
1274    stat(&format!("/dev/syd/default/chown:{action}"))
1275}
1276
1277/// Set the default action for Chgrp Sandboxing.
1278#[no_mangle]
1279pub extern "C" fn syd_default_chgrp(action: action_t) -> c_int {
1280    // Convert action_t enum to corresponding action string.
1281    let action = match Action::try_from(action) {
1282        Ok(action) => action,
1283        Err(_) => return -EINVAL,
1284    };
1285    stat(&format!("/dev/syd/default/chgrp:{action}"))
1286}
1287
1288/// Set the default action for Chmod Sandboxing.
1289#[no_mangle]
1290pub extern "C" fn syd_default_chmod(action: action_t) -> c_int {
1291    // Convert action_t enum to corresponding action string.
1292    let action = match Action::try_from(action) {
1293        Ok(action) => action,
1294        Err(_) => return -EINVAL,
1295    };
1296    stat(&format!("/dev/syd/default/chmod:{action}"))
1297}
1298
1299/// Set the default action for Chattr Sandboxing.
1300#[no_mangle]
1301pub extern "C" fn syd_default_chattr(action: action_t) -> c_int {
1302    // Convert action_t enum to corresponding action string.
1303    let action = match Action::try_from(action) {
1304        Ok(action) => action,
1305        Err(_) => return -EINVAL,
1306    };
1307    stat(&format!("/dev/syd/default/chattr:{action}"))
1308}
1309
1310/// Set the default action for Chroot Sandboxing.
1311#[no_mangle]
1312pub extern "C" fn syd_default_chroot(action: action_t) -> c_int {
1313    // Convert action_t enum to corresponding action string.
1314    let action = match Action::try_from(action) {
1315        Ok(action) => action,
1316        Err(_) => return -EINVAL,
1317    };
1318    stat(&format!("/dev/syd/default/chroot:{action}"))
1319}
1320
1321/// Set the default action for Utime Sandboxing.
1322#[no_mangle]
1323pub extern "C" fn syd_default_utime(action: action_t) -> c_int {
1324    // Convert action_t enum to corresponding action string.
1325    let action = match Action::try_from(action) {
1326        Ok(action) => action,
1327        Err(_) => return -EINVAL,
1328    };
1329    stat(&format!("/dev/syd/default/utime:{action}"))
1330}
1331
1332/// Set the default action for Mkbdev Sandboxing.
1333#[no_mangle]
1334pub extern "C" fn syd_default_mkbdev(action: action_t) -> c_int {
1335    // Convert action_t enum to corresponding action string.
1336    let action = match Action::try_from(action) {
1337        Ok(action) => action,
1338        Err(_) => return -EINVAL,
1339    };
1340    stat(&format!("/dev/syd/default/mkbdev:{action}"))
1341}
1342
1343/// Set the default action for Mkcdev Sandboxing.
1344#[no_mangle]
1345pub extern "C" fn syd_default_mkcdev(action: action_t) -> c_int {
1346    // Convert action_t enum to corresponding action string.
1347    let action = match Action::try_from(action) {
1348        Ok(action) => action,
1349        Err(_) => return -EINVAL,
1350    };
1351    stat(&format!("/dev/syd/default/mkcdev:{action}"))
1352}
1353
1354/// Set the default action for Mkfifo Sandboxing.
1355#[no_mangle]
1356pub extern "C" fn syd_default_mkfifo(action: action_t) -> c_int {
1357    // Convert action_t enum to corresponding action string.
1358    let action = match Action::try_from(action) {
1359        Ok(action) => action,
1360        Err(_) => return -EINVAL,
1361    };
1362    stat(&format!("/dev/syd/default/mkfifo:{action}"))
1363}
1364
1365/// Set the default action for Mktemp Sandboxing.
1366#[no_mangle]
1367pub extern "C" fn syd_default_mktemp(action: action_t) -> c_int {
1368    // Convert action_t enum to corresponding action string.
1369    let action = match Action::try_from(action) {
1370        Ok(action) => action,
1371        Err(_) => return -EINVAL,
1372    };
1373    stat(&format!("/dev/syd/default/mktemp:{action}"))
1374}
1375
1376/// Set the default action for Network Sandboxing.
1377#[no_mangle]
1378pub extern "C" fn syd_default_net(action: action_t) -> c_int {
1379    // Convert action_t enum to corresponding action string.
1380    let action = match Action::try_from(action) {
1381        Ok(action) => action,
1382        Err(_) => return -EINVAL,
1383    };
1384    stat(&format!("/dev/syd/default/net:{action}"))
1385}
1386
1387/// Set the default action for IP blocklist violations.
1388#[no_mangle]
1389pub extern "C" fn syd_default_block(action: action_t) -> c_int {
1390    // Convert action_t enum to corresponding action string.
1391    let action = match Action::try_from(action) {
1392        Ok(action) => action,
1393        Err(_) => return -EINVAL,
1394    };
1395    stat(&format!("/dev/syd/default/block:{action}"))
1396}
1397
1398/// Set the default action for Memory Sandboxing.
1399#[no_mangle]
1400pub extern "C" fn syd_default_mem(action: action_t) -> c_int {
1401    // Convert action_t enum to corresponding action string.
1402    let action = match Action::try_from(action) {
1403        Ok(action) => action,
1404        Err(_) => return -EINVAL,
1405    };
1406    stat(&format!("/dev/syd/default/mem:{action}"))
1407}
1408
1409/// Set the default action for PID Sandboxing.
1410#[no_mangle]
1411pub extern "C" fn syd_default_pid(action: action_t) -> c_int {
1412    // Convert action_t enum to corresponding action string.
1413    let action = match Action::try_from(action) {
1414        Ok(action) => action,
1415        Err(_) => return -EINVAL,
1416    };
1417    stat(&format!("/dev/syd/default/pid:{action}"))
1418}
1419
1420/// Set the default action for Force Sandboxing.
1421#[no_mangle]
1422pub extern "C" fn syd_default_force(action: action_t) -> c_int {
1423    // Convert action_t enum to corresponding action string.
1424    let action = match Action::try_from(action) {
1425        Ok(action) => action,
1426        Err(_) => return -EINVAL,
1427    };
1428    stat(&format!("/dev/syd/default/force:{action}"))
1429}
1430
1431/// Set the default action for SegvGuard
1432#[no_mangle]
1433pub extern "C" fn syd_default_segvguard(action: action_t) -> c_int {
1434    // Convert action_t enum to corresponding action string.
1435    let action = match Action::try_from(action) {
1436        Ok(action) => action,
1437        Err(_) => return -EINVAL,
1438    };
1439    stat(&format!("/dev/syd/default/segvguard:{action}"))
1440}
1441
1442/// Set the default action for TPE Sandboxing.
1443#[no_mangle]
1444pub extern "C" fn syd_default_tpe(action: action_t) -> c_int {
1445    // Convert action_t enum to corresponding action string.
1446    let action = match Action::try_from(action) {
1447        Ok(action) => action,
1448        Err(_) => return -EINVAL,
1449    };
1450    stat(&format!("/dev/syd/default/tpe:{action}"))
1451}
1452
1453/// Adds a request to the _ioctl_(2) denylist.
1454#[no_mangle]
1455pub extern "C" fn syd_ioctl_deny(request: u64) -> c_int {
1456    stat(&format!("/dev/syd/ioctl/deny+{request}"))
1457}
1458
1459/// Adds an entry to the Integrity Force map for Force Sandboxing.
1460///
1461/// # Safety
1462///
1463/// This function is marked `unsafe` because it dereferences raw
1464/// pointers, which is inherently unsafe in Rust.
1465///
1466/// The caller must ensure the following conditions are met to safely
1467/// use this function:
1468///
1469/// 1. The `path` pointer must point to a valid, null-terminated C-style
1470///    string.
1471/// 2. The `hash` pointer must point to a valid, null-terminated C-style
1472///    string.
1473#[no_mangle]
1474pub unsafe extern "C" fn syd_force_add(
1475    path: *const c_char,
1476    hash: *const c_char,
1477    action: action_t,
1478) -> c_int {
1479    // Convert action_t enum to corresponding action string.
1480    let action = match Action::try_from(action) {
1481        Ok(action) => action,
1482        Err(_) => return -EINVAL,
1483    };
1484
1485    if path.is_null() || hash.is_null() {
1486        return -EFAULT;
1487    }
1488
1489    // SAFETY: Trust that `path` and `hash` are a null-terminated strings.
1490    let path = unsafe { CStr::from_ptr(path) };
1491    // SAFETY: ditto
1492    let hash = unsafe { CStr::from_ptr(hash) };
1493    let path = match path.to_str() {
1494        Ok(s) => s,
1495        Err(_) => return -EINVAL,
1496    };
1497    let hash = match hash.to_str() {
1498        Ok(s) => s,
1499        Err(_) => return -EINVAL,
1500    };
1501
1502    // Call the stat function with the formatted string.
1503    stat(format!("/dev/syd/force+{path}:{hash}:{action}"))
1504}
1505
1506/// Removes an entry from the Integrity Force map for Force Sandboxing.
1507/// # Safety
1508///
1509/// This function is marked `unsafe` because it dereferences raw
1510/// pointers, which is inherently unsafe in Rust.
1511///
1512/// The caller must ensure the following conditions are met to safely
1513/// use this function:
1514///
1515/// 1. The `path` pointer must point to a valid, null-terminated C-style
1516///    string.
1517#[no_mangle]
1518pub unsafe extern "C" fn syd_force_del(path: *const c_char) -> c_int {
1519    if path.is_null() {
1520        return -EFAULT;
1521    }
1522
1523    // SAFETY: Trust that `path` is a null-terminated string.
1524    let path = unsafe { CStr::from_ptr(path) };
1525    let path = match path.to_str() {
1526        Ok(s) => s,
1527        Err(_) => return -EINVAL,
1528    };
1529
1530    // Call the stat function with the formatted string.
1531    stat(format!("/dev/syd/force-{path}"))
1532}
1533
1534/// Clears the Integrity Force map for Force Sandboxing.
1535#[no_mangle]
1536pub extern "C" fn syd_force_clr() -> c_int {
1537    stat("/dev/syd/force^")
1538}
1539
1540/// Adds to the given actionlist of walk sandboxing.
1541///
1542/// Returns 0 on success, negated errno on failure.
1543#[no_mangle]
1544pub extern "C" fn syd_walk_add(action: action_t, glob: *const c_char) -> c_int {
1545    // Convert action_t enum to corresponding action string.
1546    let action = match Action::try_from(action) {
1547        Ok(action) => action,
1548        Err(_) => return -EINVAL,
1549    };
1550
1551    // Call magic function with add operator.
1552    esyd(&format!("{action}/walk"), glob, b'+')
1553}
1554
1555/// Removes the first instance from the end of the given actionlist of
1556/// walk sandboxing.
1557///
1558/// Returns 0 on success, negated errno on failure.
1559#[no_mangle]
1560pub extern "C" fn syd_walk_del(action: action_t, glob: *const c_char) -> c_int {
1561    // Convert action_t enum to corresponding action string.
1562    let action = match Action::try_from(action) {
1563        Ok(action) => action,
1564        Err(_) => return -EINVAL,
1565    };
1566
1567    // Call magic function with del operator.
1568    esyd(&format!("{action}/walk"), glob, b'-')
1569}
1570
1571/// Removes all matching patterns from the given actionlist of walk sandboxing.
1572///
1573/// Returns 0 on success, negated errno on failure.
1574#[no_mangle]
1575pub extern "C" fn syd_walk_rem(action: action_t, glob: *const c_char) -> c_int {
1576    // Convert action_t enum to corresponding action string.
1577    let action = match Action::try_from(action) {
1578        Ok(action) => action,
1579        Err(_) => return -EINVAL,
1580    };
1581
1582    // Call magic function with rem operator.
1583    esyd(&format!("{action}/walk"), glob, b'^')
1584}
1585
1586/// Adds to the given actionlist of stat sandboxing.
1587///
1588/// Returns 0 on success, negated errno on failure.
1589#[no_mangle]
1590pub extern "C" fn syd_stat_add(action: action_t, glob: *const c_char) -> c_int {
1591    // Convert action_t enum to corresponding action string.
1592    let action = match Action::try_from(action) {
1593        Ok(action) => action,
1594        Err(_) => return -EINVAL,
1595    };
1596
1597    // Call magic function with add operator.
1598    esyd(&format!("{action}/stat"), glob, b'+')
1599}
1600
1601/// Removes the first instance from the end of the given actionlist of
1602/// stat sandboxing.
1603///
1604/// Returns 0 on success, negated errno on failure.
1605#[no_mangle]
1606pub extern "C" fn syd_stat_del(action: action_t, glob: *const c_char) -> c_int {
1607    // Convert action_t enum to corresponding action string.
1608    let action = match Action::try_from(action) {
1609        Ok(action) => action,
1610        Err(_) => return -EINVAL,
1611    };
1612
1613    // Call magic function with del operator.
1614    esyd(&format!("{action}/stat"), glob, b'-')
1615}
1616
1617/// Removes all matching patterns from the given actionlist of stat sandboxing.
1618///
1619/// Returns 0 on success, negated errno on failure.
1620#[no_mangle]
1621pub extern "C" fn syd_stat_rem(action: action_t, glob: *const c_char) -> c_int {
1622    // Convert action_t enum to corresponding action string.
1623    let action = match Action::try_from(action) {
1624        Ok(action) => action,
1625        Err(_) => return -EINVAL,
1626    };
1627
1628    // Call magic function with rem operator.
1629    esyd(&format!("{action}/stat"), glob, b'^')
1630}
1631
1632/// Adds to the given actionlist of read sandboxing.
1633///
1634/// Returns 0 on success, negated errno on failure.
1635#[no_mangle]
1636pub extern "C" fn syd_read_add(action: action_t, glob: *const c_char) -> c_int {
1637    // Convert action_t enum to corresponding action string.
1638    let action = match Action::try_from(action) {
1639        Ok(action) => action,
1640        Err(_) => return -EINVAL,
1641    };
1642
1643    // Call magic function with add operator.
1644    esyd(&format!("{action}/read"), glob, b'+')
1645}
1646
1647/// Removes the first instance from the end of the given actionlist of
1648/// read sandboxing.
1649///
1650/// Returns 0 on success, negated errno on failure.
1651#[no_mangle]
1652pub extern "C" fn syd_read_del(action: action_t, glob: *const c_char) -> c_int {
1653    // Convert action_t enum to corresponding action string.
1654    let action = match Action::try_from(action) {
1655        Ok(action) => action,
1656        Err(_) => return -EINVAL,
1657    };
1658
1659    // Call magic function with del operator.
1660    esyd(&format!("{action}/read"), glob, b'-')
1661}
1662
1663/// Removes all matching patterns from the given actionlist of read sandboxing.
1664///
1665/// Returns 0 on success, negated errno on failure.
1666#[no_mangle]
1667pub extern "C" fn syd_read_rem(action: action_t, glob: *const c_char) -> c_int {
1668    // Convert action_t enum to corresponding action string.
1669    let action = match Action::try_from(action) {
1670        Ok(action) => action,
1671        Err(_) => return -EINVAL,
1672    };
1673
1674    // Call magic function with rem operator.
1675    esyd(&format!("{action}/read"), glob, b'^')
1676}
1677
1678/// Adds to the given actionlist of write sandboxing.
1679///
1680/// Returns 0 on success, negated errno on failure.
1681#[no_mangle]
1682pub extern "C" fn syd_write_add(action: action_t, glob: *const c_char) -> c_int {
1683    // Convert action_t enum to corresponding action string.
1684    let action = match Action::try_from(action) {
1685        Ok(action) => action,
1686        Err(_) => return -EINVAL,
1687    };
1688
1689    // Call magic function with add operator.
1690    esyd(&format!("{action}/write"), glob, b'+')
1691}
1692
1693/// Removes the first instance from the end of the given actionlist of
1694/// write sandboxing.
1695///
1696/// Returns 0 on success, negated errno on failure.
1697#[no_mangle]
1698pub extern "C" fn syd_write_del(action: action_t, glob: *const c_char) -> c_int {
1699    // Convert action_t enum to corresponding action string.
1700    let action = match Action::try_from(action) {
1701        Ok(action) => action,
1702        Err(_) => return -EINVAL,
1703    };
1704
1705    // Call magic function with del operator.
1706    esyd(&format!("{action}/write"), glob, b'-')
1707}
1708
1709/// Removes all matching patterns from the given actionlist of write sandboxing.
1710///
1711/// Returns 0 on success, negated errno on failure.
1712#[no_mangle]
1713pub extern "C" fn syd_write_rem(action: action_t, glob: *const c_char) -> c_int {
1714    // Convert action_t enum to corresponding action string.
1715    let action = match Action::try_from(action) {
1716        Ok(action) => action,
1717        Err(_) => return -EINVAL,
1718    };
1719
1720    // Call magic function with rem operator.
1721    esyd(&format!("{action}/write"), glob, b'^')
1722}
1723
1724/// Adds to the given actionlist of exec sandboxing.
1725///
1726/// Returns 0 on success, negated errno on failure.
1727#[no_mangle]
1728pub extern "C" fn syd_exec_add(action: action_t, glob: *const c_char) -> c_int {
1729    // Convert action_t enum to corresponding action string.
1730    let action = match Action::try_from(action) {
1731        Ok(action) => action,
1732        Err(_) => return -EINVAL,
1733    };
1734
1735    // Call magic function with add operator.
1736    esyd(&format!("{action}/exec"), glob, b'+')
1737}
1738
1739/// Removes the first instance from the end of the given actionlist of
1740/// exec sandboxing.
1741///
1742/// Returns 0 on success, negated errno on failure.
1743#[no_mangle]
1744pub extern "C" fn syd_exec_del(action: action_t, glob: *const c_char) -> c_int {
1745    // Convert action_t enum to corresponding action string.
1746    let action = match Action::try_from(action) {
1747        Ok(action) => action,
1748        Err(_) => return -EINVAL,
1749    };
1750
1751    // Call magic function with del operator.
1752    esyd(&format!("{action}/exec"), glob, b'-')
1753}
1754
1755/// Removes all matching patterns from the given actionlist of exec sandboxing.
1756///
1757/// Returns 0 on success, negated errno on failure.
1758#[no_mangle]
1759pub extern "C" fn syd_exec_rem(action: action_t, glob: *const c_char) -> c_int {
1760    // Convert action_t enum to corresponding action string.
1761    let action = match Action::try_from(action) {
1762        Ok(action) => action,
1763        Err(_) => return -EINVAL,
1764    };
1765
1766    // Call magic function with rem operator.
1767    esyd(&format!("{action}/exec"), glob, b'^')
1768}
1769
1770/// Adds to the given actionlist of ioctl sandboxing.
1771///
1772/// Returns 0 on success, negated errno on failure.
1773#[no_mangle]
1774pub extern "C" fn syd_ioctl_add(action: action_t, glob: *const c_char) -> c_int {
1775    // Convert action_t enum to corresponding action string.
1776    let action = match Action::try_from(action) {
1777        Ok(action) => action,
1778        Err(_) => return -EINVAL,
1779    };
1780
1781    // Call magic function with add operator.
1782    esyd(&format!("{action}/ioctl"), glob, b'+')
1783}
1784
1785/// Removes the first instance from the end of the given actionlist of
1786/// ioctl sandboxing.
1787///
1788/// Returns 0 on success, negated errno on failure.
1789#[no_mangle]
1790pub extern "C" fn syd_ioctl_del(action: action_t, glob: *const c_char) -> c_int {
1791    // Convert action_t enum to corresponding action string.
1792    let action = match Action::try_from(action) {
1793        Ok(action) => action,
1794        Err(_) => return -EINVAL,
1795    };
1796
1797    // Call magic function with del operator.
1798    esyd(&format!("{action}/ioctl"), glob, b'-')
1799}
1800
1801/// Removes all matching patterns from the given actionlist of ioctl sandboxing.
1802///
1803/// Returns 0 on success, negated errno on failure.
1804#[no_mangle]
1805pub extern "C" fn syd_ioctl_rem(action: action_t, glob: *const c_char) -> c_int {
1806    // Convert action_t enum to corresponding action string.
1807    let action = match Action::try_from(action) {
1808        Ok(action) => action,
1809        Err(_) => return -EINVAL,
1810    };
1811
1812    // Call magic function with rem operator.
1813    esyd(&format!("{action}/ioctl"), glob, b'^')
1814}
1815
1816/// Adds to the given actionlist of create sandboxing.
1817///
1818/// Returns 0 on success, negated errno on failure.
1819#[no_mangle]
1820pub extern "C" fn syd_create_add(action: action_t, glob: *const c_char) -> c_int {
1821    // Convert action_t enum to corresponding action string.
1822    let action = match Action::try_from(action) {
1823        Ok(action) => action,
1824        Err(_) => return -EINVAL,
1825    };
1826
1827    // Call magic function with add operator.
1828    esyd(&format!("{action}/create"), glob, b'+')
1829}
1830
1831/// Removes the first instance from the end of the given actionlist of
1832/// create sandboxing.
1833///
1834/// Returns 0 on success, negated errno on failure.
1835#[no_mangle]
1836pub extern "C" fn syd_create_del(action: action_t, glob: *const c_char) -> c_int {
1837    // Convert action_t enum to corresponding action string.
1838    let action = match Action::try_from(action) {
1839        Ok(action) => action,
1840        Err(_) => return -EINVAL,
1841    };
1842
1843    // Call magic function with del operator.
1844    esyd(&format!("{action}/create"), glob, b'-')
1845}
1846
1847/// Removes all matching patterns from the given actionlist of create sandboxing.
1848///
1849/// Returns 0 on success, negated errno on failure.
1850#[no_mangle]
1851pub extern "C" fn syd_create_rem(action: action_t, glob: *const c_char) -> c_int {
1852    // Convert action_t enum to corresponding action string.
1853    let action = match Action::try_from(action) {
1854        Ok(action) => action,
1855        Err(_) => return -EINVAL,
1856    };
1857
1858    // Call magic function with rem operator.
1859    esyd(&format!("{action}/create"), glob, b'^')
1860}
1861
1862/// Adds to the given actionlist of delete sandboxing.
1863///
1864/// Returns 0 on success, negated errno on failure.
1865#[no_mangle]
1866pub extern "C" fn syd_delete_add(action: action_t, glob: *const c_char) -> c_int {
1867    // Convert action_t enum to corresponding action string.
1868    let action = match Action::try_from(action) {
1869        Ok(action) => action,
1870        Err(_) => return -EINVAL,
1871    };
1872
1873    // Call magic function with add operator.
1874    esyd(&format!("{action}/delete"), glob, b'+')
1875}
1876
1877/// Removes the first instance from the end of the given actionlist of
1878/// delete sandboxing.
1879///
1880/// Returns 0 on success, negated errno on failure.
1881#[no_mangle]
1882pub extern "C" fn syd_delete_del(action: action_t, glob: *const c_char) -> c_int {
1883    // Convert action_t enum to corresponding action string.
1884    let action = match Action::try_from(action) {
1885        Ok(action) => action,
1886        Err(_) => return -EINVAL,
1887    };
1888
1889    // Call magic function with del operator.
1890    esyd(&format!("{action}/delete"), glob, b'-')
1891}
1892
1893/// Removes all matching patterns from the given actionlist of delete sandboxing.
1894///
1895/// Returns 0 on success, negated errno on failure.
1896#[no_mangle]
1897pub extern "C" fn syd_delete_rem(action: action_t, glob: *const c_char) -> c_int {
1898    // Convert action_t enum to corresponding action string.
1899    let action = match Action::try_from(action) {
1900        Ok(action) => action,
1901        Err(_) => return -EINVAL,
1902    };
1903
1904    // Call magic function with rem operator.
1905    esyd(&format!("{action}/delete"), glob, b'^')
1906}
1907
1908/// Adds to the given actionlist of rename sandboxing.
1909///
1910/// Returns 0 on success, negated errno on failure.
1911#[no_mangle]
1912pub extern "C" fn syd_rename_add(action: action_t, glob: *const c_char) -> c_int {
1913    // Convert action_t enum to corresponding action string.
1914    let action = match Action::try_from(action) {
1915        Ok(action) => action,
1916        Err(_) => return -EINVAL,
1917    };
1918
1919    // Call magic function with add operator.
1920    esyd(&format!("{action}/rename"), glob, b'+')
1921}
1922
1923/// Removes the first instance from the end of the given actionlist of
1924/// rename sandboxing.
1925///
1926/// Returns 0 on success, negated errno on failure.
1927#[no_mangle]
1928pub extern "C" fn syd_rename_del(action: action_t, glob: *const c_char) -> c_int {
1929    // Convert action_t enum to corresponding action string.
1930    let action = match Action::try_from(action) {
1931        Ok(action) => action,
1932        Err(_) => return -EINVAL,
1933    };
1934
1935    // Call magic function with del operator.
1936    esyd(&format!("{action}/rename"), glob, b'-')
1937}
1938
1939/// Removes all matching patterns from the given actionlist of rename sandboxing.
1940///
1941/// Returns 0 on success, negated errno on failure.
1942#[no_mangle]
1943pub extern "C" fn syd_rename_rem(action: action_t, glob: *const c_char) -> c_int {
1944    // Convert action_t enum to corresponding action string.
1945    let action = match Action::try_from(action) {
1946        Ok(action) => action,
1947        Err(_) => return -EINVAL,
1948    };
1949
1950    // Call magic function with rem operator.
1951    esyd(&format!("{action}/rename"), glob, b'^')
1952}
1953
1954/// Adds to the given actionlist of symlink sandboxing.
1955///
1956/// Returns 0 on success, negated errno on failure.
1957#[no_mangle]
1958pub extern "C" fn syd_symlink_add(action: action_t, glob: *const c_char) -> c_int {
1959    // Convert action_t enum to corresponding action string.
1960    let action = match Action::try_from(action) {
1961        Ok(action) => action,
1962        Err(_) => return -EINVAL,
1963    };
1964
1965    // Call magic function with add operator.
1966    esyd(&format!("{action}/symlink"), glob, b'+')
1967}
1968
1969/// Removes the first instance from the end of the given actionlist of
1970/// symlink sandboxing.
1971///
1972/// Returns 0 on success, negated errno on failure.
1973#[no_mangle]
1974pub extern "C" fn syd_symlink_del(action: action_t, glob: *const c_char) -> c_int {
1975    // Convert action_t enum to corresponding action string.
1976    let action = match Action::try_from(action) {
1977        Ok(action) => action,
1978        Err(_) => return -EINVAL,
1979    };
1980
1981    // Call magic function with del operator.
1982    esyd(&format!("{action}/symlink"), glob, b'-')
1983}
1984
1985/// Removes all matching patterns from the given actionlist of symlink sandboxing.
1986///
1987/// Returns 0 on success, negated errno on failure.
1988#[no_mangle]
1989pub extern "C" fn syd_symlink_rem(action: action_t, glob: *const c_char) -> c_int {
1990    // Convert action_t enum to corresponding action string.
1991    let action = match Action::try_from(action) {
1992        Ok(action) => action,
1993        Err(_) => return -EINVAL,
1994    };
1995
1996    // Call magic function with rem operator.
1997    esyd(&format!("{action}/symlink"), glob, b'^')
1998}
1999
2000/// Adds to the given actionlist of truncate sandboxing.
2001///
2002/// Returns 0 on success, negated errno on failure.
2003#[no_mangle]
2004pub extern "C" fn syd_truncate_add(action: action_t, glob: *const c_char) -> c_int {
2005    // Convert action_t enum to corresponding action string.
2006    let action = match Action::try_from(action) {
2007        Ok(action) => action,
2008        Err(_) => return -EINVAL,
2009    };
2010
2011    // Call magic function with add operator.
2012    esyd(&format!("{action}/truncate"), glob, b'+')
2013}
2014
2015/// Removes the first instance from the end of the given actionlist of
2016/// truncate sandboxing.
2017///
2018/// Returns 0 on success, negated errno on failure.
2019#[no_mangle]
2020pub extern "C" fn syd_truncate_del(action: action_t, glob: *const c_char) -> c_int {
2021    // Convert action_t enum to corresponding action string.
2022    let action = match Action::try_from(action) {
2023        Ok(action) => action,
2024        Err(_) => return -EINVAL,
2025    };
2026
2027    // Call magic function with del operator.
2028    esyd(&format!("{action}/truncate"), glob, b'-')
2029}
2030
2031/// Removes all matching patterns from the given actionlist of truncate sandboxing.
2032///
2033/// Returns 0 on success, negated errno on failure.
2034#[no_mangle]
2035pub extern "C" fn syd_truncate_rem(action: action_t, glob: *const c_char) -> c_int {
2036    // Convert action_t enum to corresponding action string.
2037    let action = match Action::try_from(action) {
2038        Ok(action) => action,
2039        Err(_) => return -EINVAL,
2040    };
2041
2042    // Call magic function with rem operator.
2043    esyd(&format!("{action}/truncate"), glob, b'^')
2044}
2045
2046/// Adds to the given actionlist of chdir sandboxing.
2047///
2048/// Returns 0 on success, negated errno on failure.
2049#[no_mangle]
2050pub extern "C" fn syd_chdir_add(action: action_t, glob: *const c_char) -> c_int {
2051    // Convert action_t enum to corresponding action string.
2052    let action = match Action::try_from(action) {
2053        Ok(action) => action,
2054        Err(_) => return -EINVAL,
2055    };
2056
2057    // Call magic function with add operator.
2058    esyd(&format!("{action}/chdir"), glob, b'+')
2059}
2060
2061/// Removes the first instance from the end of the given actionlist of
2062/// chdir sandboxing.
2063///
2064/// Returns 0 on success, negated errno on failure.
2065#[no_mangle]
2066pub extern "C" fn syd_chdir_del(action: action_t, glob: *const c_char) -> c_int {
2067    // Convert action_t enum to corresponding action string.
2068    let action = match Action::try_from(action) {
2069        Ok(action) => action,
2070        Err(_) => return -EINVAL,
2071    };
2072
2073    // Call magic function with del operator.
2074    esyd(&format!("{action}/chdir"), glob, b'-')
2075}
2076
2077/// Removes all matching patterns from the given actionlist of chdir sandboxing.
2078///
2079/// Returns 0 on success, negated errno on failure.
2080#[no_mangle]
2081pub extern "C" fn syd_chdir_rem(action: action_t, glob: *const c_char) -> c_int {
2082    // Convert action_t enum to corresponding action string.
2083    let action = match Action::try_from(action) {
2084        Ok(action) => action,
2085        Err(_) => return -EINVAL,
2086    };
2087
2088    // Call magic function with rem operator.
2089    esyd(&format!("{action}/chdir"), glob, b'^')
2090}
2091
2092/// Adds to the given actionlist of readdir sandboxing.
2093///
2094/// Returns 0 on success, negated errno on failure.
2095#[no_mangle]
2096pub extern "C" fn syd_readdir_add(action: action_t, glob: *const c_char) -> c_int {
2097    // Convert action_t enum to corresponding action string.
2098    let action = match Action::try_from(action) {
2099        Ok(action) => action,
2100        Err(_) => return -EINVAL,
2101    };
2102
2103    // Call magic function with add operator.
2104    esyd(&format!("{action}/readdir"), glob, b'+')
2105}
2106
2107/// Removes the first instance from the end of the given actionlist of
2108/// readdir sandboxing.
2109///
2110/// Returns 0 on success, negated errno on failure.
2111#[no_mangle]
2112pub extern "C" fn syd_readdir_del(action: action_t, glob: *const c_char) -> c_int {
2113    // Convert action_t enum to corresponding action string.
2114    let action = match Action::try_from(action) {
2115        Ok(action) => action,
2116        Err(_) => return -EINVAL,
2117    };
2118
2119    // Call magic function with del operator.
2120    esyd(&format!("{action}/readdir"), glob, b'-')
2121}
2122
2123/// Removes all matching patterns from the given actionlist of readdir sandboxing.
2124///
2125/// Returns 0 on success, negated errno on failure.
2126#[no_mangle]
2127pub extern "C" fn syd_readdir_rem(action: action_t, glob: *const c_char) -> c_int {
2128    // Convert action_t enum to corresponding action string.
2129    let action = match Action::try_from(action) {
2130        Ok(action) => action,
2131        Err(_) => return -EINVAL,
2132    };
2133
2134    // Call magic function with del operator.
2135    esyd(&format!("{action}/readdir"), glob, b'^')
2136}
2137
2138/// Adds to the given actionlist of mkdir sandboxing.
2139///
2140/// Returns 0 on success, negated errno on failure.
2141#[no_mangle]
2142pub extern "C" fn syd_mkdir_add(action: action_t, glob: *const c_char) -> c_int {
2143    // Convert action_t enum to corresponding action string.
2144    let action = match Action::try_from(action) {
2145        Ok(action) => action,
2146        Err(_) => return -EINVAL,
2147    };
2148
2149    // Call magic function with add operator.
2150    esyd(&format!("{action}/mkdir"), glob, b'+')
2151}
2152
2153/// Removes the first instance from the end of the given actionlist of
2154/// mkdir sandboxing.
2155///
2156/// Returns 0 on success, negated errno on failure.
2157#[no_mangle]
2158pub extern "C" fn syd_mkdir_del(action: action_t, glob: *const c_char) -> c_int {
2159    // Convert action_t enum to corresponding action string.
2160    let action = match Action::try_from(action) {
2161        Ok(action) => action,
2162        Err(_) => return -EINVAL,
2163    };
2164
2165    // Call magic function with del operator.
2166    esyd(&format!("{action}/mkdir"), glob, b'-')
2167}
2168
2169/// Removes all matching patterns from the given actionlist of mkdir sandboxing.
2170///
2171/// Returns 0 on success, negated errno on failure.
2172#[no_mangle]
2173pub extern "C" fn syd_mkdir_rem(action: action_t, glob: *const c_char) -> c_int {
2174    // Convert action_t enum to corresponding action string.
2175    let action = match Action::try_from(action) {
2176        Ok(action) => action,
2177        Err(_) => return -EINVAL,
2178    };
2179
2180    // Call magic function with del operator.
2181    esyd(&format!("{action}/mkdir"), glob, b'^')
2182}
2183
2184/// Adds to the given actionlist of rmdir sandboxing.
2185///
2186/// Returns 0 on success, negated errno on failure.
2187#[no_mangle]
2188pub extern "C" fn syd_rmdir_add(action: action_t, glob: *const c_char) -> c_int {
2189    // Convert action_t enum to corresponding action string.
2190    let action = match Action::try_from(action) {
2191        Ok(action) => action,
2192        Err(_) => return -EINVAL,
2193    };
2194
2195    // Call magic function with add operator.
2196    esyd(&format!("{action}/rmdir"), glob, b'+')
2197}
2198
2199/// Removes the first instance from the end of the given actionlist of
2200/// rmdir sandboxing.
2201///
2202/// Returns 0 on success, negated errno on failure.
2203#[no_mangle]
2204pub extern "C" fn syd_rmdir_del(action: action_t, glob: *const c_char) -> c_int {
2205    // Convert action_t enum to corresponding action string.
2206    let action = match Action::try_from(action) {
2207        Ok(action) => action,
2208        Err(_) => return -EINVAL,
2209    };
2210
2211    // Call magic function with del operator.
2212    esyd(&format!("{action}/rmdir"), glob, b'-')
2213}
2214
2215/// Removes all matching patterns from the given actionlist of rmdir sandboxing.
2216///
2217/// Returns 0 on success, negated errno on failure.
2218#[no_mangle]
2219pub extern "C" fn syd_rmdir_rem(action: action_t, glob: *const c_char) -> c_int {
2220    // Convert action_t enum to corresponding action string.
2221    let action = match Action::try_from(action) {
2222        Ok(action) => action,
2223        Err(_) => return -EINVAL,
2224    };
2225
2226    // Call magic function with del operator.
2227    esyd(&format!("{action}/rmdir"), glob, b'^')
2228}
2229
2230/// Adds to the given actionlist of chown sandboxing.
2231///
2232/// Returns 0 on success, negated errno on failure.
2233#[no_mangle]
2234pub extern "C" fn syd_chown_add(action: action_t, glob: *const c_char) -> c_int {
2235    // Convert action_t enum to corresponding action string.
2236    let action = match Action::try_from(action) {
2237        Ok(action) => action,
2238        Err(_) => return -EINVAL,
2239    };
2240
2241    // Call magic function with add operator.
2242    esyd(&format!("{action}/chown"), glob, b'+')
2243}
2244
2245/// Removes the first instance from the end of the given actionlist of
2246/// chown sandboxing.
2247///
2248/// Returns 0 on success, negated errno on failure.
2249#[no_mangle]
2250pub extern "C" fn syd_chown_del(action: action_t, glob: *const c_char) -> c_int {
2251    // Convert action_t enum to corresponding action string.
2252    let action = match Action::try_from(action) {
2253        Ok(action) => action,
2254        Err(_) => return -EINVAL,
2255    };
2256
2257    // Call magic function with del operator.
2258    esyd(&format!("{action}/chown"), glob, b'-')
2259}
2260
2261/// Removes all matching patterns from the given actionlist of chown sandboxing.
2262///
2263/// Returns 0 on success, negated errno on failure.
2264#[no_mangle]
2265pub extern "C" fn syd_chown_rem(action: action_t, glob: *const c_char) -> c_int {
2266    // Convert action_t enum to corresponding action string.
2267    let action = match Action::try_from(action) {
2268        Ok(action) => action,
2269        Err(_) => return -EINVAL,
2270    };
2271
2272    // Call magic function with rem operator.
2273    esyd(&format!("{action}/chown"), glob, b'^')
2274}
2275
2276/// Adds to the given actionlist of chgrp sandboxing.
2277///
2278/// Returns 0 on success, negated errno on failure.
2279#[no_mangle]
2280pub extern "C" fn syd_chgrp_add(action: action_t, glob: *const c_char) -> c_int {
2281    // Convert action_t enum to corresponding action string.
2282    let action = match Action::try_from(action) {
2283        Ok(action) => action,
2284        Err(_) => return -EINVAL,
2285    };
2286
2287    // Call magic function with add operator.
2288    esyd(&format!("{action}/chgrp"), glob, b'+')
2289}
2290
2291/// Removes the first instance from the end of the given actionlist of
2292/// chgrp sandboxing.
2293///
2294/// Returns 0 on success, negated errno on failure.
2295#[no_mangle]
2296pub extern "C" fn syd_chgrp_del(action: action_t, glob: *const c_char) -> c_int {
2297    // Convert action_t enum to corresponding action string.
2298    let action = match Action::try_from(action) {
2299        Ok(action) => action,
2300        Err(_) => return -EINVAL,
2301    };
2302
2303    // Call magic function with del operator.
2304    esyd(&format!("{action}/chgrp"), glob, b'-')
2305}
2306
2307/// Removes all matching patterns from the given actionlist of chgrp sandboxing.
2308///
2309/// Returns 0 on success, negated errno on failure.
2310#[no_mangle]
2311pub extern "C" fn syd_chgrp_rem(action: action_t, glob: *const c_char) -> c_int {
2312    // Convert action_t enum to corresponding action string.
2313    let action = match Action::try_from(action) {
2314        Ok(action) => action,
2315        Err(_) => return -EINVAL,
2316    };
2317
2318    // Call magic function with rem operator.
2319    esyd(&format!("{action}/chgrp"), glob, b'^')
2320}
2321
2322/// Adds to the given actionlist of chmod sandboxing.
2323///
2324/// Returns 0 on success, negated errno on failure.
2325#[no_mangle]
2326pub extern "C" fn syd_chmod_add(action: action_t, glob: *const c_char) -> c_int {
2327    // Convert action_t enum to corresponding action string.
2328    let action = match Action::try_from(action) {
2329        Ok(action) => action,
2330        Err(_) => return -EINVAL,
2331    };
2332
2333    // Call magic function with add operator.
2334    esyd(&format!("{action}/chmod"), glob, b'+')
2335}
2336
2337/// Removes the first instance from the end of the given actionlist of
2338/// chmod sandboxing.
2339///
2340/// Returns 0 on success, negated errno on failure.
2341#[no_mangle]
2342pub extern "C" fn syd_chmod_del(action: action_t, glob: *const c_char) -> c_int {
2343    // Convert action_t enum to corresponding action string.
2344    let action = match Action::try_from(action) {
2345        Ok(action) => action,
2346        Err(_) => return -EINVAL,
2347    };
2348
2349    // Call magic function with del operator.
2350    esyd(&format!("{action}/chmod"), glob, b'-')
2351}
2352
2353/// Removes all matching patterns from the given actionlist of chmod sandboxing.
2354///
2355/// Returns 0 on success, negated errno on failure.
2356#[no_mangle]
2357pub extern "C" fn syd_chmod_rem(action: action_t, glob: *const c_char) -> c_int {
2358    // Convert action_t enum to corresponding action string.
2359    let action = match Action::try_from(action) {
2360        Ok(action) => action,
2361        Err(_) => return -EINVAL,
2362    };
2363
2364    // Call magic function with rem operator.
2365    esyd(&format!("{action}/chmod"), glob, b'^')
2366}
2367
2368/// Adds to the given actionlist of chattr sandboxing.
2369///
2370/// Returns 0 on success, negated errno on failure.
2371#[no_mangle]
2372pub extern "C" fn syd_chattr_add(action: action_t, glob: *const c_char) -> c_int {
2373    // Convert action_t enum to corresponding action string.
2374    let action = match Action::try_from(action) {
2375        Ok(action) => action,
2376        Err(_) => return -EINVAL,
2377    };
2378
2379    // Call magic function with add operator.
2380    esyd(&format!("{action}/chattr"), glob, b'+')
2381}
2382
2383/// Removes the first instance from the end of the given actionlist of
2384/// chattr sandboxing.
2385///
2386/// Returns 0 on success, negated errno on failure.
2387#[no_mangle]
2388pub extern "C" fn syd_chattr_del(action: action_t, glob: *const c_char) -> c_int {
2389    // Convert action_t enum to corresponding action string.
2390    let action = match Action::try_from(action) {
2391        Ok(action) => action,
2392        Err(_) => return -EINVAL,
2393    };
2394
2395    // Call magic function with del operator.
2396    esyd(&format!("{action}/chattr"), glob, b'-')
2397}
2398
2399/// Removes all matching patterns from the given actionlist of chattr sandboxing.
2400///
2401/// Returns 0 on success, negated errno on failure.
2402#[no_mangle]
2403pub extern "C" fn syd_chattr_rem(action: action_t, glob: *const c_char) -> c_int {
2404    // Convert action_t enum to corresponding action string.
2405    let action = match Action::try_from(action) {
2406        Ok(action) => action,
2407        Err(_) => return -EINVAL,
2408    };
2409
2410    // Call magic function with rem operator.
2411    esyd(&format!("{action}/chattr"), glob, b'^')
2412}
2413
2414/// Adds to the given actionlist of chroot sandboxing.
2415///
2416/// Returns 0 on success, negated errno on failure.
2417#[no_mangle]
2418pub extern "C" fn syd_chroot_add(action: action_t, glob: *const c_char) -> c_int {
2419    // Convert action_t enum to corresponding action string.
2420    let action = match Action::try_from(action) {
2421        Ok(action) => action,
2422        Err(_) => return -EINVAL,
2423    };
2424
2425    // Call magic function with add operator.
2426    esyd(&format!("{action}/chroot"), glob, b'+')
2427}
2428
2429/// Removes the first instance from the end of the given actionlist of
2430/// chroot sandboxing.
2431///
2432/// Returns 0 on success, negated errno on failure.
2433#[no_mangle]
2434pub extern "C" fn syd_chroot_del(action: action_t, glob: *const c_char) -> c_int {
2435    // Convert action_t enum to corresponding action string.
2436    let action = match Action::try_from(action) {
2437        Ok(action) => action,
2438        Err(_) => return -EINVAL,
2439    };
2440
2441    // Call magic function with del operator.
2442    esyd(&format!("{action}/chroot"), glob, b'-')
2443}
2444
2445/// Removes all matching patterns from the given actionlist of chroot sandboxing.
2446///
2447/// Returns 0 on success, negated errno on failure.
2448#[no_mangle]
2449pub extern "C" fn syd_chroot_rem(action: action_t, glob: *const c_char) -> c_int {
2450    // Convert action_t enum to corresponding action string.
2451    let action = match Action::try_from(action) {
2452        Ok(action) => action,
2453        Err(_) => return -EINVAL,
2454    };
2455
2456    // Call magic function with rem operator.
2457    esyd(&format!("{action}/chroot"), glob, b'^')
2458}
2459
2460/// Adds to the given actionlist of utime sandboxing.
2461///
2462/// Returns 0 on success, negated errno on failure.
2463#[no_mangle]
2464pub extern "C" fn syd_utime_add(action: action_t, glob: *const c_char) -> c_int {
2465    // Convert action_t enum to corresponding action string.
2466    let action = match Action::try_from(action) {
2467        Ok(action) => action,
2468        Err(_) => return -EINVAL,
2469    };
2470
2471    // Call magic function with add operator.
2472    esyd(&format!("{action}/utime"), glob, b'+')
2473}
2474
2475/// Removes the first instance from the end of the given actionlist of
2476/// utime sandboxing.
2477///
2478/// Returns 0 on success, negated errno on failure.
2479#[no_mangle]
2480pub extern "C" fn syd_utime_del(action: action_t, glob: *const c_char) -> c_int {
2481    // Convert action_t enum to corresponding action string.
2482    let action = match Action::try_from(action) {
2483        Ok(action) => action,
2484        Err(_) => return -EINVAL,
2485    };
2486
2487    // Call magic function with del operator.
2488    esyd(&format!("{action}/utime"), glob, b'-')
2489}
2490
2491/// Removes all matching patterns from the given actionlist of utime sandboxing.
2492///
2493/// Returns 0 on success, negated errno on failure.
2494#[no_mangle]
2495pub extern "C" fn syd_utime_rem(action: action_t, glob: *const c_char) -> c_int {
2496    // Convert action_t enum to corresponding action string.
2497    let action = match Action::try_from(action) {
2498        Ok(action) => action,
2499        Err(_) => return -EINVAL,
2500    };
2501
2502    // Call magic function with rem operator.
2503    esyd(&format!("{action}/utime"), glob, b'^')
2504}
2505
2506/// Adds to the given actionlist of mkbdev sandboxing.
2507///
2508/// Returns 0 on success, negated errno on failure.
2509#[no_mangle]
2510pub extern "C" fn syd_mkbdev_add(action: action_t, glob: *const c_char) -> c_int {
2511    // Convert action_t enum to corresponding action string.
2512    let action = match Action::try_from(action) {
2513        Ok(action) => action,
2514        Err(_) => return -EINVAL,
2515    };
2516
2517    // Call magic function with add operator.
2518    esyd(&format!("{action}/mkbdev"), glob, b'+')
2519}
2520
2521/// Removes the first instance from the end of the given actionlist of
2522/// mkbdev sandboxing.
2523///
2524/// Returns 0 on success, negated errno on failure.
2525#[no_mangle]
2526pub extern "C" fn syd_mkbdev_del(action: action_t, glob: *const c_char) -> c_int {
2527    // Convert action_t enum to corresponding action string.
2528    let action = match Action::try_from(action) {
2529        Ok(action) => action,
2530        Err(_) => return -EINVAL,
2531    };
2532
2533    // Call magic function with del operator.
2534    esyd(&format!("{action}/mkbdev"), glob, b'-')
2535}
2536
2537/// Removes all matching patterns from the given actionlist of mkbdev sandboxing.
2538///
2539/// Returns 0 on success, negated errno on failure.
2540#[no_mangle]
2541pub extern "C" fn syd_mkbdev_rem(action: action_t, glob: *const c_char) -> c_int {
2542    // Convert action_t enum to corresponding action string.
2543    let action = match Action::try_from(action) {
2544        Ok(action) => action,
2545        Err(_) => return -EINVAL,
2546    };
2547
2548    // Call magic function with rem operator.
2549    esyd(&format!("{action}/mkbdev"), glob, b'^')
2550}
2551
2552/// Adds to the given actionlist of mkcdev sandboxing.
2553///
2554/// Returns 0 on success, negated errno on failure.
2555#[no_mangle]
2556pub extern "C" fn syd_mkcdev_add(action: action_t, glob: *const c_char) -> c_int {
2557    // Convert action_t enum to corresponding action string.
2558    let action = match Action::try_from(action) {
2559        Ok(action) => action,
2560        Err(_) => return -EINVAL,
2561    };
2562
2563    // Call magic function with add operator.
2564    esyd(&format!("{action}/mkcdev"), glob, b'+')
2565}
2566
2567/// Removes the first instance from the end of the given actionlist of
2568/// mkcdev sandboxing.
2569///
2570/// Returns 0 on success, negated errno on failure.
2571#[no_mangle]
2572pub extern "C" fn syd_mkcdev_del(action: action_t, glob: *const c_char) -> c_int {
2573    // Convert action_t enum to corresponding action string.
2574    let action = match Action::try_from(action) {
2575        Ok(action) => action,
2576        Err(_) => return -EINVAL,
2577    };
2578
2579    // Call magic function with del operator.
2580    esyd(&format!("{action}/mkcdev"), glob, b'-')
2581}
2582
2583/// Removes all matching patterns from the given actionlist of mkcdev sandboxing.
2584///
2585/// Returns 0 on success, negated errno on failure.
2586#[no_mangle]
2587pub extern "C" fn syd_mkcdev_rem(action: action_t, glob: *const c_char) -> c_int {
2588    // Convert action_t enum to corresponding action string.
2589    let action = match Action::try_from(action) {
2590        Ok(action) => action,
2591        Err(_) => return -EINVAL,
2592    };
2593
2594    // Call magic function with rem operator.
2595    esyd(&format!("{action}/mkcdev"), glob, b'^')
2596}
2597
2598/// Adds to the given actionlist of mkfifo sandboxing.
2599///
2600/// Returns 0 on success, negated errno on failure.
2601#[no_mangle]
2602pub extern "C" fn syd_mkfifo_add(action: action_t, glob: *const c_char) -> c_int {
2603    // Convert action_t enum to corresponding action string.
2604    let action = match Action::try_from(action) {
2605        Ok(action) => action,
2606        Err(_) => return -EINVAL,
2607    };
2608
2609    // Call magic function with add operator.
2610    esyd(&format!("{action}/mkfifo"), glob, b'+')
2611}
2612
2613/// Removes the first instance from the end of the given actionlist of
2614/// mkfifo sandboxing.
2615///
2616/// Returns 0 on success, negated errno on failure.
2617#[no_mangle]
2618pub extern "C" fn syd_mkfifo_del(action: action_t, glob: *const c_char) -> c_int {
2619    // Convert action_t enum to corresponding action string.
2620    let action = match Action::try_from(action) {
2621        Ok(action) => action,
2622        Err(_) => return -EINVAL,
2623    };
2624
2625    // Call magic function with del operator.
2626    esyd(&format!("{action}/mkfifo"), glob, b'-')
2627}
2628
2629/// Removes all matching patterns from the given actionlist of mkfifo sandboxing.
2630///
2631/// Returns 0 on success, negated errno on failure.
2632#[no_mangle]
2633pub extern "C" fn syd_mkfifo_rem(action: action_t, glob: *const c_char) -> c_int {
2634    // Convert action_t enum to corresponding action string.
2635    let action = match Action::try_from(action) {
2636        Ok(action) => action,
2637        Err(_) => return -EINVAL,
2638    };
2639
2640    // Call magic function with rem operator.
2641    esyd(&format!("{action}/mkfifo"), glob, b'^')
2642}
2643
2644/// Adds to the given actionlist of mktemp sandboxing.
2645///
2646/// Returns 0 on success, negated errno on failure.
2647#[no_mangle]
2648pub extern "C" fn syd_mktemp_add(action: action_t, glob: *const c_char) -> c_int {
2649    // Convert action_t enum to corresponding action string.
2650    let action = match Action::try_from(action) {
2651        Ok(action) => action,
2652        Err(_) => return -EINVAL,
2653    };
2654
2655    // Call magic function with add operator.
2656    esyd(&format!("{action}/mktemp"), glob, b'+')
2657}
2658
2659/// Removes the first instance from the end of the given actionlist of
2660/// mktemp sandboxing.
2661///
2662/// Returns 0 on success, negated errno on failure.
2663#[no_mangle]
2664pub extern "C" fn syd_mktemp_del(action: action_t, glob: *const c_char) -> c_int {
2665    // Convert action_t enum to corresponding action string.
2666    let action = match Action::try_from(action) {
2667        Ok(action) => action,
2668        Err(_) => return -EINVAL,
2669    };
2670
2671    // Call magic function with del operator.
2672    esyd(&format!("{action}/mktemp"), glob, b'-')
2673}
2674
2675/// Removes all matching patterns from the given actionlist of mktemp sandboxing.
2676///
2677/// Returns 0 on success, negated errno on failure.
2678#[no_mangle]
2679pub extern "C" fn syd_mktemp_rem(action: action_t, glob: *const c_char) -> c_int {
2680    // Convert action_t enum to corresponding action string.
2681    let action = match Action::try_from(action) {
2682        Ok(action) => action,
2683        Err(_) => return -EINVAL,
2684    };
2685
2686    // Call magic function with rem operator.
2687    esyd(&format!("{action}/mktemp"), glob, b'^')
2688}
2689
2690/// Adds to the given actionlist of net/bind sandboxing.
2691///
2692/// Returns 0 on success, negated errno on failure.
2693#[no_mangle]
2694pub extern "C" fn syd_net_bind_add(action: action_t, glob: *const c_char) -> c_int {
2695    // Convert action_t enum to corresponding action string.
2696    let action = match Action::try_from(action) {
2697        Ok(action) => action,
2698        Err(_) => return -EINVAL,
2699    };
2700
2701    // Call magic function with add operator.
2702    esyd(&format!("{action}/net/bind"), glob, b'+')
2703}
2704
2705/// Removes the first instance from the end of the given actionlist of
2706/// net/bind sandboxing.
2707///
2708/// Returns 0 on success, negated errno on failure.
2709#[no_mangle]
2710pub extern "C" fn syd_net_bind_del(action: action_t, glob: *const c_char) -> c_int {
2711    // Convert action_t enum to corresponding action string.
2712    let action = match Action::try_from(action) {
2713        Ok(action) => action,
2714        Err(_) => return -EINVAL,
2715    };
2716
2717    // Call magic function with del operator.
2718    esyd(&format!("{action}/net/bind"), glob, b'-')
2719}
2720
2721/// Removes all matching patterns from the given actionlist of net/bind sandboxing.
2722///
2723/// Returns 0 on success, negated errno on failure.
2724#[no_mangle]
2725pub extern "C" fn syd_net_bind_rem(action: action_t, glob: *const c_char) -> c_int {
2726    // Convert action_t enum to corresponding action string.
2727    let action = match Action::try_from(action) {
2728        Ok(action) => action,
2729        Err(_) => return -EINVAL,
2730    };
2731
2732    // Call magic function with rem operator.
2733    esyd(&format!("{action}/net/bind"), glob, b'^')
2734}
2735
2736/// Adds to the given actionlist of net/connect sandboxing.
2737///
2738/// Returns 0 on success, negated errno on failure.
2739#[no_mangle]
2740pub extern "C" fn syd_net_connect_add(action: action_t, glob: *const c_char) -> c_int {
2741    // Convert action_t enum to corresponding action string.
2742    let action = match Action::try_from(action) {
2743        Ok(action) => action,
2744        Err(_) => return -EINVAL,
2745    };
2746
2747    // Call magic function with add operator.
2748    esyd(&format!("{action}/net/connect"), glob, b'+')
2749}
2750
2751/// Removes the first instance from the end of the given actionlist of
2752/// net/connect sandboxing.
2753///
2754/// Returns 0 on success, negated errno on failure.
2755#[no_mangle]
2756pub extern "C" fn syd_net_connect_del(action: action_t, glob: *const c_char) -> c_int {
2757    // Convert action_t enum to corresponding action string.
2758    let action = match Action::try_from(action) {
2759        Ok(action) => action,
2760        Err(_) => return -EINVAL,
2761    };
2762
2763    // Call magic function with del operator.
2764    esyd(&format!("{action}/net/connect"), glob, b'-')
2765}
2766
2767/// Removes all matching patterns from the given actionlist of net/connect sandboxing.
2768///
2769/// Returns 0 on success, negated errno on failure.
2770#[no_mangle]
2771pub extern "C" fn syd_net_connect_rem(action: action_t, glob: *const c_char) -> c_int {
2772    // Convert action_t enum to corresponding action string.
2773    let action = match Action::try_from(action) {
2774        Ok(action) => action,
2775        Err(_) => return -EINVAL,
2776    };
2777
2778    // Call magic function with rem operator.
2779    esyd(&format!("{action}/net/connect"), glob, b'^')
2780}
2781
2782/// Adds to the given actionlist of net/sendfd sandboxing.
2783///
2784/// Returns 0 on success, negated errno on failure.
2785#[no_mangle]
2786pub extern "C" fn syd_net_sendfd_add(action: action_t, glob: *const c_char) -> c_int {
2787    // Convert action_t enum to corresponding action string.
2788    let action = match Action::try_from(action) {
2789        Ok(action) => action,
2790        Err(_) => return -EINVAL,
2791    };
2792
2793    // Call magic function with add operator.
2794    esyd(&format!("{action}/net/sendfd"), glob, b'+')
2795}
2796
2797/// Removes the first instance from the end of the given actionlist of
2798/// net/sendfd sandboxing.
2799///
2800/// Returns 0 on success, negated errno on failure.
2801#[no_mangle]
2802pub extern "C" fn syd_net_sendfd_del(action: action_t, glob: *const c_char) -> c_int {
2803    // Convert action_t enum to corresponding action string.
2804    let action = match Action::try_from(action) {
2805        Ok(action) => action,
2806        Err(_) => return -EINVAL,
2807    };
2808
2809    // Call magic function with del operator.
2810    esyd(&format!("{action}/net/sendfd"), glob, b'-')
2811}
2812
2813/// Removes all matching patterns from the given actionlist of net/sendfd sandboxing.
2814///
2815/// Returns 0 on success, negated errno on failure.
2816#[no_mangle]
2817pub extern "C" fn syd_net_sendfd_rem(action: action_t, glob: *const c_char) -> c_int {
2818    // Convert action_t enum to corresponding action string.
2819    let action = match Action::try_from(action) {
2820        Ok(action) => action,
2821        Err(_) => return -EINVAL,
2822    };
2823
2824    // Call magic function with rem operator.
2825    esyd(&format!("{action}/net/sendfd"), glob, b'^')
2826}
2827
2828/// Adds to the given actionlist of net/link sandboxing.
2829///
2830/// Returns 0 on success, negated errno on failure.
2831#[no_mangle]
2832pub extern "C" fn syd_net_link_add(action: action_t, family: *const c_char) -> c_int {
2833    // Convert action_t enum to corresponding action string.
2834    let action = match Action::try_from(action) {
2835        Ok(action) => action,
2836        Err(_) => return -EINVAL,
2837    };
2838
2839    // Call magic function with add operator.
2840    esyd(&format!("{action}/net/link"), family, b'+')
2841}
2842
2843/// Removes the first instance from the end of the given actionlist of
2844/// net/link sandboxing.
2845///
2846/// Returns 0 on success, negated errno on failure.
2847#[no_mangle]
2848pub extern "C" fn syd_net_link_del(action: action_t, family: *const c_char) -> c_int {
2849    // Convert action_t enum to corresponding action string.
2850    let action = match Action::try_from(action) {
2851        Ok(action) => action,
2852        Err(_) => return -EINVAL,
2853    };
2854
2855    // Call magic function with del operator.
2856    esyd(&format!("{action}/net/link"), family, b'-')
2857}
2858
2859/// Removes all matching patterns from the given actionlist of net/link sandboxing.
2860///
2861/// Returns 0 on success, negated errno on failure.
2862#[no_mangle]
2863pub extern "C" fn syd_net_link_rem(action: action_t, family: *const c_char) -> c_int {
2864    // Convert action_t enum to corresponding action string.
2865    let action = match Action::try_from(action) {
2866        Ok(action) => action,
2867        Err(_) => return -EINVAL,
2868    };
2869
2870    // Call magic function with rem operator.
2871    esyd(&format!("{action}/net/link"), family, b'^')
2872}
2873
2874/// Set syd maximum per-process memory usage limit for memory sandboxing.
2875///
2876/// parse-size crate is used to parse the value so formatted strings are OK.
2877///
2878/// Returns 0 on success, negated errno on failure.
2879#[no_mangle]
2880pub extern "C" fn syd_mem_max(size: *const c_char) -> c_int {
2881    esyd("mem/max", size, b':')
2882}
2883
2884/// Set syd maximum per-process virtual memory usage limit for memory sandboxing.
2885///
2886/// parse-size crate is used to parse the value so formatted strings are OK.
2887///
2888/// Returns 0 on success, negated errno on failure.
2889#[no_mangle]
2890pub extern "C" fn syd_mem_vm_max(size: *const c_char) -> c_int {
2891    esyd("mem/vm_max", size, b':')
2892}
2893
2894/// Set syd maximum process id limit for PID sandboxing
2895///
2896/// Returns 0 on success, negated errno on failure.
2897#[no_mangle]
2898pub extern "C" fn syd_pid_max(size: usize) -> c_int {
2899    stat(&format!("/dev/syd/pid/max:{size}"))
2900}
2901
2902/// Specify SegvGuard entry expiry timeout in seconds.
2903/// Setting this timeout to 0 effectively disables SegvGuard.
2904///
2905/// Returns 0 on success, negated errno on failure.
2906#[no_mangle]
2907pub extern "C" fn syd_segvguard_expiry(timeout: u64) -> c_int {
2908    stat(&format!("/dev/syd/segvguard/expiry:{timeout}"))
2909}
2910
2911/// Specify SegvGuard entry suspension timeout in seconds.
2912///
2913/// Returns 0 on success, negated errno on failure.
2914#[no_mangle]
2915pub extern "C" fn syd_segvguard_suspension(timeout: u64) -> c_int {
2916    stat(&format!("/dev/syd/segvguard/suspension:{timeout}"))
2917}
2918
2919/// Specify SegvGuard max number of crashes before suspension.
2920///
2921/// Returns 0 on success, negated errno on failure.
2922#[no_mangle]
2923pub extern "C" fn syd_segvguard_maxcrashes(max: u8) -> c_int {
2924    stat(&format!("/dev/syd/segvguard/maxcrashes:{max}"))
2925}
2926
2927/// Execute a command outside the sandbox without sandboxing
2928///
2929/// # Safety
2930///
2931/// This function is marked `unsafe` because it dereferences raw
2932/// pointers, which is inherently unsafe in Rust.
2933///
2934/// The caller must ensure the following conditions are met to safely
2935/// use this function:
2936///
2937/// 1. The `file` pointer must point to a valid, null-terminated C-style
2938///    string.
2939///
2940/// 2. The `argv` pointer must point to an array of pointers, where each
2941///    pointer refers to a valid, null-terminated C-style string. The
2942///    last pointer in the array must be null, indicating the end of the
2943///    array.
2944///
2945/// 3. The memory pointed to by `file` and `argv` must remain valid for
2946///    the duration of the call.
2947///
2948/// Failing to uphold these guarantees can lead to undefined behavior,
2949/// including memory corruption and data races.
2950///
2951/// Returns 0 on success, negated errno on failure.
2952#[no_mangle]
2953pub unsafe extern "C" fn syd_exec(file: *const c_char, argv: *const *const c_char) -> c_int {
2954    if file.is_null() || argv.is_null() {
2955        return -EFAULT;
2956    }
2957
2958    // SAFETY: Trust that `file` is a null-terminated string.
2959    let file = CStr::from_ptr(file);
2960    let file = OsStr::from_bytes(file.to_bytes());
2961
2962    let mut path = OsString::from("/dev/syd/cmd/exec!");
2963    path.push(file);
2964
2965    let mut idx: isize = 0;
2966    while !(*argv.offset(idx)).is_null() {
2967        // SAFETY: Trust that each `argv` element is a null-terminated string.
2968        let arg = CStr::from_ptr(*argv.offset(idx));
2969        let arg = OsStr::from_bytes(arg.to_bytes());
2970
2971        path.push(OsStr::from_bytes(&[b'\x1F'])); // ASCII Unit Separator
2972        path.push(arg);
2973
2974        idx = idx.saturating_add(1);
2975    }
2976
2977    let path = PathBuf::from(path);
2978    stat(path)
2979}