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