rustix/backend/linux_raw/
conv.rs

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
16use super::c;
17use super::fd::{AsRawFd, BorrowedFd, FromRawFd, RawFd};
18#[cfg(any(feature = "event", feature = "runtime", feature = "system"))]
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(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(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) -> Self {
111        raw_arg(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) -> Self {
118        let mut_ptr = c as *mut T;
119        raw_arg(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 = c.as_ptr() as *mut u8;
127        raw_arg(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(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.
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 == crate::fs::ABS.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 = v.as_ptr() as *mut T;
191    raw_arg(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(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(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 = as_ptr(t) as *mut T;
216    raw_arg(mut_ptr.cast())
217}
218
219#[inline]
220pub(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]
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) => 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]
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 = "process",
307            feature = "runtime",
308            feature = "time",
309            target_arch = "x86",
310        )
311    )
312))]
313pub(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]
321        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]
328        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]
335        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]
342        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]
349        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]
356        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]
363        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]
370        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]
377        fn from(flags: crate::fs::StatxFlags) -> Self {
378            c_uint(flags.bits())
379        }
380    }
381
382    #[cfg(target_pointer_width = "32")]
383    #[inline]
384    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]
396    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]
402        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]
409    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]
415        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]
422        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]
429        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]
436        fn from(access: crate::fs::Access) -> Self {
437            c_uint(access.bits())
438        }
439    }
440}
441
442#[cfg(any(feature = "fs", feature = "mount"))]
443impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MountFlagsArg> for ArgReg<'a, Num> {
444    #[inline]
445    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"))]
453impl<'a, Num: ArgNumber> From<crate::backend::mount::types::UnmountFlags> for ArgReg<'a, Num> {
454    #[inline]
455    fn from(flags: crate::backend::mount::types::UnmountFlags) -> Self {
456        c_uint(flags.bits())
457    }
458}
459
460#[cfg(feature = "mount")]
461impl<'a, Num: ArgNumber> From<crate::mount::FsConfigCmd> for ArgReg<'a, Num> {
462    #[inline]
463    fn from(cmd: crate::mount::FsConfigCmd) -> Self {
464        c_uint(cmd as c::c_uint)
465    }
466}
467
468#[cfg(feature = "mount")]
469impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsOpenFlags> for ArgReg<'a, Num> {
470    #[inline]
471    fn from(flags: crate::backend::mount::types::FsOpenFlags) -> Self {
472        c_uint(flags.bits())
473    }
474}
475
476#[cfg(feature = "mount")]
477impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsMountFlags> for ArgReg<'a, Num> {
478    #[inline]
479    fn from(flags: crate::backend::mount::types::FsMountFlags) -> Self {
480        c_uint(flags.bits())
481    }
482}
483
484#[cfg(feature = "mount")]
485impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MountAttrFlags> for ArgReg<'a, Num> {
486    #[inline]
487    fn from(flags: crate::backend::mount::types::MountAttrFlags) -> Self {
488        c_uint(flags.bits())
489    }
490}
491
492#[cfg(feature = "mount")]
493impl<'a, Num: ArgNumber> From<crate::backend::mount::types::OpenTreeFlags> for ArgReg<'a, Num> {
494    #[inline]
495    fn from(flags: crate::backend::mount::types::OpenTreeFlags) -> Self {
496        c_uint(flags.bits())
497    }
498}
499
500#[cfg(feature = "mount")]
501impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsPickFlags> for ArgReg<'a, Num> {
502    #[inline]
503    fn from(flags: crate::backend::mount::types::FsPickFlags) -> Self {
504        c_uint(flags.bits())
505    }
506}
507
508#[cfg(feature = "mount")]
509impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MoveMountFlags> for ArgReg<'a, Num> {
510    #[inline]
511    fn from(flags: crate::backend::mount::types::MoveMountFlags) -> Self {
512        c_uint(flags.bits())
513    }
514}
515
516impl<'a, Num: ArgNumber> From<crate::io::FdFlags> for ArgReg<'a, Num> {
517    #[inline]
518    fn from(flags: crate::io::FdFlags) -> Self {
519        c_uint(flags.bits())
520    }
521}
522
523#[cfg(feature = "pipe")]
524impl<'a, Num: ArgNumber> From<crate::pipe::PipeFlags> for ArgReg<'a, Num> {
525    #[inline]
526    fn from(flags: crate::pipe::PipeFlags) -> Self {
527        c_uint(flags.bits())
528    }
529}
530
531#[cfg(feature = "pipe")]
532impl<'a, Num: ArgNumber> From<crate::pipe::SpliceFlags> for ArgReg<'a, Num> {
533    #[inline]
534    fn from(flags: crate::pipe::SpliceFlags) -> Self {
535        c_uint(flags.bits())
536    }
537}
538
539impl<'a, Num: ArgNumber> From<crate::io::DupFlags> for ArgReg<'a, Num> {
540    #[inline]
541    fn from(flags: crate::io::DupFlags) -> Self {
542        c_uint(flags.bits())
543    }
544}
545
546impl<'a, Num: ArgNumber> From<crate::io::ReadWriteFlags> for ArgReg<'a, Num> {
547    #[inline]
548    fn from(flags: crate::io::ReadWriteFlags) -> Self {
549        c_uint(flags.bits())
550    }
551}
552
553#[cfg(feature = "process")]
554impl<'a, Num: ArgNumber> From<crate::process::PidfdFlags> for ArgReg<'a, Num> {
555    #[inline]
556    fn from(flags: crate::process::PidfdFlags) -> Self {
557        c_uint(flags.bits())
558    }
559}
560
561#[cfg(feature = "pty")]
562impl<'a, Num: ArgNumber> From<crate::pty::OpenptFlags> for ArgReg<'a, Num> {
563    #[inline]
564    fn from(flags: crate::pty::OpenptFlags) -> Self {
565        c_uint(flags.bits())
566    }
567}
568
569#[cfg(feature = "thread")]
570impl<'a, Num: ArgNumber> From<crate::thread::UnshareFlags> for ArgReg<'a, Num> {
571    #[inline]
572    fn from(flags: crate::thread::UnshareFlags) -> Self {
573        c_uint(flags.bits())
574    }
575}
576
577#[cfg(feature = "event")]
578impl<'a, Num: ArgNumber> From<crate::event::EventfdFlags> for ArgReg<'a, Num> {
579    #[inline]
580    fn from(flags: crate::event::EventfdFlags) -> Self {
581        c_uint(flags.bits())
582    }
583}
584
585#[cfg(feature = "event")]
586impl<'a, Num: ArgNumber> From<crate::event::epoll::CreateFlags> for ArgReg<'a, Num> {
587    #[inline]
588    fn from(flags: crate::event::epoll::CreateFlags) -> Self {
589        c_uint(flags.bits())
590    }
591}
592
593#[cfg(feature = "mm")]
594impl<'a, Num: ArgNumber> From<crate::backend::mm::types::ProtFlags> for ArgReg<'a, Num> {
595    #[inline]
596    fn from(flags: crate::backend::mm::types::ProtFlags) -> Self {
597        c_uint(flags.bits())
598    }
599}
600
601#[cfg(feature = "mm")]
602impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MsyncFlags> for ArgReg<'a, Num> {
603    #[inline]
604    fn from(flags: crate::backend::mm::types::MsyncFlags) -> Self {
605        c_uint(flags.bits())
606    }
607}
608
609#[cfg(feature = "mm")]
610impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MremapFlags> for ArgReg<'a, Num> {
611    #[inline]
612    fn from(flags: crate::backend::mm::types::MremapFlags) -> Self {
613        c_uint(flags.bits())
614    }
615}
616
617#[cfg(feature = "mm")]
618impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MlockFlags> for ArgReg<'a, Num> {
619    #[inline]
620    fn from(flags: crate::backend::mm::types::MlockFlags) -> Self {
621        c_uint(flags.bits())
622    }
623}
624
625#[cfg(feature = "mm")]
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>
794    From<(
795        crate::backend::thread::futex::Operation,
796        crate::thread::futex::Flags,
797    )> for ArgReg<'a, Num>
798{
799    #[inline]
800    fn from(
801        pair: (
802            crate::backend::thread::futex::Operation,
803            crate::thread::futex::Flags,
804        ),
805    ) -> Self {
806        c_uint(pair.0 as u32 | pair.1.bits())
807    }
808}
809
810#[cfg(feature = "net")]
811impl<'a, Num: ArgNumber> From<crate::net::SocketType> for ArgReg<'a, Num> {
812    #[inline]
813    fn from(type_: crate::net::SocketType) -> Self {
814        c_uint(type_.0)
815    }
816}
817
818#[cfg(feature = "net")]
819impl<'a, Num: ArgNumber> From<Option<crate::net::Protocol>> for ArgReg<'a, Num> {
820    #[inline]
821    fn from(protocol: Option<crate::net::Protocol>) -> Self {
822        c_uint(match protocol {
823            Some(p) => p.0.get(),
824            None => 0,
825        })
826    }
827}
828
829impl<'a, Num: ArgNumber, T> From<&'a mut MaybeUninit<T>> for ArgReg<'a, Num> {
830    #[inline]
831    fn from(t: &'a mut MaybeUninit<T>) -> Self {
832        raw_arg(t.as_mut_ptr().cast())
833    }
834}
835
836impl<'a, Num: ArgNumber, T> From<&'a mut [MaybeUninit<T>]> for ArgReg<'a, Num> {
837    #[inline]
838    fn from(t: &'a mut [MaybeUninit<T>]) -> Self {
839        raw_arg(t.as_mut_ptr().cast())
840    }
841}
842
843#[cfg(any(feature = "process", feature = "thread"))]
844impl<'a, Num: ArgNumber> From<crate::ugid::Uid> for ArgReg<'a, Num> {
845    #[inline]
846    fn from(t: crate::ugid::Uid) -> Self {
847        c_uint(t.as_raw())
848    }
849}
850
851#[cfg(any(feature = "process", feature = "thread"))]
852impl<'a, Num: ArgNumber> From<crate::ugid::Gid> for ArgReg<'a, Num> {
853    #[inline]
854    fn from(t: crate::ugid::Gid) -> Self {
855        c_uint(t.as_raw())
856    }
857}
858
859#[cfg(feature = "runtime")]
860impl<'a, Num: ArgNumber> From<crate::runtime::How> for ArgReg<'a, Num> {
861    #[inline]
862    fn from(flags: crate::runtime::How) -> Self {
863        c_uint(flags as u32)
864    }
865}
866
867/// Convert a `usize` returned from a syscall that effectively returns `()` on
868/// success.
869///
870/// # Safety
871///
872/// The caller must ensure that this is the return value of a syscall which
873/// just returns 0 on success.
874#[inline]
875pub(super) unsafe fn ret(raw: RetReg<R0>) -> io::Result<()> {
876    try_decode_void(raw)
877}
878
879/// Convert a `usize` returned from a syscall that doesn't return on success.
880///
881/// # Safety
882///
883/// The caller must ensure that this is the return value of a syscall which
884/// doesn't return on success.
885#[cfg(any(feature = "event", feature = "runtime", feature = "system"))]
886#[inline]
887pub(super) unsafe fn ret_error(raw: RetReg<R0>) -> io::Errno {
888    try_decode_error(raw)
889}
890
891/// Convert a `usize` returned from a syscall that effectively always returns
892/// `()`.
893///
894/// # Safety
895///
896/// The caller must ensure that this is the return value of a syscall which
897/// always returns `()`.
898#[inline]
899pub(super) unsafe fn ret_infallible(raw: RetReg<R0>) {
900    #[cfg(debug_assertions)]
901    {
902        try_decode_void(raw).unwrap()
903    }
904    #[cfg(not(debug_assertions))]
905    drop(raw);
906}
907
908/// Convert a `usize` returned from a syscall that effectively returns a
909/// `c_int` on success.
910#[inline]
911pub(super) fn ret_c_int(raw: RetReg<R0>) -> io::Result<c::c_int> {
912    try_decode_c_int(raw)
913}
914
915/// Convert a `usize` returned from a syscall that effectively returns a
916/// `c_uint` on success.
917#[inline]
918pub(super) fn ret_c_uint(raw: RetReg<R0>) -> io::Result<c::c_uint> {
919    try_decode_c_uint(raw)
920}
921
922/// Convert a `usize` returned from a syscall that effectively returns a `u64`
923/// on success.
924#[cfg(target_pointer_width = "64")]
925#[inline]
926pub(super) fn ret_u64(raw: RetReg<R0>) -> io::Result<u64> {
927    try_decode_u64(raw)
928}
929
930/// Convert a `usize` returned from a syscall that effectively returns a
931/// `usize` on success.
932#[inline]
933pub(super) fn ret_usize(raw: RetReg<R0>) -> io::Result<usize> {
934    try_decode_usize(raw)
935}
936
937/// Convert a `usize` returned from a syscall that effectively always
938/// returns a `usize`.
939///
940/// # Safety
941///
942/// This function must only be used with return values from infallible
943/// syscalls.
944#[inline]
945pub(super) unsafe fn ret_usize_infallible(raw: RetReg<R0>) -> usize {
946    #[cfg(debug_assertions)]
947    {
948        try_decode_usize(raw).unwrap()
949    }
950    #[cfg(not(debug_assertions))]
951    {
952        decode_usize_infallible(raw)
953    }
954}
955
956/// Convert a `c_int` returned from a syscall that effectively always
957/// returns a `c_int`.
958///
959/// # Safety
960///
961/// This function must only be used with return values from infallible
962/// syscalls.
963#[inline]
964pub(super) unsafe fn ret_c_int_infallible(raw: RetReg<R0>) -> c::c_int {
965    #[cfg(debug_assertions)]
966    {
967        try_decode_c_int(raw).unwrap()
968    }
969    #[cfg(not(debug_assertions))]
970    {
971        decode_c_int_infallible(raw)
972    }
973}
974
975/// Convert a `c_uint` returned from a syscall that effectively always
976/// returns a `c_uint`.
977///
978/// # Safety
979///
980/// This function must only be used with return values from infallible
981/// syscalls.
982#[inline]
983pub(super) unsafe fn ret_c_uint_infallible(raw: RetReg<R0>) -> c::c_uint {
984    #[cfg(debug_assertions)]
985    {
986        try_decode_c_uint(raw).unwrap()
987    }
988    #[cfg(not(debug_assertions))]
989    {
990        decode_c_uint_infallible(raw)
991    }
992}
993
994/// Convert a `usize` returned from a syscall that effectively returns an
995/// `OwnedFd` on success.
996///
997/// # Safety
998///
999/// The caller must ensure that this is the return value of a syscall which
1000/// returns an owned file descriptor.
1001#[inline]
1002pub(super) unsafe fn ret_owned_fd(raw: RetReg<R0>) -> io::Result<OwnedFd> {
1003    let raw_fd = try_decode_raw_fd(raw)?;
1004    Ok(crate::backend::fd::OwnedFd::from_raw_fd(raw_fd))
1005}
1006
1007/// Convert the return value of `dup2` and `dup3`.
1008///
1009/// When these functions succeed, they return the same value as their second
1010/// argument, so we don't construct a new `OwnedFd`.
1011///
1012/// # Safety
1013///
1014/// The caller must ensure that this is the return value of a syscall which
1015/// returns a file descriptor.
1016#[inline]
1017pub(super) unsafe fn ret_discarded_fd(raw: RetReg<R0>) -> io::Result<()> {
1018    let _raw_fd = try_decode_raw_fd(raw)?;
1019    Ok(())
1020}
1021
1022/// Convert a `usize` returned from a syscall that effectively returns a
1023/// `*mut c_void` on success.
1024#[inline]
1025pub(super) fn ret_void_star(raw: RetReg<R0>) -> io::Result<*mut c::c_void> {
1026    try_decode_void_star(raw)
1027}