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
16use super::c;
17use super::fd::{AsRawFd, BorrowedFd, FromRawFd, RawFd};
18#[cfg(feature = "runtime")]
19use super::io::errno::try_decode_error;
20#[cfg(target_pointer_width = "64")]
21use super::io::errno::try_decode_u64;
22#[cfg(not(debug_assertions))]
23use super::io::errno::{
24 decode_c_int_infallible, decode_c_uint_infallible, decode_usize_infallible,
25};
26use 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};
30use super::reg::{raw_arg, ArgNumber, ArgReg, RetReg, R0};
31#[cfg(feature = "time")]
32use super::time::types::TimerfdClockId;
33#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
34use crate::clockid::ClockId;
35use crate::fd::OwnedFd;
36use crate::ffi::CStr;
37use crate::io;
38#[cfg(any(feature = "process", feature = "runtime", feature = "termios"))]
39use crate::pid::Pid;
40#[cfg(feature = "process")]
41use crate::process::Resource;
42#[cfg(any(feature = "process", feature = "runtime"))]
43use crate::signal::Signal;
44use crate::utils::{as_mut_ptr, as_ptr};
45use core::mem::MaybeUninit;
46use core::ptr::null_mut;
47#[cfg(any(feature = "thread", feature = "time", target_arch = "x86"))]
48use linux_raw_sys::general::__kernel_clockid_t;
49#[cfg(target_pointer_width = "64")]
50use linux_raw_sys::general::__kernel_loff_t;
51#[cfg(feature = "net")]
52use linux_raw_sys::net::socklen_t;
53
54/// Convert `SYS_*` constants for socketcall.
55#[cfg(target_arch = "x86")]
56#[inline]
57pub(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]
65pub(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]
78pub(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]
89pub(super) fn zero<'a, Num: ArgNumber>() -> ArgReg<'a, Num> {
90 raw_arg(raw:null_mut())
91}
92
93/// Pass the `mem::size_of` of a type.
94#[inline]
95pub(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]
104pub(super) fn pass_usize<'a, Num: ArgNumber>(t: usize) -> ArgReg<'a, Num> {
105 raw_arg(raw:t as *mut _)
106}
107
108impl<'a, Num: ArgNumber, T> From<*mut T> for ArgReg<'a, Num> {
109 #[inline]
110 fn from(c: *mut T) -> ArgReg<'a, Num> {
111 raw_arg(raw:c.cast())
112 }
113}
114
115impl<'a, Num: ArgNumber, T> From<*const T> for ArgReg<'a, Num> {
116 #[inline]
117 fn from(c: *const T) -> ArgReg<'a, Num> {
118 let mut_ptr: *mut T = c as *mut T;
119 raw_arg(raw:mut_ptr.cast())
120 }
121}
122
123impl<'a, Num: ArgNumber> From<&'a CStr> for ArgReg<'a, Num> {
124 #[inline]
125 fn from(c: &'a CStr) -> Self {
126 let mut_ptr: *mut u8 = c.as_ptr() as *mut u8;
127 raw_arg(raw:mut_ptr.cast())
128 }
129}
130
131impl<'a, Num: ArgNumber> From<Option<&'a CStr>> for ArgReg<'a, Num> {
132 #[inline]
133 fn from(t: Option<&'a CStr>) -> Self {
134 raw_arg(raw:match t {
135 Some(s: &CStr) => {
136 let mut_ptr: *mut u8 = 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.
145impl<'a, Num: ArgNumber> From<BorrowedFd<'a>> for ArgReg<'a, Num> {
146 #[inline]
147 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]
162pub(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]
184pub(super) fn no_fd<'a, Num: ArgNumber>() -> ArgReg<'a, Num> {
185 pass_usize(!0_usize)
186}
187
188#[inline]
189pub(super) fn slice_just_addr<T: Sized, Num: ArgNumber>(v: &[T]) -> ArgReg<'_, Num> {
190 let mut_ptr: *mut T = v.as_ptr() as *mut T;
191 raw_arg(raw:mut_ptr.cast())
192}
193
194#[inline]
195pub(super) fn slice_just_addr_mut<T: Sized, Num: ArgNumber>(v: &mut [T]) -> ArgReg<'_, Num> {
196 raw_arg(raw:v.as_mut_ptr().cast())
197}
198
199#[inline]
200pub(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]
207pub(super) fn slice_mut<T: Sized, Num0: ArgNumber, Num1: ArgNumber>(
208 v: &mut [T],
209) -> (ArgReg<'_, Num0>, ArgReg<'_, Num1>) {
210 (raw_arg(raw:v.as_mut_ptr().cast()), pass_usize(v.len()))
211}
212
213#[inline]
214pub(super) fn by_ref<T: Sized, Num: ArgNumber>(t: &T) -> ArgReg<'_, Num> {
215 let mut_ptr: *mut T = as_ptr(t) as *mut T;
216 raw_arg(raw:mut_ptr.cast())
217}
218
219#[inline]
220pub(super) fn by_mut<T: Sized, Num: ArgNumber>(t: &mut T) -> ArgReg<'_, Num> {
221 raw_arg(raw:as_mut_ptr(t).cast())
222}
223
224/// Convert an optional mutable reference into a `usize` for passing to a
225/// syscall.
226#[inline]
227pub(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: &mut T) => by_mut(t),
232 None => raw_arg(raw: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]
240pub(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]
253pub(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]
259pub(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]
265pub(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]
271pub(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"))]
278impl<'a, Num: ArgNumber> From<ClockId> for ArgReg<'a, Num> {
279 #[inline]
280 fn from(i: ClockId) -> Self {
281 pass_usize(i as __kernel_clockid_t as usize)
282 }
283}
284
285#[cfg(feature = "time")]
286impl<'a, Num: ArgNumber> From<TimerfdClockId> for ArgReg<'a, Num> {
287 #[inline]
288 fn from(i: TimerfdClockId) -> Self {
289 pass_usize(i as __kernel_clockid_t as usize)
290 }
291}
292
293#[cfg(feature = "net")]
294#[inline]
295pub(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 = "runtime",
307 feature = "time",
308 target_arch = "x86",
309 )
310 )
311))]
312pub(crate) mod fs {
313 use super::*;
314 use crate::fs::{FileType, Mode, OFlags};
315 #[cfg(target_pointer_width = "32")]
316 use linux_raw_sys::general::O_LARGEFILE;
317
318 impl<'a, Num: ArgNumber> From<Mode> for ArgReg<'a, Num> {
319 #[inline]
320 fn from(mode: Mode) -> Self {
321 pass_usize(mode.bits() as usize)
322 }
323 }
324
325 impl<'a, Num: ArgNumber> From<(Mode, FileType)> for ArgReg<'a, Num> {
326 #[inline]
327 fn from(pair: (Mode, FileType)) -> Self {
328 pass_usize(pair.0.as_raw_mode() as usize | pair.1.as_raw_mode() as usize)
329 }
330 }
331
332 impl<'a, Num: ArgNumber> From<crate::fs::AtFlags> for ArgReg<'a, Num> {
333 #[inline]
334 fn from(flags: crate::fs::AtFlags) -> Self {
335 c_uint(flags.bits())
336 }
337 }
338
339 impl<'a, Num: ArgNumber> From<crate::fs::XattrFlags> for ArgReg<'a, Num> {
340 #[inline]
341 fn from(flags: crate::fs::XattrFlags) -> Self {
342 c_uint(flags.bits())
343 }
344 }
345
346 impl<'a, Num: ArgNumber> From<crate::fs::inotify::CreateFlags> for ArgReg<'a, Num> {
347 #[inline]
348 fn from(flags: crate::fs::inotify::CreateFlags) -> Self {
349 c_uint(flags.bits())
350 }
351 }
352
353 impl<'a, Num: ArgNumber> From<crate::fs::inotify::WatchFlags> for ArgReg<'a, Num> {
354 #[inline]
355 fn from(flags: crate::fs::inotify::WatchFlags) -> Self {
356 c_uint(flags.bits())
357 }
358 }
359
360 impl<'a, Num: ArgNumber> From<crate::fs::MemfdFlags> for ArgReg<'a, Num> {
361 #[inline]
362 fn from(flags: crate::fs::MemfdFlags) -> Self {
363 c_uint(flags.bits())
364 }
365 }
366
367 impl<'a, Num: ArgNumber> From<crate::fs::RenameFlags> for ArgReg<'a, Num> {
368 #[inline]
369 fn from(flags: crate::fs::RenameFlags) -> Self {
370 c_uint(flags.bits())
371 }
372 }
373
374 impl<'a, Num: ArgNumber> From<crate::fs::StatxFlags> for ArgReg<'a, Num> {
375 #[inline]
376 fn from(flags: crate::fs::StatxFlags) -> Self {
377 c_uint(flags.bits())
378 }
379 }
380
381 #[cfg(target_pointer_width = "32")]
382 #[inline]
383 fn oflags_bits(oflags: OFlags) -> c::c_uint {
384 let mut bits = oflags.bits();
385 // Add `O_LARGEFILE`, unless `O_PATH` is set, as Linux returns `EINVAL`
386 // when both are set.
387 if !oflags.contains(OFlags::PATH) {
388 bits |= O_LARGEFILE;
389 }
390 bits
391 }
392
393 #[cfg(target_pointer_width = "64")]
394 #[inline]
395 const fn oflags_bits(oflags: OFlags) -> c::c_uint {
396 oflags.bits()
397 }
398
399 impl<'a, Num: ArgNumber> From<OFlags> for ArgReg<'a, Num> {
400 #[inline]
401 fn from(oflags: OFlags) -> Self {
402 pass_usize(oflags_bits(oflags) as usize)
403 }
404 }
405
406 /// Convert an `OFlags` into a `u64` for use in the `open_how` struct.
407 #[inline]
408 pub(crate) fn oflags_for_open_how(oflags: OFlags) -> u64 {
409 u64::from(oflags_bits(oflags))
410 }
411
412 impl<'a, Num: ArgNumber> From<crate::fs::FallocateFlags> for ArgReg<'a, Num> {
413 #[inline]
414 fn from(flags: crate::fs::FallocateFlags) -> Self {
415 c_uint(flags.bits())
416 }
417 }
418
419 impl<'a, Num: ArgNumber> From<crate::fs::Advice> for ArgReg<'a, Num> {
420 #[inline]
421 fn from(advice: crate::fs::Advice) -> Self {
422 c_uint(advice as c::c_uint)
423 }
424 }
425
426 impl<'a, Num: ArgNumber> From<crate::fs::SealFlags> for ArgReg<'a, Num> {
427 #[inline]
428 fn from(flags: crate::fs::SealFlags) -> Self {
429 c_uint(flags.bits())
430 }
431 }
432
433 impl<'a, Num: ArgNumber> From<crate::fs::Access> for ArgReg<'a, Num> {
434 #[inline]
435 fn from(access: crate::fs::Access) -> Self {
436 c_uint(access.bits())
437 }
438 }
439}
440
441#[cfg(any(feature = "fs", feature = "mount"))]
442impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MountFlagsArg> for ArgReg<'a, Num> {
443 #[inline]
444 fn from(flags: crate::backend::mount::types::MountFlagsArg) -> Self {
445 c_uint(flags.0)
446 }
447}
448
449// When the deprecated "fs" aliases are removed, we can remove the "fs"
450// here too.
451#[cfg(any(feature = "fs", feature = "mount"))]
452impl<'a, Num: ArgNumber> From<crate::backend::mount::types::UnmountFlags> for ArgReg<'a, Num> {
453 #[inline]
454 fn from(flags: crate::backend::mount::types::UnmountFlags) -> Self {
455 c_uint(flags.bits())
456 }
457}
458
459#[cfg(feature = "mount")]
460impl<'a, Num: ArgNumber> From<crate::mount::FsConfigCmd> for ArgReg<'a, Num> {
461 #[inline]
462 fn from(cmd: crate::mount::FsConfigCmd) -> Self {
463 c_uint(cmd as c::c_uint)
464 }
465}
466
467#[cfg(feature = "mount")]
468impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsOpenFlags> for ArgReg<'a, Num> {
469 #[inline]
470 fn from(flags: crate::backend::mount::types::FsOpenFlags) -> Self {
471 c_uint(flags.bits())
472 }
473}
474
475#[cfg(feature = "mount")]
476impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsMountFlags> for ArgReg<'a, Num> {
477 #[inline]
478 fn from(flags: crate::backend::mount::types::FsMountFlags) -> Self {
479 c_uint(flags.bits())
480 }
481}
482
483#[cfg(feature = "mount")]
484impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MountAttrFlags> for ArgReg<'a, Num> {
485 #[inline]
486 fn from(flags: crate::backend::mount::types::MountAttrFlags) -> Self {
487 c_uint(flags.bits())
488 }
489}
490
491#[cfg(feature = "mount")]
492impl<'a, Num: ArgNumber> From<crate::backend::mount::types::OpenTreeFlags> for ArgReg<'a, Num> {
493 #[inline]
494 fn from(flags: crate::backend::mount::types::OpenTreeFlags) -> Self {
495 c_uint(flags.bits())
496 }
497}
498
499#[cfg(feature = "mount")]
500impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsPickFlags> for ArgReg<'a, Num> {
501 #[inline]
502 fn from(flags: crate::backend::mount::types::FsPickFlags) -> Self {
503 c_uint(flags.bits())
504 }
505}
506
507#[cfg(feature = "mount")]
508impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MoveMountFlags> for ArgReg<'a, Num> {
509 #[inline]
510 fn from(flags: crate::backend::mount::types::MoveMountFlags) -> Self {
511 c_uint(flags.bits())
512 }
513}
514
515impl<'a, Num: ArgNumber> From<crate::io::FdFlags> for ArgReg<'a, Num> {
516 #[inline]
517 fn from(flags: crate::io::FdFlags) -> Self {
518 c_uint(flags.bits())
519 }
520}
521
522#[cfg(feature = "pipe")]
523impl<'a, Num: ArgNumber> From<crate::pipe::PipeFlags> for ArgReg<'a, Num> {
524 #[inline]
525 fn from(flags: crate::pipe::PipeFlags) -> Self {
526 c_uint(flags.bits())
527 }
528}
529
530#[cfg(feature = "pipe")]
531impl<'a, Num: ArgNumber> From<crate::pipe::SpliceFlags> for ArgReg<'a, Num> {
532 #[inline]
533 fn from(flags: crate::pipe::SpliceFlags) -> Self {
534 c_uint(flags.bits())
535 }
536}
537
538impl<'a, Num: ArgNumber> From<crate::io::DupFlags> for ArgReg<'a, Num> {
539 #[inline]
540 fn from(flags: crate::io::DupFlags) -> Self {
541 c_uint(flags.bits())
542 }
543}
544
545impl<'a, Num: ArgNumber> From<crate::io::ReadWriteFlags> for ArgReg<'a, Num> {
546 #[inline]
547 fn from(flags: crate::io::ReadWriteFlags) -> Self {
548 c_uint(flags.bits())
549 }
550}
551
552#[cfg(feature = "process")]
553impl<'a, Num: ArgNumber> From<crate::process::PidfdFlags> for ArgReg<'a, Num> {
554 #[inline]
555 fn from(flags: crate::process::PidfdFlags) -> Self {
556 c_uint(flags.bits())
557 }
558}
559
560#[cfg(feature = "pty")]
561impl<'a, Num: ArgNumber> From<crate::pty::OpenptFlags> for ArgReg<'a, Num> {
562 #[inline]
563 fn from(flags: crate::pty::OpenptFlags) -> Self {
564 c_uint(flags.bits())
565 }
566}
567
568#[cfg(feature = "thread")]
569impl<'a, Num: ArgNumber> From<crate::thread::UnshareFlags> for ArgReg<'a, Num> {
570 #[inline]
571 fn from(flags: crate::thread::UnshareFlags) -> Self {
572 c_uint(flags.bits())
573 }
574}
575
576#[cfg(feature = "event")]
577impl<'a, Num: ArgNumber> From<crate::event::EventfdFlags> for ArgReg<'a, Num> {
578 #[inline]
579 fn from(flags: crate::event::EventfdFlags) -> Self {
580 c_uint(flags.bits())
581 }
582}
583
584#[cfg(feature = "event")]
585impl<'a, Num: ArgNumber> From<crate::event::epoll::CreateFlags> for ArgReg<'a, Num> {
586 #[inline]
587 fn from(flags: crate::event::epoll::CreateFlags) -> Self {
588 c_uint(flags.bits())
589 }
590}
591
592#[cfg(feature = "mm")]
593impl<'a, Num: ArgNumber> From<crate::backend::mm::types::ProtFlags> for ArgReg<'a, Num> {
594 #[inline]
595 fn from(flags: crate::backend::mm::types::ProtFlags) -> Self {
596 c_uint(flags.bits())
597 }
598}
599
600#[cfg(feature = "mm")]
601impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MsyncFlags> for ArgReg<'a, Num> {
602 #[inline]
603 fn from(flags: crate::backend::mm::types::MsyncFlags) -> Self {
604 c_uint(flags.bits())
605 }
606}
607
608#[cfg(feature = "mm")]
609impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MremapFlags> for ArgReg<'a, Num> {
610 #[inline]
611 fn from(flags: crate::backend::mm::types::MremapFlags) -> Self {
612 c_uint(flags.bits())
613 }
614}
615
616#[cfg(feature = "mm")]
617impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MlockFlags> for ArgReg<'a, Num> {
618 #[inline]
619 fn from(flags: crate::backend::mm::types::MlockFlags) -> Self {
620 c_uint(flags.bits())
621 }
622}
623
624#[cfg(feature = "mm")]
625#[cfg(any(linux_kernel, freebsdlike, netbsdlike))]
626impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MlockAllFlags> for ArgReg<'a, Num> {
627 #[inline]
628 fn from(flags: crate::backend::mm::types::MlockAllFlags) -> Self {
629 c_uint(flags.bits())
630 }
631}
632
633#[cfg(feature = "mm")]
634impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MapFlags> for ArgReg<'a, Num> {
635 #[inline]
636 fn from(flags: crate::backend::mm::types::MapFlags) -> Self {
637 c_uint(flags.bits())
638 }
639}
640
641#[cfg(feature = "mm")]
642impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MprotectFlags> for ArgReg<'a, Num> {
643 #[inline]
644 fn from(flags: crate::backend::mm::types::MprotectFlags) -> Self {
645 c_uint(flags.bits())
646 }
647}
648
649#[cfg(feature = "mm")]
650impl<'a, Num: ArgNumber> From<crate::backend::mm::types::UserfaultfdFlags> for ArgReg<'a, Num> {
651 #[inline]
652 fn from(flags: crate::backend::mm::types::UserfaultfdFlags) -> Self {
653 c_uint(flags.bits())
654 }
655}
656
657#[cfg(feature = "process")]
658impl<'a, Num: ArgNumber> From<crate::backend::process::types::MembarrierCommand>
659 for ArgReg<'a, Num>
660{
661 #[inline]
662 fn from(cmd: crate::backend::process::types::MembarrierCommand) -> Self {
663 c_uint(cmd as u32)
664 }
665}
666
667#[cfg(feature = "process")]
668impl<'a, Num: ArgNumber> From<crate::process::Cpuid> for ArgReg<'a, Num> {
669 #[inline]
670 fn from(cpuid: crate::process::Cpuid) -> Self {
671 c_uint(cpuid.as_raw())
672 }
673}
674
675#[cfg(target_pointer_width = "64")]
676#[inline]
677pub(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]
683pub(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")]
689impl<'a, Num: ArgNumber> From<Resource> for ArgReg<'a, Num> {
690 #[inline]
691 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"))]
697impl<'a, Num: ArgNumber> From<Pid> for ArgReg<'a, Num> {
698 #[inline]
699 fn from(pid: Pid) -> Self {
700 pass_usize(pid.as_raw_nonzero().get() as usize)
701 }
702}
703
704#[cfg(feature = "process")]
705#[inline]
706pub(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"))]
711impl<'a, Num: ArgNumber> From<Signal> for ArgReg<'a, Num> {
712 #[inline]
713 fn from(sig: Signal) -> Self {
714 pass_usize(sig as usize)
715 }
716}
717
718#[cfg(feature = "io_uring")]
719impl<'a, Num: ArgNumber> From<crate::io_uring::IoringEnterFlags> for ArgReg<'a, Num> {
720 #[inline]
721 fn from(flags: crate::io_uring::IoringEnterFlags) -> Self {
722 c_uint(flags.bits())
723 }
724}
725
726#[cfg(feature = "time")]
727impl<'a, Num: ArgNumber> From<crate::time::TimerfdFlags> for ArgReg<'a, Num> {
728 #[inline]
729 fn from(flags: crate::time::TimerfdFlags) -> Self {
730 c_uint(flags.bits())
731 }
732}
733
734#[cfg(feature = "time")]
735impl<'a, Num: ArgNumber> From<crate::time::TimerfdTimerFlags> for ArgReg<'a, Num> {
736 #[inline]
737 fn from(flags: crate::time::TimerfdTimerFlags) -> Self {
738 c_uint(flags.bits())
739 }
740}
741
742#[cfg(feature = "rand")]
743impl<'a, Num: ArgNumber> From<crate::rand::GetRandomFlags> for ArgReg<'a, Num> {
744 #[inline]
745 fn from(flags: crate::rand::GetRandomFlags) -> Self {
746 c_uint(flags.bits())
747 }
748}
749
750#[cfg(feature = "net")]
751impl<'a, Num: ArgNumber> From<crate::net::RecvFlags> for ArgReg<'a, Num> {
752 #[inline]
753 fn from(flags: crate::net::RecvFlags) -> Self {
754 c_uint(flags.bits())
755 }
756}
757
758#[cfg(feature = "net")]
759impl<'a, Num: ArgNumber> From<crate::net::SendFlags> for ArgReg<'a, Num> {
760 #[inline]
761 fn from(flags: crate::net::SendFlags) -> Self {
762 c_uint(flags.bits())
763 }
764}
765
766#[cfg(feature = "net")]
767impl<'a, Num: ArgNumber> From<crate::net::SocketFlags> for ArgReg<'a, Num> {
768 #[inline]
769 fn from(flags: crate::net::SocketFlags) -> Self {
770 c_uint(flags.bits())
771 }
772}
773
774#[cfg(feature = "net")]
775impl<'a, Num: ArgNumber> From<crate::net::AddressFamily> for ArgReg<'a, Num> {
776 #[inline]
777 fn from(family: crate::net::AddressFamily) -> Self {
778 c_uint(family.0.into())
779 }
780}
781
782#[cfg(feature = "net")]
783impl<'a, Num: ArgNumber> From<(crate::net::SocketType, crate::net::SocketFlags)>
784 for ArgReg<'a, Num>
785{
786 #[inline]
787 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")]
793impl<'a, Num: ArgNumber> From<(crate::thread::FutexOperation, crate::thread::FutexFlags)>
794 for ArgReg<'a, Num>
795{
796 #[inline]
797 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")]
803impl<'a, Num: ArgNumber> From<crate::net::SocketType> for ArgReg<'a, Num> {
804 #[inline]
805 fn from(type_: crate::net::SocketType) -> Self {
806 c_uint(type_.0)
807 }
808}
809
810#[cfg(feature = "net")]
811impl<'a, Num: ArgNumber> From<Option<crate::net::Protocol>> for ArgReg<'a, Num> {
812 #[inline]
813 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
821impl<'a, Num: ArgNumber, T> From<&'a mut MaybeUninit<T>> for ArgReg<'a, Num> {
822 #[inline]
823 fn from(t: &'a mut MaybeUninit<T>) -> Self {
824 raw_arg(raw:t.as_mut_ptr().cast())
825 }
826}
827
828impl<'a, Num: ArgNumber, T> From<&'a mut [MaybeUninit<T>]> for ArgReg<'a, Num> {
829 #[inline]
830 fn from(t: &'a mut [MaybeUninit<T>]) -> Self {
831 raw_arg(raw:t.as_mut_ptr().cast())
832 }
833}
834
835#[cfg(any(feature = "process", feature = "thread"))]
836impl<'a, Num: ArgNumber> From<crate::ugid::Uid> for ArgReg<'a, Num> {
837 #[inline]
838 fn from(t: crate::ugid::Uid) -> Self {
839 c_uint(t.as_raw())
840 }
841}
842
843#[cfg(any(feature = "process", feature = "thread"))]
844impl<'a, Num: ArgNumber> From<crate::ugid::Gid> for ArgReg<'a, Num> {
845 #[inline]
846 fn from(t: crate::ugid::Gid) -> Self {
847 c_uint(t.as_raw())
848 }
849}
850
851#[cfg(feature = "runtime")]
852impl<'a, Num: ArgNumber> From<crate::runtime::How> for ArgReg<'a, Num> {
853 #[inline]
854 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]
867pub(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(feature = "runtime")]
878#[inline]
879pub(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]
891pub(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]
903pub(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]
910pub(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]
918pub(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]
925pub(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]
937pub(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]
956pub(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]
975pub(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]
994pub(super) unsafe fn ret_owned_fd(raw: RetReg<R0>) -> io::Result<OwnedFd> {
995 let raw_fd: i32 = 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]
1009pub(super) unsafe fn ret_discarded_fd(raw: RetReg<R0>) -> io::Result<()> {
1010 let _raw_fd: i32 = 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]
1017pub(super) fn ret_void_star(raw: RetReg<R0>) -> io::Result<*mut c::c_void> {
1018 try_decode_void_star(raw)
1019}
1020