1 //! Convert values to [`ArgReg`] and from [`RetReg`].
2 //!
3 //! System call arguments and return values are all communicated with inline
4 //! asm and FFI as `*mut Opaque`. To protect these raw pointers from escaping
5 //! or being accidentally misused as they travel through the code, we wrap them
6 //! in [`ArgReg`] and [`RetReg`] structs. This file provides `From`
7 //! implementations and explicit conversion functions for converting values
8 //! into and out of these wrapper structs.
9 //!
10 //! # Safety
11 //!
12 //! Some of this code is `unsafe` in order to work with raw file descriptors,
13 //! and some is `unsafe` to interpret the values in a `RetReg`.
14 #![allow(unsafe_code)]
15 
16 use super::c;
17 use super::fd::{AsRawFd, BorrowedFd, FromRawFd, RawFd};
18 #[cfg(any(feature = "event", feature = "runtime"))]
19 use super::io::errno::try_decode_error;
20 #[cfg(target_pointer_width = "64")]
21 use super::io::errno::try_decode_u64;
22 #[cfg(not(debug_assertions))]
23 use super::io::errno::{
24     decode_c_int_infallible, decode_c_uint_infallible, decode_usize_infallible,
25 };
26 use super::io::errno::{
27     try_decode_c_int, try_decode_c_uint, try_decode_raw_fd, try_decode_usize, try_decode_void,
28     try_decode_void_star,
29 };
30 use super::reg::{raw_arg, ArgNumber, ArgReg, RetReg, R0};
31 #[cfg(feature = "time")]
32 use super::time::types::TimerfdClockId;
33 #[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
34 use crate::clockid::ClockId;
35 use crate::fd::OwnedFd;
36 use crate::ffi::CStr;
37 use crate::io;
38 #[cfg(any(feature = "process", feature = "runtime", feature = "termios"))]
39 use crate::pid::Pid;
40 #[cfg(feature = "process")]
41 use crate::process::Resource;
42 #[cfg(any(feature = "process", feature = "runtime"))]
43 use crate::signal::Signal;
44 use crate::utils::{as_mut_ptr, as_ptr};
45 use core::mem::MaybeUninit;
46 use core::ptr::null_mut;
47 #[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
48 use linux_raw_sys::general::__kernel_clockid_t;
49 #[cfg(target_pointer_width = "64")]
50 use linux_raw_sys::general::__kernel_loff_t;
51 #[cfg(feature = "net")]
52 use linux_raw_sys::net::socklen_t;
53 
54 /// Convert `SYS_*` constants for socketcall.
55 #[cfg(target_arch = "x86")]
56 #[inline]
x86_sys<'a, Num: ArgNumber>(sys: u32) -> ArgReg<'a, Num>57 pub(super) fn x86_sys<'a, Num: ArgNumber>(sys: u32) -> ArgReg<'a, Num> {
58     pass_usize(sys as usize)
59 }
60 
61 /// Pass the "low" half of the endian-specific memory encoding of a `u64`, for
62 /// 32-bit architectures.
63 #[cfg(target_pointer_width = "32")]
64 #[inline]
lo<'a, Num: ArgNumber>(x: u64) -> ArgReg<'a, Num>65 pub(super) fn lo<'a, Num: ArgNumber>(x: u64) -> ArgReg<'a, Num> {
66     #[cfg(target_endian = "little")]
67     let x = x >> 32;
68     #[cfg(target_endian = "big")]
69     let x = x & 0xffff_ffff;
70 
71     pass_usize(x as usize)
72 }
73 
74 /// Pass the "high" half of the endian-specific memory encoding of a `u64`, for
75 /// 32-bit architectures.
76 #[cfg(target_pointer_width = "32")]
77 #[inline]
hi<'a, Num: ArgNumber>(x: u64) -> ArgReg<'a, Num>78 pub(super) fn hi<'a, Num: ArgNumber>(x: u64) -> ArgReg<'a, Num> {
79     #[cfg(target_endian = "little")]
80     let x = x & 0xffff_ffff;
81     #[cfg(target_endian = "big")]
82     let x = x >> 32;
83 
84     pass_usize(x as usize)
85 }
86 
87 /// Pass a zero, or null, argument.
88 #[inline]
zero<'a, Num: ArgNumber>() -> ArgReg<'a, Num>89 pub(super) fn zero<'a, Num: ArgNumber>() -> ArgReg<'a, Num> {
90     raw_arg(null_mut())
91 }
92 
93 /// Pass the `mem::size_of` of a type.
94 #[inline]
size_of<'a, T: Sized, Num: ArgNumber>() -> ArgReg<'a, Num>95 pub(super) fn size_of<'a, T: Sized, Num: ArgNumber>() -> ArgReg<'a, Num> {
96     pass_usize(core::mem::size_of::<T>())
97 }
98 
99 /// Pass an arbitrary `usize` value.
100 ///
101 /// For passing pointers, use `void_star` or other functions which take a raw
102 /// pointer instead of casting to `usize`, so that provenance is preserved.
103 #[inline]
pass_usize<'a, Num: ArgNumber>(t: usize) -> ArgReg<'a, Num>104 pub(super) fn pass_usize<'a, Num: ArgNumber>(t: usize) -> ArgReg<'a, Num> {
105     raw_arg(t as *mut _)
106 }
107 
108 impl<'a, Num: ArgNumber, T> From<*mut T> for ArgReg<'a, Num> {
109     #[inline]
from(c: *mut T) -> ArgReg<'a, Num>110     fn from(c: *mut T) -> ArgReg<'a, Num> {
111         raw_arg(c.cast())
112     }
113 }
114 
115 impl<'a, Num: ArgNumber, T> From<*const T> for ArgReg<'a, Num> {
116     #[inline]
from(c: *const T) -> ArgReg<'a, Num>117     fn from(c: *const T) -> ArgReg<'a, Num> {
118         let mut_ptr = c as *mut T;
119         raw_arg(mut_ptr.cast())
120     }
121 }
122 
123 impl<'a, Num: ArgNumber> From<&'a CStr> for ArgReg<'a, Num> {
124     #[inline]
from(c: &'a CStr) -> Self125     fn from(c: &'a CStr) -> Self {
126         let mut_ptr = c.as_ptr() as *mut u8;
127         raw_arg(mut_ptr.cast())
128     }
129 }
130 
131 impl<'a, Num: ArgNumber> From<Option<&'a CStr>> for ArgReg<'a, Num> {
132     #[inline]
from(t: Option<&'a CStr>) -> Self133     fn from(t: Option<&'a CStr>) -> Self {
134         raw_arg(match t {
135             Some(s) => {
136                 let mut_ptr = s.as_ptr() as *mut u8;
137                 mut_ptr.cast()
138             }
139             None => null_mut(),
140         })
141     }
142 }
143 
144 /// Pass a borrowed file-descriptor argument.
145 impl<'a, Num: ArgNumber> From<BorrowedFd<'a>> for ArgReg<'a, Num> {
146     #[inline]
from(fd: BorrowedFd<'a>) -> Self147     fn from(fd: BorrowedFd<'a>) -> Self {
148         // SAFETY: `BorrowedFd` ensures that the file descriptor is valid, and
149         // the lifetime parameter on the resulting `ArgReg` ensures that the
150         // result is bounded by the `BorrowedFd`'s lifetime.
151         unsafe { raw_fd(fd.as_raw_fd()) }
152     }
153 }
154 
155 /// Pass a raw file-descriptor argument. Most users should use [`ArgReg::from`]
156 /// instead, to preserve I/O safety as long as possible.
157 ///
158 /// # Safety
159 ///
160 /// `fd` must be a valid open file descriptor.
161 #[inline]
raw_fd<'a, Num: ArgNumber>(fd: RawFd) -> ArgReg<'a, Num>162 pub(super) unsafe fn raw_fd<'a, Num: ArgNumber>(fd: RawFd) -> ArgReg<'a, Num> {
163     // Use `no_fd` when passing `-1` is intended.
164     #[cfg(feature = "fs")]
165     debug_assert!(fd == crate::fs::CWD.as_raw_fd() || fd >= 0);
166 
167     // Don't pass the `io_uring_register_files_skip` sentry value this way.
168     #[cfg(feature = "io_uring")]
169     debug_assert_ne!(
170         fd,
171         crate::io_uring::io_uring_register_files_skip().as_raw_fd()
172     );
173 
174     // Linux doesn't look at the high bits beyond the `c_int`, so use
175     // zero-extension rather than sign-extension because it's a smaller
176     // instruction.
177     let fd: c::c_int = fd;
178     pass_usize(fd as c::c_uint as usize)
179 }
180 
181 /// Deliberately pass `-1` to a file-descriptor argument, for system calls
182 /// like `mmap` where this indicates the argument is omitted.
183 #[inline]
no_fd<'a, Num: ArgNumber>() -> ArgReg<'a, Num>184 pub(super) fn no_fd<'a, Num: ArgNumber>() -> ArgReg<'a, Num> {
185     pass_usize(!0_usize)
186 }
187 
188 #[inline]
slice_just_addr<T: Sized, Num: ArgNumber>(v: &[T]) -> ArgReg<'_, Num>189 pub(super) fn slice_just_addr<T: Sized, Num: ArgNumber>(v: &[T]) -> ArgReg<'_, Num> {
190     let mut_ptr = v.as_ptr() as *mut T;
191     raw_arg(mut_ptr.cast())
192 }
193 
194 #[inline]
slice_just_addr_mut<T: Sized, Num: ArgNumber>(v: &mut [T]) -> ArgReg<'_, Num>195 pub(super) fn slice_just_addr_mut<T: Sized, Num: ArgNumber>(v: &mut [T]) -> ArgReg<'_, Num> {
196     raw_arg(v.as_mut_ptr().cast())
197 }
198 
199 #[inline]
slice<T: Sized, Num0: ArgNumber, Num1: ArgNumber>( v: &[T], ) -> (ArgReg<'_, Num0>, ArgReg<'_, Num1>)200 pub(super) fn slice<T: Sized, Num0: ArgNumber, Num1: ArgNumber>(
201     v: &[T],
202 ) -> (ArgReg<'_, Num0>, ArgReg<'_, Num1>) {
203     (slice_just_addr(v), pass_usize(v.len()))
204 }
205 
206 #[inline]
slice_mut<T: Sized, Num0: ArgNumber, Num1: ArgNumber>( v: &mut [T], ) -> (ArgReg<'_, Num0>, ArgReg<'_, Num1>)207 pub(super) fn slice_mut<T: Sized, Num0: ArgNumber, Num1: ArgNumber>(
208     v: &mut [T],
209 ) -> (ArgReg<'_, Num0>, ArgReg<'_, Num1>) {
210     (raw_arg(v.as_mut_ptr().cast()), pass_usize(v.len()))
211 }
212 
213 #[inline]
by_ref<T: Sized, Num: ArgNumber>(t: &T) -> ArgReg<'_, Num>214 pub(super) fn by_ref<T: Sized, Num: ArgNumber>(t: &T) -> ArgReg<'_, Num> {
215     let mut_ptr = as_ptr(t) as *mut T;
216     raw_arg(mut_ptr.cast())
217 }
218 
219 #[inline]
by_mut<T: Sized, Num: ArgNumber>(t: &mut T) -> ArgReg<'_, Num>220 pub(super) fn by_mut<T: Sized, Num: ArgNumber>(t: &mut T) -> ArgReg<'_, Num> {
221     raw_arg(as_mut_ptr(t).cast())
222 }
223 
224 /// Convert an optional mutable reference into a `usize` for passing to a
225 /// syscall.
226 #[inline]
opt_mut<T: Sized, Num: ArgNumber>(t: Option<&mut T>) -> ArgReg<'_, Num>227 pub(super) fn opt_mut<T: Sized, Num: ArgNumber>(t: Option<&mut T>) -> ArgReg<'_, Num> {
228     // This optimizes into the equivalent of `transmute(t)`, and has the
229     // advantage of not requiring `unsafe`.
230     match t {
231         Some(t) => by_mut(t),
232         None => raw_arg(null_mut()),
233     }
234 }
235 
236 /// Convert an optional immutable reference into a `usize` for passing to a
237 /// syscall.
238 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
239 #[inline]
opt_ref<T: Sized, Num: ArgNumber>(t: Option<&T>) -> ArgReg<'_, Num>240 pub(super) fn opt_ref<T: Sized, Num: ArgNumber>(t: Option<&T>) -> ArgReg<'_, Num> {
241     // This optimizes into the equivalent of `transmute(t)`, and has the
242     // advantage of not requiring `unsafe`.
243     match t {
244         Some(t) => by_ref(t),
245         None => raw_arg(null_mut()),
246     }
247 }
248 
249 /// Convert a `c_int` into an `ArgReg`.
250 ///
251 /// Be sure to use `raw_fd` to pass `RawFd` values.
252 #[inline]
c_int<'a, Num: ArgNumber>(i: c::c_int) -> ArgReg<'a, Num>253 pub(super) fn c_int<'a, Num: ArgNumber>(i: c::c_int) -> ArgReg<'a, Num> {
254     pass_usize(i as usize)
255 }
256 
257 /// Convert a `c_uint` into an `ArgReg`.
258 #[inline]
c_uint<'a, Num: ArgNumber>(i: c::c_uint) -> ArgReg<'a, Num>259 pub(super) fn c_uint<'a, Num: ArgNumber>(i: c::c_uint) -> ArgReg<'a, Num> {
260     pass_usize(i as usize)
261 }
262 
263 #[cfg(target_pointer_width = "64")]
264 #[inline]
loff_t<'a, Num: ArgNumber>(i: __kernel_loff_t) -> ArgReg<'a, Num>265 pub(super) fn loff_t<'a, Num: ArgNumber>(i: __kernel_loff_t) -> ArgReg<'a, Num> {
266     pass_usize(i as usize)
267 }
268 
269 #[cfg(target_pointer_width = "64")]
270 #[inline]
loff_t_from_u64<'a, Num: ArgNumber>(i: u64) -> ArgReg<'a, Num>271 pub(super) fn loff_t_from_u64<'a, Num: ArgNumber>(i: u64) -> ArgReg<'a, Num> {
272     // `loff_t` is signed, but syscalls which expect `loff_t` return `EINVAL`
273     // if it's outside the signed `i64` range, so we can silently cast.
274     pass_usize(i as usize)
275 }
276 
277 #[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
278 impl<'a, Num: ArgNumber> From<ClockId> for ArgReg<'a, Num> {
279     #[inline]
from(i: ClockId) -> Self280     fn from(i: ClockId) -> Self {
281         pass_usize(i as __kernel_clockid_t as usize)
282     }
283 }
284 
285 #[cfg(feature = "time")]
286 impl<'a, Num: ArgNumber> From<TimerfdClockId> for ArgReg<'a, Num> {
287     #[inline]
from(i: TimerfdClockId) -> Self288     fn from(i: TimerfdClockId) -> Self {
289         pass_usize(i as __kernel_clockid_t as usize)
290     }
291 }
292 
293 #[cfg(feature = "net")]
294 #[inline]
socklen_t<'a, Num: ArgNumber>(i: socklen_t) -> ArgReg<'a, Num>295 pub(super) fn socklen_t<'a, Num: ArgNumber>(i: socklen_t) -> ArgReg<'a, Num> {
296     pass_usize(i as usize)
297 }
298 
299 #[cfg(any(
300     feature = "fs",
301     all(
302         not(feature = "use-libc-auxv"),
303         not(feature = "use-explicitly-provided-auxv"),
304         any(
305             feature = "param",
306             feature = "process",
307             feature = "runtime",
308             feature = "time",
309             target_arch = "x86",
310         )
311     )
312 ))]
313 pub(crate) mod fs {
314     use super::*;
315     use crate::fs::{FileType, Mode, OFlags};
316     #[cfg(target_pointer_width = "32")]
317     use linux_raw_sys::general::O_LARGEFILE;
318 
319     impl<'a, Num: ArgNumber> From<Mode> for ArgReg<'a, Num> {
320         #[inline]
from(mode: Mode) -> Self321         fn from(mode: Mode) -> Self {
322             pass_usize(mode.bits() as usize)
323         }
324     }
325 
326     impl<'a, Num: ArgNumber> From<(Mode, FileType)> for ArgReg<'a, Num> {
327         #[inline]
from(pair: (Mode, FileType)) -> Self328         fn from(pair: (Mode, FileType)) -> Self {
329             pass_usize(pair.0.as_raw_mode() as usize | pair.1.as_raw_mode() as usize)
330         }
331     }
332 
333     impl<'a, Num: ArgNumber> From<crate::fs::AtFlags> for ArgReg<'a, Num> {
334         #[inline]
from(flags: crate::fs::AtFlags) -> Self335         fn from(flags: crate::fs::AtFlags) -> Self {
336             c_uint(flags.bits())
337         }
338     }
339 
340     impl<'a, Num: ArgNumber> From<crate::fs::XattrFlags> for ArgReg<'a, Num> {
341         #[inline]
from(flags: crate::fs::XattrFlags) -> Self342         fn from(flags: crate::fs::XattrFlags) -> Self {
343             c_uint(flags.bits())
344         }
345     }
346 
347     impl<'a, Num: ArgNumber> From<crate::fs::inotify::CreateFlags> for ArgReg<'a, Num> {
348         #[inline]
from(flags: crate::fs::inotify::CreateFlags) -> Self349         fn from(flags: crate::fs::inotify::CreateFlags) -> Self {
350             c_uint(flags.bits())
351         }
352     }
353 
354     impl<'a, Num: ArgNumber> From<crate::fs::inotify::WatchFlags> for ArgReg<'a, Num> {
355         #[inline]
from(flags: crate::fs::inotify::WatchFlags) -> Self356         fn from(flags: crate::fs::inotify::WatchFlags) -> Self {
357             c_uint(flags.bits())
358         }
359     }
360 
361     impl<'a, Num: ArgNumber> From<crate::fs::MemfdFlags> for ArgReg<'a, Num> {
362         #[inline]
from(flags: crate::fs::MemfdFlags) -> Self363         fn from(flags: crate::fs::MemfdFlags) -> Self {
364             c_uint(flags.bits())
365         }
366     }
367 
368     impl<'a, Num: ArgNumber> From<crate::fs::RenameFlags> for ArgReg<'a, Num> {
369         #[inline]
from(flags: crate::fs::RenameFlags) -> Self370         fn from(flags: crate::fs::RenameFlags) -> Self {
371             c_uint(flags.bits())
372         }
373     }
374 
375     impl<'a, Num: ArgNumber> From<crate::fs::StatxFlags> for ArgReg<'a, Num> {
376         #[inline]
from(flags: crate::fs::StatxFlags) -> Self377         fn from(flags: crate::fs::StatxFlags) -> Self {
378             c_uint(flags.bits())
379         }
380     }
381 
382     #[cfg(target_pointer_width = "32")]
383     #[inline]
oflags_bits(oflags: OFlags) -> c::c_uint384     fn oflags_bits(oflags: OFlags) -> c::c_uint {
385         let mut bits = oflags.bits();
386         // Add `O_LARGEFILE`, unless `O_PATH` is set, as Linux returns `EINVAL`
387         // when both are set.
388         if !oflags.contains(OFlags::PATH) {
389             bits |= O_LARGEFILE;
390         }
391         bits
392     }
393 
394     #[cfg(target_pointer_width = "64")]
395     #[inline]
oflags_bits(oflags: OFlags) -> c::c_uint396     const fn oflags_bits(oflags: OFlags) -> c::c_uint {
397         oflags.bits()
398     }
399 
400     impl<'a, Num: ArgNumber> From<OFlags> for ArgReg<'a, Num> {
401         #[inline]
from(oflags: OFlags) -> Self402         fn from(oflags: OFlags) -> Self {
403             pass_usize(oflags_bits(oflags) as usize)
404         }
405     }
406 
407     /// Convert an `OFlags` into a `u64` for use in the `open_how` struct.
408     #[inline]
oflags_for_open_how(oflags: OFlags) -> u64409     pub(crate) fn oflags_for_open_how(oflags: OFlags) -> u64 {
410         u64::from(oflags_bits(oflags))
411     }
412 
413     impl<'a, Num: ArgNumber> From<crate::fs::FallocateFlags> for ArgReg<'a, Num> {
414         #[inline]
from(flags: crate::fs::FallocateFlags) -> Self415         fn from(flags: crate::fs::FallocateFlags) -> Self {
416             c_uint(flags.bits())
417         }
418     }
419 
420     impl<'a, Num: ArgNumber> From<crate::fs::Advice> for ArgReg<'a, Num> {
421         #[inline]
from(advice: crate::fs::Advice) -> Self422         fn from(advice: crate::fs::Advice) -> Self {
423             c_uint(advice as c::c_uint)
424         }
425     }
426 
427     impl<'a, Num: ArgNumber> From<crate::fs::SealFlags> for ArgReg<'a, Num> {
428         #[inline]
from(flags: crate::fs::SealFlags) -> Self429         fn from(flags: crate::fs::SealFlags) -> Self {
430             c_uint(flags.bits())
431         }
432     }
433 
434     impl<'a, Num: ArgNumber> From<crate::fs::Access> for ArgReg<'a, Num> {
435         #[inline]
from(access: crate::fs::Access) -> Self436         fn from(access: crate::fs::Access) -> Self {
437             c_uint(access.bits())
438         }
439     }
440 }
441 
442 #[cfg(any(feature = "fs", feature = "mount"))]
443 impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MountFlagsArg> for ArgReg<'a, Num> {
444     #[inline]
from(flags: crate::backend::mount::types::MountFlagsArg) -> Self445     fn from(flags: crate::backend::mount::types::MountFlagsArg) -> Self {
446         c_uint(flags.0)
447     }
448 }
449 
450 // When the deprecated "fs" aliases are removed, we can remove the "fs"
451 // here too.
452 #[cfg(any(feature = "fs", feature = "mount"))]
453 impl<'a, Num: ArgNumber> From<crate::backend::mount::types::UnmountFlags> for ArgReg<'a, Num> {
454     #[inline]
from(flags: crate::backend::mount::types::UnmountFlags) -> Self455     fn from(flags: crate::backend::mount::types::UnmountFlags) -> Self {
456         c_uint(flags.bits())
457     }
458 }
459 
460 #[cfg(feature = "mount")]
461 impl<'a, Num: ArgNumber> From<crate::mount::FsConfigCmd> for ArgReg<'a, Num> {
462     #[inline]
from(cmd: crate::mount::FsConfigCmd) -> Self463     fn from(cmd: crate::mount::FsConfigCmd) -> Self {
464         c_uint(cmd as c::c_uint)
465     }
466 }
467 
468 #[cfg(feature = "mount")]
469 impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsOpenFlags> for ArgReg<'a, Num> {
470     #[inline]
from(flags: crate::backend::mount::types::FsOpenFlags) -> Self471     fn from(flags: crate::backend::mount::types::FsOpenFlags) -> Self {
472         c_uint(flags.bits())
473     }
474 }
475 
476 #[cfg(feature = "mount")]
477 impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsMountFlags> for ArgReg<'a, Num> {
478     #[inline]
from(flags: crate::backend::mount::types::FsMountFlags) -> Self479     fn from(flags: crate::backend::mount::types::FsMountFlags) -> Self {
480         c_uint(flags.bits())
481     }
482 }
483 
484 #[cfg(feature = "mount")]
485 impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MountAttrFlags> for ArgReg<'a, Num> {
486     #[inline]
from(flags: crate::backend::mount::types::MountAttrFlags) -> Self487     fn from(flags: crate::backend::mount::types::MountAttrFlags) -> Self {
488         c_uint(flags.bits())
489     }
490 }
491 
492 #[cfg(feature = "mount")]
493 impl<'a, Num: ArgNumber> From<crate::backend::mount::types::OpenTreeFlags> for ArgReg<'a, Num> {
494     #[inline]
from(flags: crate::backend::mount::types::OpenTreeFlags) -> Self495     fn from(flags: crate::backend::mount::types::OpenTreeFlags) -> Self {
496         c_uint(flags.bits())
497     }
498 }
499 
500 #[cfg(feature = "mount")]
501 impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsPickFlags> for ArgReg<'a, Num> {
502     #[inline]
from(flags: crate::backend::mount::types::FsPickFlags) -> Self503     fn from(flags: crate::backend::mount::types::FsPickFlags) -> Self {
504         c_uint(flags.bits())
505     }
506 }
507 
508 #[cfg(feature = "mount")]
509 impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MoveMountFlags> for ArgReg<'a, Num> {
510     #[inline]
from(flags: crate::backend::mount::types::MoveMountFlags) -> Self511     fn from(flags: crate::backend::mount::types::MoveMountFlags) -> Self {
512         c_uint(flags.bits())
513     }
514 }
515 
516 impl<'a, Num: ArgNumber> From<crate::io::FdFlags> for ArgReg<'a, Num> {
517     #[inline]
from(flags: crate::io::FdFlags) -> Self518     fn from(flags: crate::io::FdFlags) -> Self {
519         c_uint(flags.bits())
520     }
521 }
522 
523 #[cfg(feature = "pipe")]
524 impl<'a, Num: ArgNumber> From<crate::pipe::PipeFlags> for ArgReg<'a, Num> {
525     #[inline]
from(flags: crate::pipe::PipeFlags) -> Self526     fn from(flags: crate::pipe::PipeFlags) -> Self {
527         c_uint(flags.bits())
528     }
529 }
530 
531 #[cfg(feature = "pipe")]
532 impl<'a, Num: ArgNumber> From<crate::pipe::SpliceFlags> for ArgReg<'a, Num> {
533     #[inline]
from(flags: crate::pipe::SpliceFlags) -> Self534     fn from(flags: crate::pipe::SpliceFlags) -> Self {
535         c_uint(flags.bits())
536     }
537 }
538 
539 impl<'a, Num: ArgNumber> From<crate::io::DupFlags> for ArgReg<'a, Num> {
540     #[inline]
from(flags: crate::io::DupFlags) -> Self541     fn from(flags: crate::io::DupFlags) -> Self {
542         c_uint(flags.bits())
543     }
544 }
545 
546 impl<'a, Num: ArgNumber> From<crate::io::ReadWriteFlags> for ArgReg<'a, Num> {
547     #[inline]
from(flags: crate::io::ReadWriteFlags) -> Self548     fn from(flags: crate::io::ReadWriteFlags) -> Self {
549         c_uint(flags.bits())
550     }
551 }
552 
553 #[cfg(feature = "process")]
554 impl<'a, Num: ArgNumber> From<crate::process::PidfdFlags> for ArgReg<'a, Num> {
555     #[inline]
from(flags: crate::process::PidfdFlags) -> Self556     fn from(flags: crate::process::PidfdFlags) -> Self {
557         c_uint(flags.bits())
558     }
559 }
560 
561 #[cfg(feature = "pty")]
562 impl<'a, Num: ArgNumber> From<crate::pty::OpenptFlags> for ArgReg<'a, Num> {
563     #[inline]
from(flags: crate::pty::OpenptFlags) -> Self564     fn from(flags: crate::pty::OpenptFlags) -> Self {
565         c_uint(flags.bits())
566     }
567 }
568 
569 #[cfg(feature = "thread")]
570 impl<'a, Num: ArgNumber> From<crate::thread::UnshareFlags> for ArgReg<'a, Num> {
571     #[inline]
from(flags: crate::thread::UnshareFlags) -> Self572     fn from(flags: crate::thread::UnshareFlags) -> Self {
573         c_uint(flags.bits())
574     }
575 }
576 
577 #[cfg(feature = "event")]
578 impl<'a, Num: ArgNumber> From<crate::event::EventfdFlags> for ArgReg<'a, Num> {
579     #[inline]
from(flags: crate::event::EventfdFlags) -> Self580     fn from(flags: crate::event::EventfdFlags) -> Self {
581         c_uint(flags.bits())
582     }
583 }
584 
585 #[cfg(feature = "event")]
586 impl<'a, Num: ArgNumber> From<crate::event::epoll::CreateFlags> for ArgReg<'a, Num> {
587     #[inline]
from(flags: crate::event::epoll::CreateFlags) -> Self588     fn from(flags: crate::event::epoll::CreateFlags) -> Self {
589         c_uint(flags.bits())
590     }
591 }
592 
593 #[cfg(feature = "mm")]
594 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::ProtFlags> for ArgReg<'a, Num> {
595     #[inline]
from(flags: crate::backend::mm::types::ProtFlags) -> Self596     fn from(flags: crate::backend::mm::types::ProtFlags) -> Self {
597         c_uint(flags.bits())
598     }
599 }
600 
601 #[cfg(feature = "mm")]
602 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MsyncFlags> for ArgReg<'a, Num> {
603     #[inline]
from(flags: crate::backend::mm::types::MsyncFlags) -> Self604     fn from(flags: crate::backend::mm::types::MsyncFlags) -> Self {
605         c_uint(flags.bits())
606     }
607 }
608 
609 #[cfg(feature = "mm")]
610 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MremapFlags> for ArgReg<'a, Num> {
611     #[inline]
from(flags: crate::backend::mm::types::MremapFlags) -> Self612     fn from(flags: crate::backend::mm::types::MremapFlags) -> Self {
613         c_uint(flags.bits())
614     }
615 }
616 
617 #[cfg(feature = "mm")]
618 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MlockFlags> for ArgReg<'a, Num> {
619     #[inline]
from(flags: crate::backend::mm::types::MlockFlags) -> Self620     fn from(flags: crate::backend::mm::types::MlockFlags) -> Self {
621         c_uint(flags.bits())
622     }
623 }
624 
625 #[cfg(feature = "mm")]
626 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MlockAllFlags> for ArgReg<'a, Num> {
627     #[inline]
from(flags: crate::backend::mm::types::MlockAllFlags) -> Self628     fn from(flags: crate::backend::mm::types::MlockAllFlags) -> Self {
629         c_uint(flags.bits())
630     }
631 }
632 
633 #[cfg(feature = "mm")]
634 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MapFlags> for ArgReg<'a, Num> {
635     #[inline]
from(flags: crate::backend::mm::types::MapFlags) -> Self636     fn from(flags: crate::backend::mm::types::MapFlags) -> Self {
637         c_uint(flags.bits())
638     }
639 }
640 
641 #[cfg(feature = "mm")]
642 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MprotectFlags> for ArgReg<'a, Num> {
643     #[inline]
from(flags: crate::backend::mm::types::MprotectFlags) -> Self644     fn from(flags: crate::backend::mm::types::MprotectFlags) -> Self {
645         c_uint(flags.bits())
646     }
647 }
648 
649 #[cfg(feature = "mm")]
650 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::UserfaultfdFlags> for ArgReg<'a, Num> {
651     #[inline]
from(flags: crate::backend::mm::types::UserfaultfdFlags) -> Self652     fn from(flags: crate::backend::mm::types::UserfaultfdFlags) -> Self {
653         c_uint(flags.bits())
654     }
655 }
656 
657 #[cfg(feature = "process")]
658 impl<'a, Num: ArgNumber> From<crate::backend::process::types::MembarrierCommand>
659     for ArgReg<'a, Num>
660 {
661     #[inline]
from(cmd: crate::backend::process::types::MembarrierCommand) -> Self662     fn from(cmd: crate::backend::process::types::MembarrierCommand) -> Self {
663         c_uint(cmd as u32)
664     }
665 }
666 
667 #[cfg(feature = "process")]
668 impl<'a, Num: ArgNumber> From<crate::process::Cpuid> for ArgReg<'a, Num> {
669     #[inline]
from(cpuid: crate::process::Cpuid) -> Self670     fn from(cpuid: crate::process::Cpuid) -> Self {
671         c_uint(cpuid.as_raw())
672     }
673 }
674 
675 #[cfg(target_pointer_width = "64")]
676 #[inline]
dev_t<'a, Num: ArgNumber>(dev: u64) -> ArgReg<'a, Num>677 pub(super) fn dev_t<'a, Num: ArgNumber>(dev: u64) -> ArgReg<'a, Num> {
678     pass_usize(dev as usize)
679 }
680 
681 #[cfg(target_pointer_width = "32")]
682 #[inline]
dev_t<'a, Num: ArgNumber>(dev: u64) -> io::Result<ArgReg<'a, Num>>683 pub(super) fn dev_t<'a, Num: ArgNumber>(dev: u64) -> io::Result<ArgReg<'a, Num>> {
684     Ok(pass_usize(dev.try_into().map_err(|_err| io::Errno::INVAL)?))
685 }
686 
687 /// Convert a `Resource` into a syscall argument.
688 #[cfg(feature = "process")]
689 impl<'a, Num: ArgNumber> From<Resource> for ArgReg<'a, Num> {
690     #[inline]
from(resource: Resource) -> Self691     fn from(resource: Resource) -> Self {
692         c_uint(resource as c::c_uint)
693     }
694 }
695 
696 #[cfg(any(feature = "process", feature = "runtime", feature = "termios"))]
697 impl<'a, Num: ArgNumber> From<Pid> for ArgReg<'a, Num> {
698     #[inline]
from(pid: Pid) -> Self699     fn from(pid: Pid) -> Self {
700         pass_usize(pid.as_raw_nonzero().get() as usize)
701     }
702 }
703 
704 #[cfg(feature = "process")]
705 #[inline]
negative_pid<'a, Num: ArgNumber>(pid: Pid) -> ArgReg<'a, Num>706 pub(super) fn negative_pid<'a, Num: ArgNumber>(pid: Pid) -> ArgReg<'a, Num> {
707     pass_usize(pid.as_raw_nonzero().get().wrapping_neg() as usize)
708 }
709 
710 #[cfg(any(feature = "process", feature = "runtime"))]
711 impl<'a, Num: ArgNumber> From<Signal> for ArgReg<'a, Num> {
712     #[inline]
from(sig: Signal) -> Self713     fn from(sig: Signal) -> Self {
714         pass_usize(sig as usize)
715     }
716 }
717 
718 #[cfg(feature = "io_uring")]
719 impl<'a, Num: ArgNumber> From<crate::io_uring::IoringEnterFlags> for ArgReg<'a, Num> {
720     #[inline]
from(flags: crate::io_uring::IoringEnterFlags) -> Self721     fn from(flags: crate::io_uring::IoringEnterFlags) -> Self {
722         c_uint(flags.bits())
723     }
724 }
725 
726 #[cfg(feature = "time")]
727 impl<'a, Num: ArgNumber> From<crate::time::TimerfdFlags> for ArgReg<'a, Num> {
728     #[inline]
from(flags: crate::time::TimerfdFlags) -> Self729     fn from(flags: crate::time::TimerfdFlags) -> Self {
730         c_uint(flags.bits())
731     }
732 }
733 
734 #[cfg(feature = "time")]
735 impl<'a, Num: ArgNumber> From<crate::time::TimerfdTimerFlags> for ArgReg<'a, Num> {
736     #[inline]
from(flags: crate::time::TimerfdTimerFlags) -> Self737     fn from(flags: crate::time::TimerfdTimerFlags) -> Self {
738         c_uint(flags.bits())
739     }
740 }
741 
742 #[cfg(feature = "rand")]
743 impl<'a, Num: ArgNumber> From<crate::rand::GetRandomFlags> for ArgReg<'a, Num> {
744     #[inline]
from(flags: crate::rand::GetRandomFlags) -> Self745     fn from(flags: crate::rand::GetRandomFlags) -> Self {
746         c_uint(flags.bits())
747     }
748 }
749 
750 #[cfg(feature = "net")]
751 impl<'a, Num: ArgNumber> From<crate::net::RecvFlags> for ArgReg<'a, Num> {
752     #[inline]
from(flags: crate::net::RecvFlags) -> Self753     fn from(flags: crate::net::RecvFlags) -> Self {
754         c_uint(flags.bits())
755     }
756 }
757 
758 #[cfg(feature = "net")]
759 impl<'a, Num: ArgNumber> From<crate::net::SendFlags> for ArgReg<'a, Num> {
760     #[inline]
from(flags: crate::net::SendFlags) -> Self761     fn from(flags: crate::net::SendFlags) -> Self {
762         c_uint(flags.bits())
763     }
764 }
765 
766 #[cfg(feature = "net")]
767 impl<'a, Num: ArgNumber> From<crate::net::SocketFlags> for ArgReg<'a, Num> {
768     #[inline]
from(flags: crate::net::SocketFlags) -> Self769     fn from(flags: crate::net::SocketFlags) -> Self {
770         c_uint(flags.bits())
771     }
772 }
773 
774 #[cfg(feature = "net")]
775 impl<'a, Num: ArgNumber> From<crate::net::AddressFamily> for ArgReg<'a, Num> {
776     #[inline]
from(family: crate::net::AddressFamily) -> Self777     fn from(family: crate::net::AddressFamily) -> Self {
778         c_uint(family.0.into())
779     }
780 }
781 
782 #[cfg(feature = "net")]
783 impl<'a, Num: ArgNumber> From<(crate::net::SocketType, crate::net::SocketFlags)>
784     for ArgReg<'a, Num>
785 {
786     #[inline]
from(pair: (crate::net::SocketType, crate::net::SocketFlags)) -> Self787     fn from(pair: (crate::net::SocketType, crate::net::SocketFlags)) -> Self {
788         c_uint(pair.0 .0 | pair.1.bits())
789     }
790 }
791 
792 #[cfg(feature = "thread")]
793 impl<'a, Num: ArgNumber> From<(crate::thread::FutexOperation, crate::thread::FutexFlags)>
794     for ArgReg<'a, Num>
795 {
796     #[inline]
from(pair: (crate::thread::FutexOperation, crate::thread::FutexFlags)) -> Self797     fn from(pair: (crate::thread::FutexOperation, crate::thread::FutexFlags)) -> Self {
798         c_uint(pair.0 as u32 | pair.1.bits())
799     }
800 }
801 
802 #[cfg(feature = "net")]
803 impl<'a, Num: ArgNumber> From<crate::net::SocketType> for ArgReg<'a, Num> {
804     #[inline]
from(type_: crate::net::SocketType) -> Self805     fn from(type_: crate::net::SocketType) -> Self {
806         c_uint(type_.0)
807     }
808 }
809 
810 #[cfg(feature = "net")]
811 impl<'a, Num: ArgNumber> From<Option<crate::net::Protocol>> for ArgReg<'a, Num> {
812     #[inline]
from(protocol: Option<crate::net::Protocol>) -> Self813     fn from(protocol: Option<crate::net::Protocol>) -> Self {
814         c_uint(match protocol {
815             Some(p) => p.0.get(),
816             None => 0,
817         })
818     }
819 }
820 
821 impl<'a, Num: ArgNumber, T> From<&'a mut MaybeUninit<T>> for ArgReg<'a, Num> {
822     #[inline]
from(t: &'a mut MaybeUninit<T>) -> Self823     fn from(t: &'a mut MaybeUninit<T>) -> Self {
824         raw_arg(t.as_mut_ptr().cast())
825     }
826 }
827 
828 impl<'a, Num: ArgNumber, T> From<&'a mut [MaybeUninit<T>]> for ArgReg<'a, Num> {
829     #[inline]
from(t: &'a mut [MaybeUninit<T>]) -> Self830     fn from(t: &'a mut [MaybeUninit<T>]) -> Self {
831         raw_arg(t.as_mut_ptr().cast())
832     }
833 }
834 
835 #[cfg(any(feature = "process", feature = "thread"))]
836 impl<'a, Num: ArgNumber> From<crate::ugid::Uid> for ArgReg<'a, Num> {
837     #[inline]
from(t: crate::ugid::Uid) -> Self838     fn from(t: crate::ugid::Uid) -> Self {
839         c_uint(t.as_raw())
840     }
841 }
842 
843 #[cfg(any(feature = "process", feature = "thread"))]
844 impl<'a, Num: ArgNumber> From<crate::ugid::Gid> for ArgReg<'a, Num> {
845     #[inline]
from(t: crate::ugid::Gid) -> Self846     fn from(t: crate::ugid::Gid) -> Self {
847         c_uint(t.as_raw())
848     }
849 }
850 
851 #[cfg(feature = "runtime")]
852 impl<'a, Num: ArgNumber> From<crate::runtime::How> for ArgReg<'a, Num> {
853     #[inline]
from(flags: crate::runtime::How) -> Self854     fn from(flags: crate::runtime::How) -> Self {
855         c_uint(flags as u32)
856     }
857 }
858 
859 /// Convert a `usize` returned from a syscall that effectively returns `()` on
860 /// success.
861 ///
862 /// # Safety
863 ///
864 /// The caller must ensure that this is the return value of a syscall which
865 /// just returns 0 on success.
866 #[inline]
ret(raw: RetReg<R0>) -> io::Result<()>867 pub(super) unsafe fn ret(raw: RetReg<R0>) -> io::Result<()> {
868     try_decode_void(raw)
869 }
870 
871 /// Convert a `usize` returned from a syscall that doesn't return on success.
872 ///
873 /// # Safety
874 ///
875 /// The caller must ensure that this is the return value of a syscall which
876 /// doesn't return on success.
877 #[cfg(any(feature = "event", feature = "runtime"))]
878 #[inline]
ret_error(raw: RetReg<R0>) -> io::Errno879 pub(super) unsafe fn ret_error(raw: RetReg<R0>) -> io::Errno {
880     try_decode_error(raw)
881 }
882 
883 /// Convert a `usize` returned from a syscall that effectively always returns
884 /// `()`.
885 ///
886 /// # Safety
887 ///
888 /// The caller must ensure that this is the return value of a syscall which
889 /// always returns `()`.
890 #[inline]
ret_infallible(raw: RetReg<R0>)891 pub(super) unsafe fn ret_infallible(raw: RetReg<R0>) {
892     #[cfg(debug_assertions)]
893     {
894         try_decode_void(raw).unwrap()
895     }
896     #[cfg(not(debug_assertions))]
897     drop(raw);
898 }
899 
900 /// Convert a `usize` returned from a syscall that effectively returns a
901 /// `c_int` on success.
902 #[inline]
ret_c_int(raw: RetReg<R0>) -> io::Result<c::c_int>903 pub(super) fn ret_c_int(raw: RetReg<R0>) -> io::Result<c::c_int> {
904     try_decode_c_int(raw)
905 }
906 
907 /// Convert a `usize` returned from a syscall that effectively returns a
908 /// `c_uint` on success.
909 #[inline]
ret_c_uint(raw: RetReg<R0>) -> io::Result<c::c_uint>910 pub(super) fn ret_c_uint(raw: RetReg<R0>) -> io::Result<c::c_uint> {
911     try_decode_c_uint(raw)
912 }
913 
914 /// Convert a `usize` returned from a syscall that effectively returns a `u64`
915 /// on success.
916 #[cfg(target_pointer_width = "64")]
917 #[inline]
ret_u64(raw: RetReg<R0>) -> io::Result<u64>918 pub(super) fn ret_u64(raw: RetReg<R0>) -> io::Result<u64> {
919     try_decode_u64(raw)
920 }
921 
922 /// Convert a `usize` returned from a syscall that effectively returns a
923 /// `usize` on success.
924 #[inline]
ret_usize(raw: RetReg<R0>) -> io::Result<usize>925 pub(super) fn ret_usize(raw: RetReg<R0>) -> io::Result<usize> {
926     try_decode_usize(raw)
927 }
928 
929 /// Convert a `usize` returned from a syscall that effectively always
930 /// returns a `usize`.
931 ///
932 /// # Safety
933 ///
934 /// This function must only be used with return values from infallible
935 /// syscalls.
936 #[inline]
ret_usize_infallible(raw: RetReg<R0>) -> usize937 pub(super) unsafe fn ret_usize_infallible(raw: RetReg<R0>) -> usize {
938     #[cfg(debug_assertions)]
939     {
940         try_decode_usize(raw).unwrap()
941     }
942     #[cfg(not(debug_assertions))]
943     {
944         decode_usize_infallible(raw)
945     }
946 }
947 
948 /// Convert a `c_int` returned from a syscall that effectively always
949 /// returns a `c_int`.
950 ///
951 /// # Safety
952 ///
953 /// This function must only be used with return values from infallible
954 /// syscalls.
955 #[inline]
ret_c_int_infallible(raw: RetReg<R0>) -> c::c_int956 pub(super) unsafe fn ret_c_int_infallible(raw: RetReg<R0>) -> c::c_int {
957     #[cfg(debug_assertions)]
958     {
959         try_decode_c_int(raw).unwrap()
960     }
961     #[cfg(not(debug_assertions))]
962     {
963         decode_c_int_infallible(raw)
964     }
965 }
966 
967 /// Convert a `c_uint` returned from a syscall that effectively always
968 /// returns a `c_uint`.
969 ///
970 /// # Safety
971 ///
972 /// This function must only be used with return values from infallible
973 /// syscalls.
974 #[inline]
ret_c_uint_infallible(raw: RetReg<R0>) -> c::c_uint975 pub(super) unsafe fn ret_c_uint_infallible(raw: RetReg<R0>) -> c::c_uint {
976     #[cfg(debug_assertions)]
977     {
978         try_decode_c_uint(raw).unwrap()
979     }
980     #[cfg(not(debug_assertions))]
981     {
982         decode_c_uint_infallible(raw)
983     }
984 }
985 
986 /// Convert a `usize` returned from a syscall that effectively returns an
987 /// `OwnedFd` on success.
988 ///
989 /// # Safety
990 ///
991 /// The caller must ensure that this is the return value of a syscall which
992 /// returns an owned file descriptor.
993 #[inline]
ret_owned_fd(raw: RetReg<R0>) -> io::Result<OwnedFd>994 pub(super) unsafe fn ret_owned_fd(raw: RetReg<R0>) -> io::Result<OwnedFd> {
995     let raw_fd = try_decode_raw_fd(raw)?;
996     Ok(crate::backend::fd::OwnedFd::from_raw_fd(raw_fd))
997 }
998 
999 /// Convert the return value of `dup2` and `dup3`.
1000 ///
1001 /// When these functions succeed, they return the same value as their second
1002 /// argument, so we don't construct a new `OwnedFd`.
1003 ///
1004 /// # Safety
1005 ///
1006 /// The caller must ensure that this is the return value of a syscall which
1007 /// returns a file descriptor.
1008 #[inline]
ret_discarded_fd(raw: RetReg<R0>) -> io::Result<()>1009 pub(super) unsafe fn ret_discarded_fd(raw: RetReg<R0>) -> io::Result<()> {
1010     let _raw_fd = try_decode_raw_fd(raw)?;
1011     Ok(())
1012 }
1013 
1014 /// Convert a `usize` returned from a syscall that effectively returns a
1015 /// `*mut c_void` on success.
1016 #[inline]
ret_void_star(raw: RetReg<R0>) -> io::Result<*mut c::c_void>1017 pub(super) fn ret_void_star(raw: RetReg<R0>) -> io::Result<*mut c::c_void> {
1018     try_decode_void_star(raw)
1019 }
1020