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