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 | |
16 | use super::c; |
17 | use super::fd::{AsRawFd, BorrowedFd, FromRawFd, RawFd}; |
18 | #[cfg (any(feature = "event" , feature = "runtime" ))] |
19 | use super::io::errno::try_decode_error; |
20 | #[cfg (target_pointer_width = "64" )] |
21 | use super::io::errno::try_decode_u64; |
22 | #[cfg (not(debug_assertions))] |
23 | use super::io::errno::{ |
24 | decode_c_int_infallible, decode_c_uint_infallible, decode_usize_infallible, |
25 | }; |
26 | use 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 | }; |
30 | use super::reg::{raw_arg, ArgNumber, ArgReg, RetReg, R0}; |
31 | #[cfg (feature = "time" )] |
32 | use super::time::types::TimerfdClockId; |
33 | #[cfg (any(feature = "thread" , feature = "time" , target_arch = "x86" ))] |
34 | use crate::clockid::ClockId; |
35 | use crate::fd::OwnedFd; |
36 | use crate::ffi::CStr; |
37 | use crate::io; |
38 | #[cfg (any(feature = "process" , feature = "runtime" , feature = "termios" ))] |
39 | use crate::pid::Pid; |
40 | #[cfg (feature = "process" )] |
41 | use crate::process::Resource; |
42 | #[cfg (any(feature = "process" , feature = "runtime" ))] |
43 | use crate::signal::Signal; |
44 | use crate::utils::{as_mut_ptr, as_ptr}; |
45 | use core::mem::MaybeUninit; |
46 | use core::ptr::null_mut; |
47 | #[cfg (any(feature = "thread" , feature = "time" , target_arch = "x86" ))] |
48 | use linux_raw_sys::general::__kernel_clockid_t; |
49 | #[cfg (target_pointer_width = "64" )] |
50 | use linux_raw_sys::general::__kernel_loff_t; |
51 | #[cfg (feature = "net" )] |
52 | use linux_raw_sys::net::socklen_t; |
53 | |
54 | /// Convert `SYS_*` constants for socketcall. |
55 | #[cfg (target_arch = "x86" )] |
56 | #[inline ] |
57 | pub(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 ] |
65 | pub(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 ] |
78 | pub(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 ] |
89 | pub(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 ] |
95 | pub(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 ] |
104 | pub(super) fn pass_usize<'a, Num: ArgNumber>(t: usize) -> ArgReg<'a, Num> { |
105 | raw_arg(t as *mut _) |
106 | } |
107 | |
108 | impl<'a, Num: ArgNumber, T> From<*mut T> for ArgReg<'a, Num> { |
109 | #[inline ] |
110 | fn from(c: *mut T) -> ArgReg<'a, Num> { |
111 | raw_arg(c.cast()) |
112 | } |
113 | } |
114 | |
115 | impl<'a, Num: ArgNumber, T> From<*const T> for ArgReg<'a, Num> { |
116 | #[inline ] |
117 | fn from(c: *const T) -> ArgReg<'a, Num> { |
118 | let mut_ptr = c as *mut T; |
119 | raw_arg(mut_ptr.cast()) |
120 | } |
121 | } |
122 | |
123 | impl<'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 | |
131 | impl<'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. |
145 | impl<'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 ] |
162 | pub(super) unsafe fn raw_fd<'a, Num: ArgNumber>(fd: RawFd) -> ArgReg<'a, Num> { |
163 | // Use `no_fd` when passing `-1` is intended. |
164 | #[cfg (feature = "fs" )] |
165 | debug_assert!(fd == crate::fs::CWD.as_raw_fd() || fd >= 0); |
166 | |
167 | // Don't pass the `io_uring_register_files_skip` sentry value this way. |
168 | #[cfg (feature = "io_uring" )] |
169 | debug_assert_ne!( |
170 | fd, |
171 | crate::io_uring::io_uring_register_files_skip().as_raw_fd() |
172 | ); |
173 | |
174 | // Linux doesn't look at the high bits beyond the `c_int`, so use |
175 | // zero-extension rather than sign-extension because it's a smaller |
176 | // instruction. |
177 | let fd: c::c_int = fd; |
178 | pass_usize(fd as c::c_uint as usize) |
179 | } |
180 | |
181 | /// Deliberately pass `-1` to a file-descriptor argument, for system calls |
182 | /// like `mmap` where this indicates the argument is omitted. |
183 | #[inline ] |
184 | pub(super) fn no_fd<'a, Num: ArgNumber>() -> ArgReg<'a, Num> { |
185 | pass_usize(!0_usize) |
186 | } |
187 | |
188 | #[inline ] |
189 | pub(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 ] |
195 | pub(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 ] |
200 | pub(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 ] |
207 | pub(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 ] |
214 | pub(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 ] |
220 | pub(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 ] |
227 | pub(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 ] |
240 | pub(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 ] |
253 | pub(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 ] |
259 | pub(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 ] |
265 | pub(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 ] |
271 | pub(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" ))] |
278 | impl<'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" )] |
286 | impl<'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 ] |
295 | pub(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 | ))] |
313 | pub(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" ))] |
443 | impl<'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" ))] |
453 | impl<'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" )] |
461 | impl<'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" )] |
469 | impl<'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" )] |
477 | impl<'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" )] |
485 | impl<'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" )] |
493 | impl<'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" )] |
501 | impl<'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" )] |
509 | impl<'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 | |
516 | impl<'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" )] |
524 | impl<'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" )] |
532 | impl<'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 | |
539 | impl<'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 | |
546 | impl<'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" )] |
554 | impl<'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" )] |
562 | impl<'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" )] |
570 | impl<'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" )] |
578 | impl<'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" )] |
586 | impl<'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" )] |
594 | impl<'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" )] |
602 | impl<'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" )] |
610 | impl<'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" )] |
618 | impl<'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" )] |
626 | impl<'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" )] |
634 | impl<'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" )] |
642 | impl<'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" )] |
650 | impl<'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" )] |
658 | impl<'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" )] |
668 | impl<'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 ] |
677 | pub(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 ] |
683 | pub(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" )] |
689 | impl<'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" ))] |
697 | impl<'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 ] |
706 | pub(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" ))] |
711 | impl<'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" )] |
719 | impl<'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" )] |
727 | impl<'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" )] |
735 | impl<'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" )] |
743 | impl<'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" )] |
751 | impl<'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" )] |
759 | impl<'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" )] |
767 | impl<'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" )] |
775 | impl<'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" )] |
783 | impl<'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" )] |
793 | impl<'a, Num: ArgNumber> From<(crate::thread::FutexOperation, crate::thread::FutexFlags)> |
794 | for ArgReg<'a, Num> |
795 | { |
796 | #[inline ] |
797 | fn from(pair: (crate::thread::FutexOperation, crate::thread::FutexFlags)) -> Self { |
798 | c_uint(pair.0 as u32 | pair.1.bits()) |
799 | } |
800 | } |
801 | |
802 | #[cfg (feature = "net" )] |
803 | impl<'a, Num: ArgNumber> From<crate::net::SocketType> for ArgReg<'a, Num> { |
804 | #[inline ] |
805 | fn from(type_: crate::net::SocketType) -> Self { |
806 | c_uint(type_.0) |
807 | } |
808 | } |
809 | |
810 | #[cfg (feature = "net" )] |
811 | impl<'a, Num: ArgNumber> From<Option<crate::net::Protocol>> for ArgReg<'a, Num> { |
812 | #[inline ] |
813 | fn from(protocol: Option<crate::net::Protocol>) -> Self { |
814 | c_uint(match protocol { |
815 | Some(p) => p.0.get(), |
816 | None => 0, |
817 | }) |
818 | } |
819 | } |
820 | |
821 | impl<'a, Num: ArgNumber, T> From<&'a mut MaybeUninit<T>> for ArgReg<'a, Num> { |
822 | #[inline ] |
823 | fn from(t: &'a mut MaybeUninit<T>) -> Self { |
824 | raw_arg(t.as_mut_ptr().cast()) |
825 | } |
826 | } |
827 | |
828 | impl<'a, Num: ArgNumber, T> From<&'a mut [MaybeUninit<T>]> for ArgReg<'a, Num> { |
829 | #[inline ] |
830 | fn from(t: &'a mut [MaybeUninit<T>]) -> Self { |
831 | raw_arg(t.as_mut_ptr().cast()) |
832 | } |
833 | } |
834 | |
835 | #[cfg (any(feature = "process" , feature = "thread" ))] |
836 | impl<'a, Num: ArgNumber> From<crate::ugid::Uid> for ArgReg<'a, Num> { |
837 | #[inline ] |
838 | fn from(t: crate::ugid::Uid) -> Self { |
839 | c_uint(t.as_raw()) |
840 | } |
841 | } |
842 | |
843 | #[cfg (any(feature = "process" , feature = "thread" ))] |
844 | impl<'a, Num: ArgNumber> From<crate::ugid::Gid> for ArgReg<'a, Num> { |
845 | #[inline ] |
846 | fn from(t: crate::ugid::Gid) -> Self { |
847 | c_uint(t.as_raw()) |
848 | } |
849 | } |
850 | |
851 | #[cfg (feature = "runtime" )] |
852 | impl<'a, Num: ArgNumber> From<crate::runtime::How> for ArgReg<'a, Num> { |
853 | #[inline ] |
854 | fn from(flags: crate::runtime::How) -> Self { |
855 | c_uint(flags as u32) |
856 | } |
857 | } |
858 | |
859 | /// Convert a `usize` returned from a syscall that effectively returns `()` on |
860 | /// success. |
861 | /// |
862 | /// # Safety |
863 | /// |
864 | /// The caller must ensure that this is the return value of a syscall which |
865 | /// just returns 0 on success. |
866 | #[inline ] |
867 | pub(super) unsafe fn ret(raw: RetReg<R0>) -> io::Result<()> { |
868 | try_decode_void(raw) |
869 | } |
870 | |
871 | /// Convert a `usize` returned from a syscall that doesn't return on success. |
872 | /// |
873 | /// # Safety |
874 | /// |
875 | /// The caller must ensure that this is the return value of a syscall which |
876 | /// doesn't return on success. |
877 | #[cfg (any(feature = "event" , feature = "runtime" ))] |
878 | #[inline ] |
879 | pub(super) unsafe fn ret_error(raw: RetReg<R0>) -> io::Errno { |
880 | try_decode_error(raw) |
881 | } |
882 | |
883 | /// Convert a `usize` returned from a syscall that effectively always returns |
884 | /// `()`. |
885 | /// |
886 | /// # Safety |
887 | /// |
888 | /// The caller must ensure that this is the return value of a syscall which |
889 | /// always returns `()`. |
890 | #[inline ] |
891 | pub(super) unsafe fn ret_infallible(raw: RetReg<R0>) { |
892 | #[cfg (debug_assertions)] |
893 | { |
894 | try_decode_void(raw).unwrap() |
895 | } |
896 | #[cfg (not(debug_assertions))] |
897 | drop(raw); |
898 | } |
899 | |
900 | /// Convert a `usize` returned from a syscall that effectively returns a |
901 | /// `c_int` on success. |
902 | #[inline ] |
903 | pub(super) fn ret_c_int(raw: RetReg<R0>) -> io::Result<c::c_int> { |
904 | try_decode_c_int(raw) |
905 | } |
906 | |
907 | /// Convert a `usize` returned from a syscall that effectively returns a |
908 | /// `c_uint` on success. |
909 | #[inline ] |
910 | pub(super) fn ret_c_uint(raw: RetReg<R0>) -> io::Result<c::c_uint> { |
911 | try_decode_c_uint(raw) |
912 | } |
913 | |
914 | /// Convert a `usize` returned from a syscall that effectively returns a `u64` |
915 | /// on success. |
916 | #[cfg (target_pointer_width = "64" )] |
917 | #[inline ] |
918 | pub(super) fn ret_u64(raw: RetReg<R0>) -> io::Result<u64> { |
919 | try_decode_u64(raw) |
920 | } |
921 | |
922 | /// Convert a `usize` returned from a syscall that effectively returns a |
923 | /// `usize` on success. |
924 | #[inline ] |
925 | pub(super) fn ret_usize(raw: RetReg<R0>) -> io::Result<usize> { |
926 | try_decode_usize(raw) |
927 | } |
928 | |
929 | /// Convert a `usize` returned from a syscall that effectively always |
930 | /// returns a `usize`. |
931 | /// |
932 | /// # Safety |
933 | /// |
934 | /// This function must only be used with return values from infallible |
935 | /// syscalls. |
936 | #[inline ] |
937 | pub(super) unsafe fn ret_usize_infallible(raw: RetReg<R0>) -> usize { |
938 | #[cfg (debug_assertions)] |
939 | { |
940 | try_decode_usize(raw).unwrap() |
941 | } |
942 | #[cfg (not(debug_assertions))] |
943 | { |
944 | decode_usize_infallible(raw) |
945 | } |
946 | } |
947 | |
948 | /// Convert a `c_int` returned from a syscall that effectively always |
949 | /// returns a `c_int`. |
950 | /// |
951 | /// # Safety |
952 | /// |
953 | /// This function must only be used with return values from infallible |
954 | /// syscalls. |
955 | #[inline ] |
956 | pub(super) unsafe fn ret_c_int_infallible(raw: RetReg<R0>) -> c::c_int { |
957 | #[cfg (debug_assertions)] |
958 | { |
959 | try_decode_c_int(raw).unwrap() |
960 | } |
961 | #[cfg (not(debug_assertions))] |
962 | { |
963 | decode_c_int_infallible(raw) |
964 | } |
965 | } |
966 | |
967 | /// Convert a `c_uint` returned from a syscall that effectively always |
968 | /// returns a `c_uint`. |
969 | /// |
970 | /// # Safety |
971 | /// |
972 | /// This function must only be used with return values from infallible |
973 | /// syscalls. |
974 | #[inline ] |
975 | pub(super) unsafe fn ret_c_uint_infallible(raw: RetReg<R0>) -> c::c_uint { |
976 | #[cfg (debug_assertions)] |
977 | { |
978 | try_decode_c_uint(raw).unwrap() |
979 | } |
980 | #[cfg (not(debug_assertions))] |
981 | { |
982 | decode_c_uint_infallible(raw) |
983 | } |
984 | } |
985 | |
986 | /// Convert a `usize` returned from a syscall that effectively returns an |
987 | /// `OwnedFd` on success. |
988 | /// |
989 | /// # Safety |
990 | /// |
991 | /// The caller must ensure that this is the return value of a syscall which |
992 | /// returns an owned file descriptor. |
993 | #[inline ] |
994 | pub(super) unsafe fn ret_owned_fd(raw: RetReg<R0>) -> io::Result<OwnedFd> { |
995 | let raw_fd = try_decode_raw_fd(raw)?; |
996 | Ok(crate::backend::fd::OwnedFd::from_raw_fd(raw_fd)) |
997 | } |
998 | |
999 | /// Convert the return value of `dup2` and `dup3`. |
1000 | /// |
1001 | /// When these functions succeed, they return the same value as their second |
1002 | /// argument, so we don't construct a new `OwnedFd`. |
1003 | /// |
1004 | /// # Safety |
1005 | /// |
1006 | /// The caller must ensure that this is the return value of a syscall which |
1007 | /// returns a file descriptor. |
1008 | #[inline ] |
1009 | pub(super) unsafe fn ret_discarded_fd(raw: RetReg<R0>) -> io::Result<()> { |
1010 | let _raw_fd = try_decode_raw_fd(raw)?; |
1011 | Ok(()) |
1012 | } |
1013 | |
1014 | /// Convert a `usize` returned from a syscall that effectively returns a |
1015 | /// `*mut c_void` on success. |
1016 | #[inline ] |
1017 | pub(super) fn ret_void_star(raw: RetReg<R0>) -> io::Result<*mut c::c_void> { |
1018 | try_decode_void_star(raw) |
1019 | } |
1020 | |