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 as _, BorrowedFd, FromRawFd as _, 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"))]
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"))]
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 `IORING_REGISTER_FILES_SKIP` sentry value this way.
168    #[cfg(feature = "io_uring")]
169    debug_assert_ne!(fd, crate::io_uring::IORING_REGISTER_FILES_SKIP.as_raw_fd());
170
171    // Linux doesn't look at the high bits beyond the `c_int`, so use
172    // zero-extension rather than sign-extension because it's a smaller
173    // instruction.
174    let fd: c::c_int = fd;
175    pass_usize(fd as c::c_uint as usize)
176}
177
178/// Deliberately pass `-1` to a file-descriptor argument, for system calls
179/// like `mmap` where this indicates the argument is omitted.
180#[inline]
181pub(super) fn no_fd<'a, Num: ArgNumber>() -> ArgReg<'a, Num> {
182    pass_usize(!0_usize)
183}
184
185#[inline]
186pub(super) fn slice_just_addr<T: Sized, Num: ArgNumber>(v: &[T]) -> ArgReg<'_, Num> {
187    let mut_ptr = v.as_ptr() as *mut T;
188    raw_arg(mut_ptr.cast())
189}
190
191#[inline]
192pub(super) fn slice_just_addr_mut<T: Sized, Num: ArgNumber>(v: &mut [T]) -> ArgReg<'_, Num> {
193    raw_arg(v.as_mut_ptr().cast())
194}
195
196#[inline]
197pub(super) fn slice<T: Sized, Num0: ArgNumber, Num1: ArgNumber>(
198    v: &[T],
199) -> (ArgReg<'_, Num0>, ArgReg<'_, Num1>) {
200    (slice_just_addr(v), pass_usize(v.len()))
201}
202
203#[inline]
204pub(super) fn slice_mut<T: Sized, Num0: ArgNumber, Num1: ArgNumber>(
205    v: &mut [T],
206) -> (ArgReg<'_, Num0>, ArgReg<'_, Num1>) {
207    (raw_arg(v.as_mut_ptr().cast()), pass_usize(v.len()))
208}
209
210#[inline]
211pub(super) fn by_ref<T: Sized, Num: ArgNumber>(t: &T) -> ArgReg<'_, Num> {
212    let mut_ptr = as_ptr(t) as *mut T;
213    raw_arg(mut_ptr.cast())
214}
215
216#[inline]
217pub(super) fn by_mut<T: Sized, Num: ArgNumber>(t: &mut T) -> ArgReg<'_, Num> {
218    raw_arg(as_mut_ptr(t).cast())
219}
220
221/// Convert an optional mutable reference into a `usize` for passing to a
222/// syscall.
223#[inline]
224pub(super) fn opt_mut<T: Sized, Num: ArgNumber>(t: Option<&mut T>) -> ArgReg<'_, Num> {
225    // This optimizes into the equivalent of `transmute(t)`, and has the
226    // advantage of not requiring `unsafe`.
227    match t {
228        Some(t) => by_mut(t),
229        None => raw_arg(null_mut()),
230    }
231}
232
233/// Convert an optional immutable reference into a `usize` for passing to a
234/// syscall.
235#[inline]
236pub(super) fn opt_ref<T: Sized, Num: ArgNumber>(t: Option<&T>) -> ArgReg<'_, Num> {
237    // This optimizes into the equivalent of `transmute(t)`, and has the
238    // advantage of not requiring `unsafe`.
239    match t {
240        Some(t) => by_ref(t),
241        None => raw_arg(null_mut()),
242    }
243}
244
245/// Convert a `c_int` into an `ArgReg`.
246///
247/// Be sure to use `raw_fd` to pass `RawFd` values.
248#[inline]
249pub(super) fn c_int<'a, Num: ArgNumber>(i: c::c_int) -> ArgReg<'a, Num> {
250    pass_usize(i as usize)
251}
252
253/// Convert a `c_uint` into an `ArgReg`.
254#[inline]
255pub(super) fn c_uint<'a, Num: ArgNumber>(i: c::c_uint) -> ArgReg<'a, Num> {
256    pass_usize(i as usize)
257}
258
259#[cfg(target_pointer_width = "64")]
260#[inline]
261pub(super) fn loff_t<'a, Num: ArgNumber>(i: __kernel_loff_t) -> ArgReg<'a, Num> {
262    pass_usize(i as usize)
263}
264
265#[cfg(target_pointer_width = "64")]
266#[inline]
267pub(super) fn loff_t_from_u64<'a, Num: ArgNumber>(i: u64) -> ArgReg<'a, Num> {
268    // `loff_t` is signed, but syscalls which expect `loff_t` return `EINVAL`
269    // if it's outside the signed `i64` range, so we can silently cast.
270    pass_usize(i as usize)
271}
272
273#[cfg(any(feature = "thread", feature = "time"))]
274impl<'a, Num: ArgNumber> From<ClockId> for ArgReg<'a, Num> {
275    #[inline]
276    fn from(i: ClockId) -> Self {
277        pass_usize(i as __kernel_clockid_t as usize)
278    }
279}
280
281#[cfg(feature = "time")]
282impl<'a, Num: ArgNumber> From<TimerfdClockId> for ArgReg<'a, Num> {
283    #[inline]
284    fn from(i: TimerfdClockId) -> Self {
285        pass_usize(i as __kernel_clockid_t as usize)
286    }
287}
288
289#[cfg(feature = "net")]
290#[inline]
291pub(super) fn socklen_t<'a, Num: ArgNumber>(i: socklen_t) -> ArgReg<'a, Num> {
292    pass_usize(i as usize)
293}
294
295#[cfg(any(
296    feature = "fs",
297    all(
298        not(feature = "use-libc-auxv"),
299        not(feature = "use-explicitly-provided-auxv"),
300        any(
301            feature = "param",
302            feature = "runtime",
303            feature = "thread",
304            feature = "time",
305            target_arch = "x86",
306        )
307    )
308))]
309pub(crate) mod fs {
310    use super::*;
311    use crate::fs::{FileType, Mode, OFlags};
312    #[cfg(target_pointer_width = "32")]
313    use linux_raw_sys::general::O_LARGEFILE;
314
315    impl<'a, Num: ArgNumber> From<Mode> for ArgReg<'a, Num> {
316        #[inline]
317        fn from(mode: Mode) -> Self {
318            pass_usize(mode.bits() as usize)
319        }
320    }
321
322    impl<'a, Num: ArgNumber> From<(Mode, FileType)> for ArgReg<'a, Num> {
323        #[inline]
324        fn from(pair: (Mode, FileType)) -> Self {
325            pass_usize(pair.0.as_raw_mode() as usize | pair.1.as_raw_mode() as usize)
326        }
327    }
328
329    impl<'a, Num: ArgNumber> From<crate::fs::AtFlags> for ArgReg<'a, Num> {
330        #[inline]
331        fn from(flags: crate::fs::AtFlags) -> Self {
332            c_uint(flags.bits())
333        }
334    }
335
336    impl<'a, Num: ArgNumber> From<crate::fs::XattrFlags> for ArgReg<'a, Num> {
337        #[inline]
338        fn from(flags: crate::fs::XattrFlags) -> Self {
339            c_uint(flags.bits())
340        }
341    }
342
343    impl<'a, Num: ArgNumber> From<crate::fs::inotify::CreateFlags> for ArgReg<'a, Num> {
344        #[inline]
345        fn from(flags: crate::fs::inotify::CreateFlags) -> Self {
346            c_uint(flags.bits())
347        }
348    }
349
350    impl<'a, Num: ArgNumber> From<crate::fs::inotify::WatchFlags> for ArgReg<'a, Num> {
351        #[inline]
352        fn from(flags: crate::fs::inotify::WatchFlags) -> Self {
353            c_uint(flags.bits())
354        }
355    }
356
357    impl<'a, Num: ArgNumber> From<crate::fs::MemfdFlags> for ArgReg<'a, Num> {
358        #[inline]
359        fn from(flags: crate::fs::MemfdFlags) -> Self {
360            c_uint(flags.bits())
361        }
362    }
363
364    impl<'a, Num: ArgNumber> From<crate::fs::RenameFlags> for ArgReg<'a, Num> {
365        #[inline]
366        fn from(flags: crate::fs::RenameFlags) -> Self {
367            c_uint(flags.bits())
368        }
369    }
370
371    impl<'a, Num: ArgNumber> From<crate::fs::StatxFlags> for ArgReg<'a, Num> {
372        #[inline]
373        fn from(flags: crate::fs::StatxFlags) -> Self {
374            c_uint(flags.bits())
375        }
376    }
377
378    #[cfg(target_pointer_width = "32")]
379    #[inline]
380    fn oflags_bits(oflags: OFlags) -> c::c_uint {
381        let mut bits = oflags.bits();
382        // Add `O_LARGEFILE`, unless `O_PATH` is set, as Linux returns `EINVAL`
383        // when both are set.
384        if !oflags.contains(OFlags::PATH) {
385            bits |= O_LARGEFILE;
386        }
387        bits
388    }
389
390    #[cfg(target_pointer_width = "64")]
391    #[inline]
392    const fn oflags_bits(oflags: OFlags) -> c::c_uint {
393        oflags.bits()
394    }
395
396    impl<'a, Num: ArgNumber> From<OFlags> for ArgReg<'a, Num> {
397        #[inline]
398        fn from(oflags: OFlags) -> Self {
399            pass_usize(oflags_bits(oflags) as usize)
400        }
401    }
402
403    /// Convert an `OFlags` into a `u64` for use in the `open_how` struct.
404    #[inline]
405    pub(crate) fn oflags_for_open_how(oflags: OFlags) -> u64 {
406        u64::from(oflags_bits(oflags))
407    }
408
409    impl<'a, Num: ArgNumber> From<crate::fs::FallocateFlags> for ArgReg<'a, Num> {
410        #[inline]
411        fn from(flags: crate::fs::FallocateFlags) -> Self {
412            c_uint(flags.bits())
413        }
414    }
415
416    impl<'a, Num: ArgNumber> From<crate::fs::Advice> for ArgReg<'a, Num> {
417        #[inline]
418        fn from(advice: crate::fs::Advice) -> Self {
419            c_uint(advice as c::c_uint)
420        }
421    }
422
423    impl<'a, Num: ArgNumber> From<crate::fs::SealFlags> for ArgReg<'a, Num> {
424        #[inline]
425        fn from(flags: crate::fs::SealFlags) -> Self {
426            c_uint(flags.bits())
427        }
428    }
429
430    impl<'a, Num: ArgNumber> From<crate::fs::Access> for ArgReg<'a, Num> {
431        #[inline]
432        fn from(access: crate::fs::Access) -> Self {
433            c_uint(access.bits())
434        }
435    }
436}
437
438#[cfg(feature = "mount")]
439impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MountFlagsArg> for ArgReg<'a, Num> {
440    #[inline]
441    fn from(flags: crate::backend::mount::types::MountFlagsArg) -> Self {
442        c_uint(flags.0)
443    }
444}
445
446#[cfg(feature = "mount")]
447impl<'a, Num: ArgNumber> From<crate::backend::mount::types::UnmountFlags> for ArgReg<'a, Num> {
448    #[inline]
449    fn from(flags: crate::backend::mount::types::UnmountFlags) -> Self {
450        c_uint(flags.bits())
451    }
452}
453
454#[cfg(feature = "mount")]
455impl<'a, Num: ArgNumber> From<crate::mount::FsConfigCmd> for ArgReg<'a, Num> {
456    #[inline]
457    fn from(cmd: crate::mount::FsConfigCmd) -> Self {
458        c_uint(cmd as c::c_uint)
459    }
460}
461
462#[cfg(feature = "mount")]
463impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsOpenFlags> for ArgReg<'a, Num> {
464    #[inline]
465    fn from(flags: crate::backend::mount::types::FsOpenFlags) -> Self {
466        c_uint(flags.bits())
467    }
468}
469
470#[cfg(feature = "mount")]
471impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsMountFlags> for ArgReg<'a, Num> {
472    #[inline]
473    fn from(flags: crate::backend::mount::types::FsMountFlags) -> Self {
474        c_uint(flags.bits())
475    }
476}
477
478#[cfg(feature = "mount")]
479impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MountAttrFlags> for ArgReg<'a, Num> {
480    #[inline]
481    fn from(flags: crate::backend::mount::types::MountAttrFlags) -> Self {
482        c_uint(flags.bits())
483    }
484}
485
486#[cfg(feature = "mount")]
487impl<'a, Num: ArgNumber> From<crate::backend::mount::types::OpenTreeFlags> for ArgReg<'a, Num> {
488    #[inline]
489    fn from(flags: crate::backend::mount::types::OpenTreeFlags) -> Self {
490        c_uint(flags.bits())
491    }
492}
493
494#[cfg(feature = "mount")]
495impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsPickFlags> for ArgReg<'a, Num> {
496    #[inline]
497    fn from(flags: crate::backend::mount::types::FsPickFlags) -> Self {
498        c_uint(flags.bits())
499    }
500}
501
502#[cfg(feature = "mount")]
503impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MoveMountFlags> for ArgReg<'a, Num> {
504    #[inline]
505    fn from(flags: crate::backend::mount::types::MoveMountFlags) -> Self {
506        c_uint(flags.bits())
507    }
508}
509
510impl<'a, Num: ArgNumber> From<crate::io::FdFlags> for ArgReg<'a, Num> {
511    #[inline]
512    fn from(flags: crate::io::FdFlags) -> Self {
513        c_uint(flags.bits())
514    }
515}
516
517#[cfg(feature = "pipe")]
518impl<'a, Num: ArgNumber> From<crate::pipe::PipeFlags> for ArgReg<'a, Num> {
519    #[inline]
520    fn from(flags: crate::pipe::PipeFlags) -> Self {
521        c_uint(flags.bits())
522    }
523}
524
525#[cfg(feature = "pipe")]
526impl<'a, Num: ArgNumber> From<crate::pipe::SpliceFlags> for ArgReg<'a, Num> {
527    #[inline]
528    fn from(flags: crate::pipe::SpliceFlags) -> Self {
529        c_uint(flags.bits())
530    }
531}
532
533impl<'a, Num: ArgNumber> From<crate::io::DupFlags> for ArgReg<'a, Num> {
534    #[inline]
535    fn from(flags: crate::io::DupFlags) -> Self {
536        c_uint(flags.bits())
537    }
538}
539
540impl<'a, Num: ArgNumber> From<crate::io::ReadWriteFlags> for ArgReg<'a, Num> {
541    #[inline]
542    fn from(flags: crate::io::ReadWriteFlags) -> Self {
543        c_uint(flags.bits())
544    }
545}
546
547#[cfg(feature = "process")]
548impl<'a, Num: ArgNumber> From<crate::process::PidfdFlags> for ArgReg<'a, Num> {
549    #[inline]
550    fn from(flags: crate::process::PidfdFlags) -> Self {
551        c_uint(flags.bits())
552    }
553}
554
555#[cfg(feature = "pty")]
556impl<'a, Num: ArgNumber> From<crate::pty::OpenptFlags> for ArgReg<'a, Num> {
557    #[inline]
558    fn from(flags: crate::pty::OpenptFlags) -> Self {
559        c_uint(flags.bits())
560    }
561}
562
563#[cfg(feature = "thread")]
564impl<'a, Num: ArgNumber> From<crate::thread::UnshareFlags> for ArgReg<'a, Num> {
565    #[inline]
566    fn from(flags: crate::thread::UnshareFlags) -> Self {
567        c_uint(flags.bits())
568    }
569}
570
571#[cfg(feature = "event")]
572impl<'a, Num: ArgNumber> From<crate::event::EventfdFlags> for ArgReg<'a, Num> {
573    #[inline]
574    fn from(flags: crate::event::EventfdFlags) -> Self {
575        c_uint(flags.bits())
576    }
577}
578
579#[cfg(feature = "event")]
580impl<'a, Num: ArgNumber> From<crate::event::epoll::CreateFlags> for ArgReg<'a, Num> {
581    #[inline]
582    fn from(flags: crate::event::epoll::CreateFlags) -> Self {
583        c_uint(flags.bits())
584    }
585}
586
587#[cfg(feature = "mm")]
588impl<'a, Num: ArgNumber> From<crate::backend::mm::types::ProtFlags> for ArgReg<'a, Num> {
589    #[inline]
590    fn from(flags: crate::backend::mm::types::ProtFlags) -> Self {
591        c_uint(flags.bits())
592    }
593}
594
595#[cfg(feature = "mm")]
596impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MsyncFlags> for ArgReg<'a, Num> {
597    #[inline]
598    fn from(flags: crate::backend::mm::types::MsyncFlags) -> Self {
599        c_uint(flags.bits())
600    }
601}
602
603#[cfg(feature = "mm")]
604impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MremapFlags> for ArgReg<'a, Num> {
605    #[inline]
606    fn from(flags: crate::backend::mm::types::MremapFlags) -> Self {
607        c_uint(flags.bits())
608    }
609}
610
611#[cfg(feature = "mm")]
612impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MlockFlags> for ArgReg<'a, Num> {
613    #[inline]
614    fn from(flags: crate::backend::mm::types::MlockFlags) -> Self {
615        c_uint(flags.bits())
616    }
617}
618
619#[cfg(feature = "mm")]
620impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MlockAllFlags> for ArgReg<'a, Num> {
621    #[inline]
622    fn from(flags: crate::backend::mm::types::MlockAllFlags) -> Self {
623        c_uint(flags.bits())
624    }
625}
626
627#[cfg(feature = "mm")]
628impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MapFlags> for ArgReg<'a, Num> {
629    #[inline]
630    fn from(flags: crate::backend::mm::types::MapFlags) -> Self {
631        c_uint(flags.bits())
632    }
633}
634
635#[cfg(feature = "mm")]
636impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MprotectFlags> for ArgReg<'a, Num> {
637    #[inline]
638    fn from(flags: crate::backend::mm::types::MprotectFlags) -> Self {
639        c_uint(flags.bits())
640    }
641}
642
643#[cfg(feature = "mm")]
644impl<'a, Num: ArgNumber> From<crate::backend::mm::types::UserfaultfdFlags> for ArgReg<'a, Num> {
645    #[inline]
646    fn from(flags: crate::backend::mm::types::UserfaultfdFlags) -> Self {
647        c_uint(flags.bits())
648    }
649}
650
651#[cfg(feature = "thread")]
652impl<'a, Num: ArgNumber> From<crate::backend::thread::types::MembarrierCommand>
653    for ArgReg<'a, Num>
654{
655    #[inline]
656    fn from(cmd: crate::backend::thread::types::MembarrierCommand) -> Self {
657        c_uint(cmd as u32)
658    }
659}
660
661#[cfg(feature = "thread")]
662impl<'a, Num: ArgNumber> From<crate::thread::Cpuid> for ArgReg<'a, Num> {
663    #[inline]
664    fn from(cpuid: crate::thread::Cpuid) -> Self {
665        c_uint(cpuid.as_raw())
666    }
667}
668
669#[cfg(target_pointer_width = "64")]
670#[inline]
671pub(super) fn dev_t<'a, Num: ArgNumber>(dev: u64) -> ArgReg<'a, Num> {
672    pass_usize(dev as usize)
673}
674
675#[cfg(target_pointer_width = "32")]
676#[inline]
677pub(super) fn dev_t<'a, Num: ArgNumber>(dev: u64) -> io::Result<ArgReg<'a, Num>> {
678    Ok(pass_usize(dev.try_into().map_err(|_err| io::Errno::INVAL)?))
679}
680
681/// Convert a `Resource` into a syscall argument.
682#[cfg(feature = "process")]
683impl<'a, Num: ArgNumber> From<Resource> for ArgReg<'a, Num> {
684    #[inline]
685    fn from(resource: Resource) -> Self {
686        c_uint(resource as c::c_uint)
687    }
688}
689
690#[cfg(any(feature = "process", feature = "runtime", feature = "termios"))]
691impl<'a, Num: ArgNumber> From<Pid> for ArgReg<'a, Num> {
692    #[inline]
693    fn from(pid: Pid) -> Self {
694        pass_usize(pid.as_raw_nonzero().get() as usize)
695    }
696}
697
698#[cfg(feature = "process")]
699#[inline]
700pub(super) fn negative_pid<'a, Num: ArgNumber>(pid: Pid) -> ArgReg<'a, Num> {
701    pass_usize(pid.as_raw_nonzero().get().wrapping_neg() as usize)
702}
703
704#[cfg(any(feature = "process", feature = "runtime"))]
705impl<'a, Num: ArgNumber> From<Signal> for ArgReg<'a, Num> {
706    #[inline]
707    fn from(sig: Signal) -> Self {
708        pass_usize(sig.as_raw() as usize)
709    }
710}
711
712#[cfg(feature = "io_uring")]
713impl<'a, Num: ArgNumber> From<crate::io_uring::IoringEnterFlags> for ArgReg<'a, Num> {
714    #[inline]
715    fn from(flags: crate::io_uring::IoringEnterFlags) -> Self {
716        c_uint(flags.bits())
717    }
718}
719
720#[cfg(feature = "time")]
721impl<'a, Num: ArgNumber> From<crate::time::TimerfdFlags> for ArgReg<'a, Num> {
722    #[inline]
723    fn from(flags: crate::time::TimerfdFlags) -> Self {
724        c_uint(flags.bits())
725    }
726}
727
728#[cfg(feature = "time")]
729impl<'a, Num: ArgNumber> From<crate::time::TimerfdTimerFlags> for ArgReg<'a, Num> {
730    #[inline]
731    fn from(flags: crate::time::TimerfdTimerFlags) -> Self {
732        c_uint(flags.bits())
733    }
734}
735
736#[cfg(feature = "rand")]
737impl<'a, Num: ArgNumber> From<crate::rand::GetRandomFlags> for ArgReg<'a, Num> {
738    #[inline]
739    fn from(flags: crate::rand::GetRandomFlags) -> Self {
740        c_uint(flags.bits())
741    }
742}
743
744#[cfg(feature = "net")]
745impl<'a, Num: ArgNumber> From<crate::net::RecvFlags> for ArgReg<'a, Num> {
746    #[inline]
747    fn from(flags: crate::net::RecvFlags) -> Self {
748        c_uint(flags.bits())
749    }
750}
751
752#[cfg(feature = "net")]
753impl<'a, Num: ArgNumber> From<crate::net::SendFlags> for ArgReg<'a, Num> {
754    #[inline]
755    fn from(flags: crate::net::SendFlags) -> Self {
756        c_uint(flags.bits())
757    }
758}
759
760#[cfg(feature = "net")]
761impl<'a, Num: ArgNumber> From<crate::net::SocketFlags> for ArgReg<'a, Num> {
762    #[inline]
763    fn from(flags: crate::net::SocketFlags) -> Self {
764        c_uint(flags.bits())
765    }
766}
767
768#[cfg(feature = "net")]
769impl<'a, Num: ArgNumber> From<crate::net::AddressFamily> for ArgReg<'a, Num> {
770    #[inline]
771    fn from(family: crate::net::AddressFamily) -> Self {
772        c_uint(family.0.into())
773    }
774}
775
776#[cfg(feature = "net")]
777impl<'a, Num: ArgNumber> From<(crate::net::SocketType, crate::net::SocketFlags)>
778    for ArgReg<'a, Num>
779{
780    #[inline]
781    fn from(pair: (crate::net::SocketType, crate::net::SocketFlags)) -> Self {
782        c_uint(pair.0 .0 | pair.1.bits())
783    }
784}
785
786#[cfg(feature = "thread")]
787impl<'a, Num: ArgNumber>
788    From<(
789        crate::backend::thread::futex::Operation,
790        crate::thread::futex::Flags,
791    )> for ArgReg<'a, Num>
792{
793    #[inline]
794    fn from(
795        pair: (
796            crate::backend::thread::futex::Operation,
797            crate::thread::futex::Flags,
798        ),
799    ) -> Self {
800        c_uint(pair.0 as u32 | pair.1.bits())
801    }
802}
803
804#[cfg(feature = "net")]
805impl<'a, Num: ArgNumber> From<crate::net::SocketType> for ArgReg<'a, Num> {
806    #[inline]
807    fn from(type_: crate::net::SocketType) -> Self {
808        c_uint(type_.0)
809    }
810}
811
812#[cfg(feature = "net")]
813impl<'a, Num: ArgNumber> From<Option<crate::net::Protocol>> for ArgReg<'a, Num> {
814    #[inline]
815    fn from(protocol: Option<crate::net::Protocol>) -> Self {
816        c_uint(match protocol {
817            Some(p) => p.0.get(),
818            None => 0,
819        })
820    }
821}
822
823impl<'a, Num: ArgNumber, T> From<&'a mut MaybeUninit<T>> for ArgReg<'a, Num> {
824    #[inline]
825    fn from(t: &'a mut MaybeUninit<T>) -> Self {
826        raw_arg(t.as_mut_ptr().cast())
827    }
828}
829
830impl<'a, Num: ArgNumber, T> From<&'a mut [MaybeUninit<T>]> for ArgReg<'a, Num> {
831    #[inline]
832    fn from(t: &'a mut [MaybeUninit<T>]) -> Self {
833        raw_arg(t.as_mut_ptr().cast())
834    }
835}
836
837#[cfg(any(feature = "process", feature = "thread"))]
838impl<'a, Num: ArgNumber> From<crate::ugid::Uid> for ArgReg<'a, Num> {
839    #[inline]
840    fn from(t: crate::ugid::Uid) -> Self {
841        c_uint(t.as_raw())
842    }
843}
844
845#[cfg(any(feature = "process", feature = "thread"))]
846impl<'a, Num: ArgNumber> From<crate::ugid::Gid> for ArgReg<'a, Num> {
847    #[inline]
848    fn from(t: crate::ugid::Gid) -> Self {
849        c_uint(t.as_raw())
850    }
851}
852
853#[cfg(feature = "runtime")]
854impl<'a, Num: ArgNumber> From<crate::runtime::How> for ArgReg<'a, Num> {
855    #[inline]
856    fn from(flags: crate::runtime::How) -> Self {
857        c_uint(flags as u32)
858    }
859}
860
861/// Convert a `usize` returned from a syscall that effectively returns `()` on
862/// success.
863///
864/// # Safety
865///
866/// The caller must ensure that this is the return value of a syscall which
867/// just returns 0 on success.
868#[inline]
869pub(super) unsafe fn ret(raw: RetReg<R0>) -> io::Result<()> {
870    try_decode_void(raw)
871}
872
873/// Convert a `usize` returned from a syscall that doesn't return on success.
874///
875/// # Safety
876///
877/// The caller must ensure that this is the return value of a syscall which
878/// doesn't return on success.
879#[cfg(any(feature = "event", feature = "runtime", feature = "system"))]
880#[inline]
881pub(super) unsafe fn ret_error(raw: RetReg<R0>) -> io::Errno {
882    try_decode_error(raw)
883}
884
885/// Convert a `usize` returned from a syscall that effectively always returns
886/// `()`.
887///
888/// # Safety
889///
890/// The caller must ensure that this is the return value of a syscall which
891/// always returns `()`.
892#[inline]
893pub(super) unsafe fn ret_infallible(raw: RetReg<R0>) {
894    #[cfg(debug_assertions)]
895    {
896        try_decode_void(raw).unwrap()
897    }
898    #[cfg(not(debug_assertions))]
899    drop(raw);
900}
901
902/// Convert a `usize` returned from a syscall that effectively returns a
903/// `c_int` on success.
904#[inline]
905pub(super) fn ret_c_int(raw: RetReg<R0>) -> io::Result<c::c_int> {
906    try_decode_c_int(raw)
907}
908
909/// Convert a `usize` returned from a syscall that effectively returns a
910/// `c_uint` on success.
911#[inline]
912pub(super) fn ret_c_uint(raw: RetReg<R0>) -> io::Result<c::c_uint> {
913    try_decode_c_uint(raw)
914}
915
916/// Convert a `usize` returned from a syscall that effectively returns a `u64`
917/// on success.
918#[cfg(target_pointer_width = "64")]
919#[inline]
920pub(super) fn ret_u64(raw: RetReg<R0>) -> io::Result<u64> {
921    try_decode_u64(raw)
922}
923
924/// Convert a `usize` returned from a syscall that effectively returns a
925/// `usize` on success.
926#[inline]
927pub(super) fn ret_usize(raw: RetReg<R0>) -> io::Result<usize> {
928    try_decode_usize(raw)
929}
930
931/// Convert a `usize` returned from a syscall that effectively always
932/// returns a `usize`.
933///
934/// # Safety
935///
936/// This function must only be used with return values from infallible
937/// syscalls.
938#[inline]
939pub(super) unsafe fn ret_usize_infallible(raw: RetReg<R0>) -> usize {
940    #[cfg(debug_assertions)]
941    {
942        try_decode_usize(raw).unwrap()
943    }
944    #[cfg(not(debug_assertions))]
945    {
946        decode_usize_infallible(raw)
947    }
948}
949
950/// Convert a `c_int` returned from a syscall that effectively always
951/// returns a `c_int`.
952///
953/// # Safety
954///
955/// This function must only be used with return values from infallible
956/// syscalls.
957#[inline]
958pub(super) unsafe fn ret_c_int_infallible(raw: RetReg<R0>) -> c::c_int {
959    #[cfg(debug_assertions)]
960    {
961        try_decode_c_int(raw).unwrap()
962    }
963    #[cfg(not(debug_assertions))]
964    {
965        decode_c_int_infallible(raw)
966    }
967}
968
969/// Convert a `c_uint` returned from a syscall that effectively always
970/// returns a `c_uint`.
971///
972/// # Safety
973///
974/// This function must only be used with return values from infallible
975/// syscalls.
976#[inline]
977pub(super) unsafe fn ret_c_uint_infallible(raw: RetReg<R0>) -> c::c_uint {
978    #[cfg(debug_assertions)]
979    {
980        try_decode_c_uint(raw).unwrap()
981    }
982    #[cfg(not(debug_assertions))]
983    {
984        decode_c_uint_infallible(raw)
985    }
986}
987
988/// Convert a `usize` returned from a syscall that effectively returns an
989/// `OwnedFd` on success.
990///
991/// # Safety
992///
993/// The caller must ensure that this is the return value of a syscall which
994/// returns an owned file descriptor.
995#[inline]
996pub(super) unsafe fn ret_owned_fd(raw: RetReg<R0>) -> io::Result<OwnedFd> {
997    let raw_fd = try_decode_raw_fd(raw)?;
998    Ok(crate::backend::fd::OwnedFd::from_raw_fd(raw_fd))
999}
1000
1001/// Convert the return value of `dup2` and `dup3`.
1002///
1003/// When these functions succeed, they return the same value as their second
1004/// argument, so we don't construct a new `OwnedFd`.
1005///
1006/// # Safety
1007///
1008/// The caller must ensure that this is the return value of a syscall which
1009/// returns a file descriptor.
1010#[inline]
1011pub(super) unsafe fn ret_discarded_fd(raw: RetReg<R0>) -> io::Result<()> {
1012    let _raw_fd = try_decode_raw_fd(raw)?;
1013    Ok(())
1014}
1015
1016/// Convert a `usize` returned from a syscall that effectively returns a
1017/// `*mut c_void` on success.
1018#[inline]
1019pub(super) fn ret_void_star(raw: RetReg<R0>) -> io::Result<*mut c::c_void> {
1020    try_decode_void_star(raw)
1021}