1use super::raw;
3use crate::get_architecture;
4use nix::libc::free;
5use std::{
6 error,
7 ffi::{CStr, CString, c_int, c_void},
8 fmt,
9};
10
11#[derive(Debug)]
13pub enum Error {
14 Name(String),
15 Code(c_int),
16}
17impl fmt::Display for Error {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 match self {
20 Error::Name(name) => write!(f, "Failed to resolve syscall name: {name}"),
21 Error::Code(code) => write!(f, "Failed to resolve syscall name: {code}"),
22 }
23 }
24}
25impl error::Error for Error {}
26
27#[derive(Debug, Copy, Clone)]
29pub struct Syscall {
30 code: c_int,
32}
33impl Syscall {
34 pub fn from_number(code: c_int) -> Self {
36 Self { code }
37 }
38
39 pub fn from_name(name: &str) -> Result<Self, Error> {
41 if let Ok(c_name) = CString::new(name) {
42 match unsafe { raw::seccomp_syscall_resolve_name(c_name.as_ptr()) } {
43 -1 => Err(Error::Name(name.to_string())),
44 code => Ok(Self { code }),
45 }
46 } else {
47 Err(Error::Name(name.to_string()))
48 }
49 }
50
51 pub fn with_arch(name: &str, arch: u32) -> Result<Self, Error> {
54 if let Ok(c_name) = CString::new(name) {
55 match unsafe { raw::seccomp_syscall_resolve_name_arch(arch, c_name.as_ptr()) } {
56 -1 => Err(Error::Name(name.to_string())),
57 code => Ok(Self { code }),
58 }
59 } else {
60 Err(Error::Name(name.to_string()))
61 }
62 }
63
64 pub fn get_name(num: c_int) -> Result<String, Error> {
66 Self::get_name_arch(num, get_architecture())
67 }
68
69 pub fn get_name_arch(num: c_int, arch: u32) -> Result<String, Error> {
71 let name = unsafe { raw::seccomp_syscall_resolve_num_arch(arch, num) };
72
73 if name.is_null() {
74 Err(Error::Code(num))
75 } else {
76 let syscall_name = unsafe {
77 let c_str = CStr::from_ptr(name);
78 if let Ok(result) = c_str.to_str() {
79 let result = result.to_owned();
80 free(name as *mut c_void);
81 result
82 } else {
83 return Err(Error::Code(num));
84 }
85 };
86 Ok(syscall_name)
87 }
88 }
89
90 pub fn get_number(&self) -> i32 {
92 self.code
93 }
94}
95impl From<Syscall> for c_int {
96 fn from(syscall: Syscall) -> c_int {
97 syscall.code
98 }
99}
100impl fmt::Display for Syscall {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 write!(f, "{}", self.code)
103 }
104}