• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
6 //! them 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(not(debug_assertions))]
19 use super::io::errno::decode_usize_infallible;
20 #[cfg(feature = "runtime")]
21 use super::io::errno::try_decode_error;
22 #[cfg(target_pointer_width = "64")]
23 use super::io::errno::try_decode_u64;
24 use super::io::errno::{
25     try_decode_c_int, try_decode_c_uint, try_decode_raw_fd, try_decode_usize, try_decode_void,
26     try_decode_void_star,
27 };
28 use super::reg::{raw_arg, ArgNumber, ArgReg, RetReg, R0};
29 #[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
30 use super::time::types::ClockId;
31 #[cfg(feature = "time")]
32 use super::time::types::TimerfdClockId;
33 use crate::fd::OwnedFd;
34 use crate::ffi::CStr;
35 #[cfg(feature = "fs")]
36 use crate::fs::{FileType, Mode, OFlags};
37 use crate::io;
38 use crate::process::{Pid, Resource, Signal};
39 use crate::utils::{as_mut_ptr, as_ptr};
40 use core::mem::MaybeUninit;
41 use core::ptr::null_mut;
42 #[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
43 use linux_raw_sys::general::__kernel_clockid_t;
44 #[cfg(target_pointer_width = "64")]
45 use linux_raw_sys::general::__kernel_loff_t;
46 #[cfg(feature = "net")]
47 use linux_raw_sys::general::socklen_t;
48 #[cfg(target_pointer_width = "32")]
49 #[cfg(feature = "fs")]
50 use linux_raw_sys::general::O_LARGEFILE;
51 
52 /// Convert `SYS_*` constants for socketcall.
53 #[cfg(target_arch = "x86")]
54 #[inline]
x86_sys<'a, Num: ArgNumber>(sys: u32) -> ArgReg<'a, Num>55 pub(super) fn x86_sys<'a, Num: ArgNumber>(sys: u32) -> ArgReg<'a, Num> {
56     pass_usize(sys as usize)
57 }
58 
59 /// Pass the "low" half of the endian-specific memory encoding of a `u64`, for
60 /// 32-bit architectures.
61 #[cfg(target_pointer_width = "32")]
62 #[inline]
lo<'a, Num: ArgNumber>(x: u64) -> ArgReg<'a, Num>63 pub(super) fn lo<'a, Num: ArgNumber>(x: u64) -> ArgReg<'a, Num> {
64     #[cfg(target_endian = "little")]
65     let x = x >> 32;
66     #[cfg(target_endian = "big")]
67     let x = x & 0xffff_ffff;
68 
69     pass_usize(x as usize)
70 }
71 
72 /// Pass the "high" half of the endian-specific memory encoding of a `u64`, for
73 /// 32-bit architectures.
74 #[cfg(target_pointer_width = "32")]
75 #[inline]
hi<'a, Num: ArgNumber>(x: u64) -> ArgReg<'a, Num>76 pub(super) fn hi<'a, Num: ArgNumber>(x: u64) -> ArgReg<'a, Num> {
77     #[cfg(target_endian = "little")]
78     let x = x & 0xffff_ffff;
79     #[cfg(target_endian = "big")]
80     let x = x >> 32;
81 
82     pass_usize(x as usize)
83 }
84 
85 /// Pass a zero, or null, argument.
86 #[inline]
zero<'a, Num: ArgNumber>() -> ArgReg<'a, Num>87 pub(super) fn zero<'a, Num: ArgNumber>() -> ArgReg<'a, Num> {
88     raw_arg(null_mut())
89 }
90 
91 /// Pass the `mem::size_of` of a type.
92 #[inline]
size_of<'a, T: Sized, Num: ArgNumber>() -> ArgReg<'a, Num>93 pub(super) fn size_of<'a, T: Sized, Num: ArgNumber>() -> ArgReg<'a, Num> {
94     pass_usize(core::mem::size_of::<T>())
95 }
96 
97 /// Pass an arbitrary `usize` value.
98 ///
99 /// For passing pointers, use `void_star` or other functions which take a raw
100 /// pointer instead of casting to `usize`, so that provenance is preserved.
101 #[inline]
pass_usize<'a, Num: ArgNumber>(t: usize) -> ArgReg<'a, Num>102 pub(super) fn pass_usize<'a, Num: ArgNumber>(t: usize) -> ArgReg<'a, Num> {
103     raw_arg(t as *mut _)
104 }
105 
106 impl<'a, Num: ArgNumber, T> From<*mut T> for ArgReg<'a, Num> {
107     #[inline]
from(c: *mut T) -> ArgReg<'a, Num>108     fn from(c: *mut T) -> ArgReg<'a, Num> {
109         raw_arg(c.cast())
110     }
111 }
112 
113 impl<'a, Num: ArgNumber, T> From<*const T> for ArgReg<'a, Num> {
114     #[inline]
from(c: *const T) -> ArgReg<'a, Num>115     fn from(c: *const T) -> ArgReg<'a, Num> {
116         let mut_ptr = c as *mut T;
117         raw_arg(mut_ptr.cast())
118     }
119 }
120 
121 impl<'a, Num: ArgNumber> From<&'a CStr> for ArgReg<'a, Num> {
122     #[inline]
from(c: &'a CStr) -> Self123     fn from(c: &'a CStr) -> Self {
124         let mut_ptr = c.as_ptr() as *mut u8;
125         raw_arg(mut_ptr.cast())
126     }
127 }
128 
129 impl<'a, Num: ArgNumber> From<Option<&'a CStr>> for ArgReg<'a, Num> {
130     #[inline]
from(t: Option<&'a CStr>) -> Self131     fn from(t: Option<&'a CStr>) -> Self {
132         raw_arg(match t {
133             Some(s) => {
134                 let mut_ptr = s.as_ptr() as *mut u8;
135                 mut_ptr.cast()
136             }
137             None => null_mut(),
138         })
139     }
140 }
141 
142 /// Pass a borrowed file-descriptor argument.
143 impl<'a, Num: ArgNumber> From<BorrowedFd<'a>> for ArgReg<'a, Num> {
144     #[inline]
from(fd: BorrowedFd<'a>) -> Self145     fn from(fd: BorrowedFd<'a>) -> Self {
146         // Safety: `BorrowedFd` ensures that the file descriptor is valid, and the
147         // lifetime parameter on the resulting `ArgReg` ensures that the result is
148         // bounded by the `BorrowedFd`'s lifetime.
149         unsafe { raw_fd(fd.as_raw_fd()) }
150     }
151 }
152 
153 /// Pass a raw file-descriptor argument. Most users should use [`ArgReg::from`]
154 /// instead, to preserve I/O safety as long as possible.
155 ///
156 /// # Safety
157 ///
158 /// `fd` must be a valid open file descriptor.
159 #[inline]
raw_fd<'a, Num: ArgNumber>(fd: RawFd) -> ArgReg<'a, Num>160 pub(super) unsafe fn raw_fd<'a, Num: ArgNumber>(fd: RawFd) -> ArgReg<'a, Num> {
161     // Use `no_fd` when passing `-1` is intended.
162     #[cfg(feature = "fs")]
163     debug_assert!(fd == crate::fs::cwd().as_raw_fd() || fd >= 0);
164 
165     // Don't pass the `io_uring_register_files_skip` sentry value this way.
166     #[cfg(feature = "io_uring")]
167     debug_assert_ne!(
168         fd,
169         crate::io_uring::io_uring_register_files_skip().as_raw_fd()
170     );
171 
172     // Linux doesn't look at the high bits beyond the `c_int`, so use
173     // zero-extension rather than sign-extension because it's a smaller
174     // instruction.
175     let fd: c::c_int = fd;
176     pass_usize(fd as c::c_uint as usize)
177 }
178 
179 /// Deliberately pass `-1` to a file-descriptor argument, for system calls
180 /// like `mmap` where this indicates the argument is omitted.
181 #[inline]
no_fd<'a, Num: ArgNumber>() -> ArgReg<'a, Num>182 pub(super) fn no_fd<'a, Num: ArgNumber>() -> ArgReg<'a, Num> {
183     pass_usize(!0_usize)
184 }
185 
186 #[inline]
slice_just_addr<T: Sized, Num: ArgNumber>(v: &[T]) -> ArgReg<Num>187 pub(super) fn slice_just_addr<T: Sized, Num: ArgNumber>(v: &[T]) -> ArgReg<Num> {
188     let mut_ptr = v.as_ptr() as *mut T;
189     raw_arg(mut_ptr.cast())
190 }
191 
192 #[inline]
slice<T: Sized, Num0: ArgNumber, Num1: ArgNumber>( v: &[T], ) -> (ArgReg<Num0>, ArgReg<Num1>)193 pub(super) fn slice<T: Sized, Num0: ArgNumber, Num1: ArgNumber>(
194     v: &[T],
195 ) -> (ArgReg<Num0>, ArgReg<Num1>) {
196     (slice_just_addr(v), pass_usize(v.len()))
197 }
198 
199 #[inline]
slice_mut<T: Sized, Num0: ArgNumber, Num1: ArgNumber>( v: &mut [T], ) -> (ArgReg<Num0>, ArgReg<Num1>)200 pub(super) fn slice_mut<T: Sized, Num0: ArgNumber, Num1: ArgNumber>(
201     v: &mut [T],
202 ) -> (ArgReg<Num0>, ArgReg<Num1>) {
203     (raw_arg(v.as_mut_ptr().cast()), pass_usize(v.len()))
204 }
205 
206 #[inline]
by_ref<T: Sized, Num: ArgNumber>(t: &T) -> ArgReg<Num>207 pub(super) fn by_ref<T: Sized, Num: ArgNumber>(t: &T) -> ArgReg<Num> {
208     let mut_ptr = as_ptr(t) as *mut T;
209     raw_arg(mut_ptr.cast())
210 }
211 
212 #[inline]
by_mut<T: Sized, Num: ArgNumber>(t: &mut T) -> ArgReg<Num>213 pub(super) fn by_mut<T: Sized, Num: ArgNumber>(t: &mut T) -> ArgReg<Num> {
214     raw_arg(as_mut_ptr(t).cast())
215 }
216 
217 /// Convert an optional mutable reference into a `usize` for passing to a
218 /// syscall.
219 #[inline]
opt_mut<T: Sized, Num: ArgNumber>(t: Option<&mut T>) -> ArgReg<Num>220 pub(super) fn opt_mut<T: Sized, Num: ArgNumber>(t: Option<&mut T>) -> ArgReg<Num> {
221     // This optimizes into the equivalent of `transmute(t)`, and has the
222     // advantage of not requiring `unsafe`.
223     match t {
224         Some(t) => by_mut(t),
225         None => raw_arg(null_mut()),
226     }
227 }
228 
229 /// Convert an optional immutable reference into a `usize` for passing to a
230 /// syscall.
231 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
232 #[inline]
opt_ref<T: Sized, Num: ArgNumber>(t: Option<&T>) -> ArgReg<Num>233 pub(super) fn opt_ref<T: Sized, Num: ArgNumber>(t: Option<&T>) -> ArgReg<Num> {
234     // This optimizes into the equivalent of `transmute(t)`, and has the
235     // advantage of not requiring `unsafe`.
236     match t {
237         Some(t) => by_ref(t),
238         None => raw_arg(null_mut()),
239     }
240 }
241 
242 /// Convert a `c_int` into an `ArgReg`.
243 ///
244 /// Be sure to use `raw_fd` to pass `RawFd` values.
245 #[inline]
c_int<'a, Num: ArgNumber>(i: c::c_int) -> ArgReg<'a, Num>246 pub(super) fn c_int<'a, Num: ArgNumber>(i: c::c_int) -> ArgReg<'a, Num> {
247     pass_usize(i as usize)
248 }
249 
250 /// Convert a `c_uint` into an `ArgReg`.
251 #[inline]
c_uint<'a, Num: ArgNumber>(i: c::c_uint) -> ArgReg<'a, Num>252 pub(super) fn c_uint<'a, Num: ArgNumber>(i: c::c_uint) -> ArgReg<'a, Num> {
253     pass_usize(i as usize)
254 }
255 
256 #[cfg(target_pointer_width = "64")]
257 #[inline]
loff_t<'a, Num: ArgNumber>(i: __kernel_loff_t) -> ArgReg<'a, Num>258 pub(super) fn loff_t<'a, Num: ArgNumber>(i: __kernel_loff_t) -> ArgReg<'a, Num> {
259     pass_usize(i as usize)
260 }
261 
262 #[cfg(target_pointer_width = "64")]
263 #[inline]
loff_t_from_u64<'a, Num: ArgNumber>(i: u64) -> ArgReg<'a, Num>264 pub(super) fn loff_t_from_u64<'a, Num: ArgNumber>(i: u64) -> ArgReg<'a, Num> {
265     // `loff_t` is signed, but syscalls which expect `loff_t` return `EINVAL`
266     // if it's outside the signed `i64` range, so we can silently cast.
267     pass_usize(i as usize)
268 }
269 
270 #[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
271 impl<'a, Num: ArgNumber> From<ClockId> for ArgReg<'a, Num> {
272     #[inline]
from(i: ClockId) -> Self273     fn from(i: ClockId) -> Self {
274         pass_usize(i as __kernel_clockid_t as usize)
275     }
276 }
277 
278 #[cfg(feature = "time")]
279 impl<'a, Num: ArgNumber> From<TimerfdClockId> for ArgReg<'a, Num> {
280     #[inline]
from(i: TimerfdClockId) -> Self281     fn from(i: TimerfdClockId) -> Self {
282         pass_usize(i as __kernel_clockid_t as usize)
283     }
284 }
285 
286 #[cfg(feature = "net")]
287 #[inline]
socklen_t<'a, Num: ArgNumber>(i: socklen_t) -> ArgReg<'a, Num>288 pub(super) fn socklen_t<'a, Num: ArgNumber>(i: socklen_t) -> ArgReg<'a, Num> {
289     pass_usize(i as usize)
290 }
291 
292 #[cfg(feature = "fs")]
293 impl<'a, Num: ArgNumber> From<Mode> for ArgReg<'a, Num> {
294     #[inline]
from(mode: Mode) -> Self295     fn from(mode: Mode) -> Self {
296         pass_usize(mode.bits() as usize)
297     }
298 }
299 
300 #[cfg(feature = "fs")]
301 impl<'a, Num: ArgNumber> From<(Mode, FileType)> for ArgReg<'a, Num> {
302     #[inline]
from(pair: (Mode, FileType)) -> Self303     fn from(pair: (Mode, FileType)) -> Self {
304         pass_usize(pair.0.as_raw_mode() as usize | pair.1.as_raw_mode() as usize)
305     }
306 }
307 
308 #[cfg(feature = "fs")]
309 impl<'a, Num: ArgNumber> From<crate::fs::AtFlags> for ArgReg<'a, Num> {
310     #[inline]
from(flags: crate::fs::AtFlags) -> Self311     fn from(flags: crate::fs::AtFlags) -> Self {
312         c_uint(flags.bits())
313     }
314 }
315 
316 #[cfg(feature = "fs")]
317 impl<'a, Num: ArgNumber> From<crate::fs::MemfdFlags> for ArgReg<'a, Num> {
318     #[inline]
from(flags: crate::fs::MemfdFlags) -> Self319     fn from(flags: crate::fs::MemfdFlags) -> Self {
320         c_uint(flags.bits())
321     }
322 }
323 
324 #[cfg(feature = "fs")]
325 impl<'a, Num: ArgNumber> From<crate::fs::RenameFlags> for ArgReg<'a, Num> {
326     #[inline]
from(flags: crate::fs::RenameFlags) -> Self327     fn from(flags: crate::fs::RenameFlags) -> Self {
328         c_uint(flags.bits())
329     }
330 }
331 
332 #[cfg(feature = "fs")]
333 impl<'a, Num: ArgNumber> From<crate::fs::StatxFlags> for ArgReg<'a, Num> {
334     #[inline]
from(flags: crate::fs::StatxFlags) -> Self335     fn from(flags: crate::fs::StatxFlags) -> Self {
336         c_uint(flags.bits())
337     }
338 }
339 
340 impl<'a, Num: ArgNumber> From<crate::io::FdFlags> for ArgReg<'a, Num> {
341     #[inline]
from(flags: crate::io::FdFlags) -> Self342     fn from(flags: crate::io::FdFlags) -> Self {
343         c_uint(flags.bits())
344     }
345 }
346 
347 impl<'a, Num: ArgNumber> From<crate::io::PipeFlags> for ArgReg<'a, Num> {
348     #[inline]
from(flags: crate::io::PipeFlags) -> Self349     fn from(flags: crate::io::PipeFlags) -> Self {
350         c_uint(flags.bits())
351     }
352 }
353 
354 impl<'a, Num: ArgNumber> From<crate::io::DupFlags> for ArgReg<'a, Num> {
355     #[inline]
from(flags: crate::io::DupFlags) -> Self356     fn from(flags: crate::io::DupFlags) -> Self {
357         c_uint(flags.bits())
358     }
359 }
360 
361 impl<'a, Num: ArgNumber> From<crate::io::ReadWriteFlags> for ArgReg<'a, Num> {
362     #[inline]
from(flags: crate::io::ReadWriteFlags) -> Self363     fn from(flags: crate::io::ReadWriteFlags) -> Self {
364         c_uint(flags.bits())
365     }
366 }
367 
368 impl<'a, Num: ArgNumber> From<crate::io::EventfdFlags> for ArgReg<'a, Num> {
369     #[inline]
from(flags: crate::io::EventfdFlags) -> Self370     fn from(flags: crate::io::EventfdFlags) -> Self {
371         c_uint(flags.bits())
372     }
373 }
374 
375 impl<'a, Num: ArgNumber> From<crate::io::epoll::CreateFlags> for ArgReg<'a, Num> {
376     #[inline]
from(flags: crate::io::epoll::CreateFlags) -> Self377     fn from(flags: crate::io::epoll::CreateFlags) -> Self {
378         c_uint(flags.bits())
379     }
380 }
381 
382 #[cfg(feature = "mm")]
383 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::ProtFlags> for ArgReg<'a, Num> {
384     #[inline]
from(flags: crate::backend::mm::types::ProtFlags) -> Self385     fn from(flags: crate::backend::mm::types::ProtFlags) -> Self {
386         c_uint(flags.bits())
387     }
388 }
389 
390 #[cfg(feature = "mm")]
391 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MsyncFlags> for ArgReg<'a, Num> {
392     #[inline]
from(flags: crate::backend::mm::types::MsyncFlags) -> Self393     fn from(flags: crate::backend::mm::types::MsyncFlags) -> Self {
394         c_uint(flags.bits())
395     }
396 }
397 
398 #[cfg(feature = "mm")]
399 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MremapFlags> for ArgReg<'a, Num> {
400     #[inline]
from(flags: crate::backend::mm::types::MremapFlags) -> Self401     fn from(flags: crate::backend::mm::types::MremapFlags) -> Self {
402         c_uint(flags.bits())
403     }
404 }
405 
406 #[cfg(feature = "mm")]
407 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MlockFlags> for ArgReg<'a, Num> {
408     #[inline]
from(flags: crate::backend::mm::types::MlockFlags) -> Self409     fn from(flags: crate::backend::mm::types::MlockFlags) -> Self {
410         c_uint(flags.bits())
411     }
412 }
413 
414 #[cfg(feature = "mm")]
415 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MapFlags> for ArgReg<'a, Num> {
416     #[inline]
from(flags: crate::backend::mm::types::MapFlags) -> Self417     fn from(flags: crate::backend::mm::types::MapFlags) -> Self {
418         c_uint(flags.bits())
419     }
420 }
421 
422 #[cfg(feature = "mm")]
423 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MprotectFlags> for ArgReg<'a, Num> {
424     #[inline]
from(flags: crate::backend::mm::types::MprotectFlags) -> Self425     fn from(flags: crate::backend::mm::types::MprotectFlags) -> Self {
426         c_uint(flags.bits())
427     }
428 }
429 
430 #[cfg(feature = "mm")]
431 impl<'a, Num: ArgNumber> From<crate::backend::mm::types::UserfaultfdFlags> for ArgReg<'a, Num> {
432     #[inline]
from(flags: crate::backend::mm::types::UserfaultfdFlags) -> Self433     fn from(flags: crate::backend::mm::types::UserfaultfdFlags) -> Self {
434         c_uint(flags.bits())
435     }
436 }
437 
438 impl<'a, Num: ArgNumber> From<crate::backend::process::types::MembarrierCommand>
439     for ArgReg<'a, Num>
440 {
441     #[inline]
from(cmd: crate::backend::process::types::MembarrierCommand) -> Self442     fn from(cmd: crate::backend::process::types::MembarrierCommand) -> Self {
443         c_uint(cmd as u32)
444     }
445 }
446 
447 impl<'a, Num: ArgNumber> From<crate::process::Cpuid> for ArgReg<'a, Num> {
448     #[inline]
from(cpuid: crate::process::Cpuid) -> Self449     fn from(cpuid: crate::process::Cpuid) -> Self {
450         c_uint(cpuid.as_raw())
451     }
452 }
453 
454 #[cfg(target_pointer_width = "64")]
455 #[inline]
dev_t<'a, Num: ArgNumber>(dev: u64) -> ArgReg<'a, Num>456 pub(super) fn dev_t<'a, Num: ArgNumber>(dev: u64) -> ArgReg<'a, Num> {
457     pass_usize(dev as usize)
458 }
459 
460 #[cfg(target_pointer_width = "32")]
461 #[inline]
dev_t<'a, Num: ArgNumber>(dev: u64) -> io::Result<ArgReg<'a, Num>>462 pub(super) fn dev_t<'a, Num: ArgNumber>(dev: u64) -> io::Result<ArgReg<'a, Num>> {
463     use core::convert::TryInto;
464     Ok(pass_usize(dev.try_into().map_err(|_err| io::Errno::INVAL)?))
465 }
466 
467 #[cfg(target_pointer_width = "32")]
468 #[cfg(feature = "fs")]
469 #[inline]
oflags_bits(oflags: OFlags) -> c::c_uint470 fn oflags_bits(oflags: OFlags) -> c::c_uint {
471     let mut bits = oflags.bits();
472     // Add `O_LARGEFILE`, unless `O_PATH` is set, as Linux returns `EINVAL`
473     // when both are set.
474     if !oflags.contains(OFlags::PATH) {
475         bits |= O_LARGEFILE;
476     }
477     bits
478 }
479 
480 #[cfg(target_pointer_width = "64")]
481 #[cfg(feature = "fs")]
482 #[inline]
oflags_bits(oflags: OFlags) -> c::c_uint483 const fn oflags_bits(oflags: OFlags) -> c::c_uint {
484     oflags.bits()
485 }
486 
487 #[cfg(feature = "fs")]
488 impl<'a, Num: ArgNumber> From<OFlags> for ArgReg<'a, Num> {
489     #[inline]
from(oflags: OFlags) -> Self490     fn from(oflags: OFlags) -> Self {
491         pass_usize(oflags_bits(oflags) as usize)
492     }
493 }
494 
495 /// Convert an `OFlags` into a `u64` for use in the `open_how` struct.
496 #[cfg(feature = "fs")]
497 #[inline]
oflags_for_open_how(oflags: OFlags) -> u64498 pub(super) fn oflags_for_open_how(oflags: OFlags) -> u64 {
499     u64::from(oflags_bits(oflags))
500 }
501 
502 #[cfg(feature = "fs")]
503 impl<'a, Num: ArgNumber> From<crate::fs::FallocateFlags> for ArgReg<'a, Num> {
504     #[inline]
from(flags: crate::fs::FallocateFlags) -> Self505     fn from(flags: crate::fs::FallocateFlags) -> Self {
506         c_uint(flags.bits())
507     }
508 }
509 
510 /// Convert a `Resource` into a syscall argument.
511 impl<'a, Num: ArgNumber> From<Resource> for ArgReg<'a, Num> {
512     #[inline]
from(resource: Resource) -> Self513     fn from(resource: Resource) -> Self {
514         c_uint(resource as c::c_uint)
515     }
516 }
517 
518 impl<'a, Num: ArgNumber> From<Pid> for ArgReg<'a, Num> {
519     #[inline]
from(pid: Pid) -> Self520     fn from(pid: Pid) -> Self {
521         pass_usize(pid.as_raw_nonzero().get() as usize)
522     }
523 }
524 
525 #[inline]
negative_pid<'a, Num: ArgNumber>(pid: Pid) -> ArgReg<'a, Num>526 pub(super) fn negative_pid<'a, Num: ArgNumber>(pid: Pid) -> ArgReg<'a, Num> {
527     pass_usize(pid.as_raw_nonzero().get().wrapping_neg() as usize)
528 }
529 
530 impl<'a, Num: ArgNumber> From<Signal> for ArgReg<'a, Num> {
531     #[inline]
from(sig: Signal) -> Self532     fn from(sig: Signal) -> Self {
533         pass_usize(sig as usize)
534     }
535 }
536 
537 #[cfg(feature = "fs")]
538 impl<'a, Num: ArgNumber> From<crate::fs::Advice> for ArgReg<'a, Num> {
539     #[inline]
from(advice: crate::fs::Advice) -> Self540     fn from(advice: crate::fs::Advice) -> Self {
541         c_uint(advice as c::c_uint)
542     }
543 }
544 
545 #[cfg(feature = "fs")]
546 impl<'a, Num: ArgNumber> From<crate::fs::SealFlags> for ArgReg<'a, Num> {
547     #[inline]
from(flags: crate::fs::SealFlags) -> Self548     fn from(flags: crate::fs::SealFlags) -> Self {
549         c_uint(flags.bits())
550     }
551 }
552 
553 #[cfg(feature = "io_uring")]
554 impl<'a, Num: ArgNumber> From<crate::io_uring::IoringEnterFlags> for ArgReg<'a, Num> {
555     #[inline]
from(flags: crate::io_uring::IoringEnterFlags) -> Self556     fn from(flags: crate::io_uring::IoringEnterFlags) -> Self {
557         c_uint(flags.bits())
558     }
559 }
560 
561 #[cfg(feature = "time")]
562 impl<'a, Num: ArgNumber> From<crate::time::TimerfdFlags> for ArgReg<'a, Num> {
563     #[inline]
from(flags: crate::time::TimerfdFlags) -> Self564     fn from(flags: crate::time::TimerfdFlags) -> Self {
565         c_uint(flags.bits())
566     }
567 }
568 
569 #[cfg(feature = "time")]
570 impl<'a, Num: ArgNumber> From<crate::time::TimerfdTimerFlags> for ArgReg<'a, Num> {
571     #[inline]
from(flags: crate::time::TimerfdTimerFlags) -> Self572     fn from(flags: crate::time::TimerfdTimerFlags) -> Self {
573         c_uint(flags.bits())
574     }
575 }
576 
577 #[cfg(feature = "rand")]
578 impl<'a, Num: ArgNumber> From<crate::rand::GetRandomFlags> for ArgReg<'a, Num> {
579     #[inline]
from(flags: crate::rand::GetRandomFlags) -> Self580     fn from(flags: crate::rand::GetRandomFlags) -> Self {
581         c_uint(flags.bits())
582     }
583 }
584 
585 #[cfg(feature = "net")]
586 impl<'a, Num: ArgNumber> From<crate::net::RecvFlags> for ArgReg<'a, Num> {
587     #[inline]
from(flags: crate::net::RecvFlags) -> Self588     fn from(flags: crate::net::RecvFlags) -> Self {
589         c_uint(flags.bits())
590     }
591 }
592 
593 #[cfg(feature = "net")]
594 impl<'a, Num: ArgNumber> From<crate::net::SendFlags> for ArgReg<'a, Num> {
595     #[inline]
from(flags: crate::net::SendFlags) -> Self596     fn from(flags: crate::net::SendFlags) -> Self {
597         c_uint(flags.bits())
598     }
599 }
600 
601 #[cfg(feature = "net")]
602 impl<'a, Num: ArgNumber> From<crate::net::AcceptFlags> for ArgReg<'a, Num> {
603     #[inline]
from(flags: crate::net::AcceptFlags) -> Self604     fn from(flags: crate::net::AcceptFlags) -> Self {
605         c_uint(flags.bits())
606     }
607 }
608 
609 #[cfg(feature = "net")]
610 impl<'a, Num: ArgNumber> From<crate::net::AddressFamily> for ArgReg<'a, Num> {
611     #[inline]
from(family: crate::net::AddressFamily) -> Self612     fn from(family: crate::net::AddressFamily) -> Self {
613         c_uint(family.0.into())
614     }
615 }
616 
617 #[cfg(feature = "net")]
618 impl<'a, Num: ArgNumber> From<(crate::net::SocketType, crate::net::SocketFlags)>
619     for ArgReg<'a, Num>
620 {
621     #[inline]
from(pair: (crate::net::SocketType, crate::net::SocketFlags)) -> Self622     fn from(pair: (crate::net::SocketType, crate::net::SocketFlags)) -> Self {
623         c_uint(pair.0 .0 | pair.1.bits())
624     }
625 }
626 
627 #[cfg(feature = "thread")]
628 impl<'a, Num: ArgNumber> From<(crate::thread::FutexOperation, crate::thread::FutexFlags)>
629     for ArgReg<'a, Num>
630 {
631     #[inline]
from(pair: (crate::thread::FutexOperation, crate::thread::FutexFlags)) -> Self632     fn from(pair: (crate::thread::FutexOperation, crate::thread::FutexFlags)) -> Self {
633         c_uint(pair.0 as u32 | pair.1.bits())
634     }
635 }
636 
637 #[cfg(feature = "fs")]
638 impl<'a, Num: ArgNumber> From<crate::fs::Access> for ArgReg<'a, Num> {
639     #[inline]
from(access: crate::fs::Access) -> Self640     fn from(access: crate::fs::Access) -> Self {
641         c_uint(access.bits())
642     }
643 }
644 
645 #[cfg(feature = "net")]
646 impl<'a, Num: ArgNumber> From<crate::net::SocketType> for ArgReg<'a, Num> {
647     #[inline]
from(type_: crate::net::SocketType) -> Self648     fn from(type_: crate::net::SocketType) -> Self {
649         c_uint(type_.0)
650     }
651 }
652 
653 #[cfg(feature = "net")]
654 impl<'a, Num: ArgNumber> From<crate::net::Protocol> for ArgReg<'a, Num> {
655     #[inline]
from(protocol: crate::net::Protocol) -> Self656     fn from(protocol: crate::net::Protocol) -> Self {
657         c_uint(protocol.0)
658     }
659 }
660 
661 impl<'a, Num: ArgNumber, T> From<&'a mut MaybeUninit<T>> for ArgReg<'a, Num> {
662     #[inline]
from(t: &'a mut MaybeUninit<T>) -> Self663     fn from(t: &'a mut MaybeUninit<T>) -> Self {
664         raw_arg(t.as_mut_ptr().cast())
665     }
666 }
667 
668 #[cfg(feature = "fs")]
669 #[cfg(any(target_os = "android", target_os = "linux"))]
670 impl<'a, Num: ArgNumber> From<crate::backend::fs::types::MountFlagsArg> for ArgReg<'a, Num> {
671     #[inline]
from(flags: crate::backend::fs::types::MountFlagsArg) -> Self672     fn from(flags: crate::backend::fs::types::MountFlagsArg) -> Self {
673         c_uint(flags.0)
674     }
675 }
676 
677 /// Convert a `usize` returned from a syscall that effectively returns `()` on
678 /// success.
679 ///
680 /// # Safety
681 ///
682 /// The caller must ensure that this is the return value of a syscall which
683 /// just returns 0 on success.
684 #[inline]
ret(raw: RetReg<R0>) -> io::Result<()>685 pub(super) unsafe fn ret(raw: RetReg<R0>) -> io::Result<()> {
686     try_decode_void(raw)
687 }
688 
689 /// Convert a `usize` returned from a syscall that doesn't return on success.
690 ///
691 /// # Safety
692 ///
693 /// The caller must ensure that this is the return value of a syscall which
694 /// doesn't return on success.
695 #[cfg(feature = "runtime")]
696 #[inline]
ret_error(raw: RetReg<R0>) -> io::Errno697 pub(super) unsafe fn ret_error(raw: RetReg<R0>) -> io::Errno {
698     try_decode_error(raw)
699 }
700 
701 /// Convert a `usize` returned from a syscall that effectively always returns
702 /// `()`.
703 ///
704 /// # Safety
705 ///
706 /// The caller must ensure that this is the return value of a syscall which
707 /// always returns `()`.
708 #[inline]
ret_infallible(raw: RetReg<R0>)709 pub(super) unsafe fn ret_infallible(raw: RetReg<R0>) {
710     #[cfg(debug_assertions)]
711     {
712         try_decode_void(raw).unwrap()
713     }
714     #[cfg(not(debug_assertions))]
715     drop(raw);
716 }
717 
718 /// Convert a `usize` returned from a syscall that effectively returns a
719 /// `c_int` on success.
720 #[inline]
ret_c_int(raw: RetReg<R0>) -> io::Result<c::c_int>721 pub(super) fn ret_c_int(raw: RetReg<R0>) -> io::Result<c::c_int> {
722     try_decode_c_int(raw)
723 }
724 
725 /// Convert a `usize` returned from a syscall that effectively returns a
726 /// `c_uint` on success.
727 #[inline]
ret_c_uint(raw: RetReg<R0>) -> io::Result<c::c_uint>728 pub(super) fn ret_c_uint(raw: RetReg<R0>) -> io::Result<c::c_uint> {
729     try_decode_c_uint(raw)
730 }
731 
732 /// Convert a `usize` returned from a syscall that effectively returns a `u64`
733 /// on success.
734 #[cfg(target_pointer_width = "64")]
735 #[inline]
ret_u64(raw: RetReg<R0>) -> io::Result<u64>736 pub(super) fn ret_u64(raw: RetReg<R0>) -> io::Result<u64> {
737     try_decode_u64(raw)
738 }
739 
740 /// Convert a `usize` returned from a syscall that effectively returns a
741 /// `usize` on success.
742 #[inline]
ret_usize(raw: RetReg<R0>) -> io::Result<usize>743 pub(super) fn ret_usize(raw: RetReg<R0>) -> io::Result<usize> {
744     try_decode_usize(raw)
745 }
746 
747 /// Convert a `usize` returned from a syscall that effectively always
748 /// returns a `usize`.
749 ///
750 /// # Safety
751 ///
752 /// This function must only be used with return values from infallible
753 /// syscalls.
754 #[inline]
ret_usize_infallible(raw: RetReg<R0>) -> usize755 pub(super) unsafe fn ret_usize_infallible(raw: RetReg<R0>) -> usize {
756     #[cfg(debug_assertions)]
757     {
758         try_decode_usize(raw).unwrap()
759     }
760     #[cfg(not(debug_assertions))]
761     {
762         decode_usize_infallible(raw)
763     }
764 }
765 
766 /// Convert a `usize` returned from a syscall that effectively returns an
767 /// `OwnedFd` on success.
768 ///
769 /// # Safety
770 ///
771 /// The caller must ensure that this is the return value of a syscall which
772 /// returns an owned file descriptor.
773 #[inline]
ret_owned_fd(raw: RetReg<R0>) -> io::Result<OwnedFd>774 pub(super) unsafe fn ret_owned_fd(raw: RetReg<R0>) -> io::Result<OwnedFd> {
775     let raw_fd = try_decode_raw_fd(raw)?;
776     Ok(crate::backend::fd::OwnedFd::from_raw_fd(raw_fd))
777 }
778 
779 /// Convert the return value of `dup2` and `dup3`.
780 ///
781 /// When these functions succeed, they return the same value as their second
782 /// argument, so we don't construct a new `OwnedFd`.
783 ///
784 /// # Safety
785 ///
786 /// The caller must ensure that this is the return value of a syscall which
787 /// returns a file descriptor.
788 #[inline]
ret_discarded_fd(raw: RetReg<R0>) -> io::Result<()>789 pub(super) unsafe fn ret_discarded_fd(raw: RetReg<R0>) -> io::Result<()> {
790     let _raw_fd = try_decode_raw_fd(raw)?;
791     Ok(())
792 }
793 
794 /// Convert a `usize` returned from a syscall that effectively returns a
795 /// `*mut c_void` on success.
796 #[inline]
ret_void_star(raw: RetReg<R0>) -> io::Result<*mut c::c_void>797 pub(super) fn ret_void_star(raw: RetReg<R0>) -> io::Result<*mut c::c_void> {
798     try_decode_void_star(raw)
799 }
800