rawsys_linux/
args.rs

1//! `SyscallArgs`: lightweight packing of syscall parameters
2//!
3//! This module provides the plain container `SyscallArgs` and a helper macro
4//! `syscall_args!` for collecting up to six raw syscall arguments. It is useful
5//! when you want to prepare arguments programmatically and call the generic
6//! `syscall(nr, &SyscallArgs)` wrapper.
7//!
8//! Notes
9//! - Kept intentionally untyped: the kernel ABI is in terms of machine words;
10//!   `SyscallArgs` mirrors that to avoid accidental conversions or allocations.
11//! - `no_std` friendly by design; no dependency on `std::io::Error`.
12//!
13//! Example
14//! ```no_run
15//! use rawsys_linux::{Sysno, SyscallArgs, syscall};
16//!
17//! let args = SyscallArgs::from(&[1, b"hi\n".as_ptr() as _, 3]);
18//! let _ = unsafe { syscall(Sysno::write, &args) };
19//! ```
20
21use crate::SyscallWord;
22
23/// The 6 arguments of a syscall, raw untyped version.
24#[derive(PartialEq, Debug, Eq, Clone, Copy)]
25#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
26pub struct SyscallArgs {
27    pub arg0: SyscallWord,
28    pub arg1: SyscallWord,
29    pub arg2: SyscallWord,
30    pub arg3: SyscallWord,
31    pub arg4: SyscallWord,
32    pub arg5: SyscallWord,
33}
34
35impl SyscallArgs {
36    pub fn new(
37        a0: SyscallWord,
38        a1: SyscallWord,
39        a2: SyscallWord,
40        a3: SyscallWord,
41        a4: SyscallWord,
42        a5: SyscallWord,
43    ) -> Self {
44        SyscallArgs {
45            arg0: a0,
46            arg1: a1,
47            arg2: a2,
48            arg3: a3,
49            arg4: a4,
50            arg5: a5,
51        }
52    }
53}
54
55impl From<&[SyscallWord; 6]> for SyscallArgs {
56    fn from(args: &[SyscallWord; 6]) -> Self {
57        SyscallArgs {
58            arg0: args[0],
59            arg1: args[1],
60            arg2: args[2],
61            arg3: args[3],
62            arg4: args[4],
63            arg5: args[5],
64        }
65    }
66}
67
68impl From<&[SyscallWord; 5]> for SyscallArgs {
69    fn from(args: &[SyscallWord; 5]) -> Self {
70        SyscallArgs {
71            arg0: args[0],
72            arg1: args[1],
73            arg2: args[2],
74            arg3: args[3],
75            arg4: args[4],
76            arg5: 0,
77        }
78    }
79}
80
81impl From<&[SyscallWord; 4]> for SyscallArgs {
82    fn from(args: &[SyscallWord; 4]) -> Self {
83        SyscallArgs {
84            arg0: args[0],
85            arg1: args[1],
86            arg2: args[2],
87            arg3: args[3],
88            arg4: 0,
89            arg5: 0,
90        }
91    }
92}
93
94impl From<&[SyscallWord; 3]> for SyscallArgs {
95    fn from(args: &[SyscallWord; 3]) -> Self {
96        SyscallArgs {
97            arg0: args[0],
98            arg1: args[1],
99            arg2: args[2],
100            arg3: 0,
101            arg4: 0,
102            arg5: 0,
103        }
104    }
105}
106
107impl From<&[SyscallWord; 2]> for SyscallArgs {
108    fn from(args: &[SyscallWord; 2]) -> Self {
109        SyscallArgs {
110            arg0: args[0],
111            arg1: args[1],
112            arg2: 0,
113            arg3: 0,
114            arg4: 0,
115            arg5: 0,
116        }
117    }
118}
119
120impl From<&[SyscallWord; 1]> for SyscallArgs {
121    fn from(args: &[SyscallWord; 1]) -> Self {
122        SyscallArgs {
123            arg0: args[0],
124            arg1: 0,
125            arg2: 0,
126            arg3: 0,
127            arg4: 0,
128            arg5: 0,
129        }
130    }
131}
132
133impl From<&[SyscallWord; 0]> for SyscallArgs {
134    fn from(_args: &[SyscallWord; 0]) -> Self {
135        SyscallArgs {
136            arg0: 0,
137            arg1: 0,
138            arg2: 0,
139            arg3: 0,
140            arg4: 0,
141            arg5: 0,
142        }
143    }
144}
145
146#[macro_export]
147macro_rules! syscall_args {
148    ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr, $f:expr) => {
149        $crate::SyscallArgs::new($a, $b, $c, $d, $e, $f)
150    };
151    ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr) => {
152        $crate::SyscallArgs::new($a, $b, $c, $d, $e, 0)
153    };
154    ($a:expr, $b:expr, $c:expr, $d:expr) => {
155        $crate::SyscallArgs::new($a, $b, $c, $d, 0, 0)
156    };
157    ($a:expr, $b:expr, $c:expr) => {
158        $crate::SyscallArgs::new($a, $b, $c, 0, 0, 0)
159    };
160    ($a:expr, $b:expr) => {
161        $crate::SyscallArgs::new($a, $b, 0, 0, 0, 0)
162    };
163    ($a:expr) => {
164        $crate::SyscallArgs::new($a, 0, 0, 0, 0, 0)
165    };
166    () => {
167        $crate::SyscallArgs::new(0, 0, 0, 0, 0, 0)
168    };
169}
170
171#[cfg(test)]
172mod tests {
173    use super::*;
174
175    #[test]
176    fn syscall_args_macro_test() {
177        assert_eq!(
178            syscall_args!(1, 2, 3, 4, 5, 6),
179            SyscallArgs::new(1, 2, 3, 4, 5, 6)
180        );
181        assert_eq!(
182            syscall_args!(1, 2, 3, 4, 5),
183            SyscallArgs::new(1, 2, 3, 4, 5, 0)
184        );
185        assert_eq!(
186            syscall_args!(1, 2, 3, 4),
187            SyscallArgs::new(1, 2, 3, 4, 0, 0)
188        );
189        assert_eq!(syscall_args!(1, 2, 3), SyscallArgs::new(1, 2, 3, 0, 0, 0));
190        assert_eq!(syscall_args!(1, 2), SyscallArgs::new(1, 2, 0, 0, 0, 0));
191        assert_eq!(syscall_args!(1), SyscallArgs::new(1, 0, 0, 0, 0, 0));
192        assert_eq!(syscall_args!(), SyscallArgs::new(0, 0, 0, 0, 0, 0));
193    }
194
195    #[test]
196    fn syscall_args_from_u64_slice() {
197        assert_eq!(
198            SyscallArgs::from(&[1, 2, 3, 4, 5, 6]),
199            syscall_args!(1, 2, 3, 4, 5, 6)
200        );
201        assert_eq!(
202            SyscallArgs::from(&[1, 2, 3, 4, 5]),
203            syscall_args!(1, 2, 3, 4, 5)
204        );
205        assert_eq!(SyscallArgs::from(&[1, 2, 3, 4]), syscall_args!(1, 2, 3, 4));
206        assert_eq!(SyscallArgs::from(&[1, 2, 3]), syscall_args!(1, 2, 3));
207        assert_eq!(SyscallArgs::from(&[1, 2]), syscall_args!(1, 2));
208        assert_eq!(SyscallArgs::from(&[1]), syscall_args!(1));
209        assert_eq!(SyscallArgs::from(&[0]), syscall_args!());
210    }
211}