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