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