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 as _, BorrowedFd, FromRawFd as _, RawFd}; |
18 | #[cfg (any(feature = "event" , feature = "runtime" , feature = "system" ))] |
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" ))] |
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" ))] |
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(raw: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(raw: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) -> Self { |
111 | raw_arg(raw: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) -> Self { |
118 | let mut_ptr: *mut T = c as *mut T; |
119 | raw_arg(raw: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: *mut u8 = c.as_ptr() as *mut u8; |
127 | raw_arg(raw: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(raw:match t { |
135 | Some(s: &'a CStr) => { |
136 | let mut_ptr: *mut u8 = s.as_ptr() as *mut u8; |
137 | mut_ptr.cast() |
138 | } |
139 | None => null_mut(), |
140 | }) |
141 | } |
142 | } |
143 | |
144 | /// Pass a borrowed file-descriptor argument. |
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 == 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 ] |
181 | pub(super) fn no_fd<'a, Num: ArgNumber>() -> ArgReg<'a, Num> { |
182 | pass_usize(!0_usize) |
183 | } |
184 | |
185 | #[inline ] |
186 | pub(super) fn slice_just_addr<T: Sized, Num: ArgNumber>(v: &[T]) -> ArgReg<'_, Num> { |
187 | let mut_ptr: *mut T = v.as_ptr() as *mut T; |
188 | raw_arg(raw:mut_ptr.cast()) |
189 | } |
190 | |
191 | #[inline ] |
192 | pub(super) fn slice_just_addr_mut<T: Sized, Num: ArgNumber>(v: &mut [T]) -> ArgReg<'_, Num> { |
193 | raw_arg(raw:v.as_mut_ptr().cast()) |
194 | } |
195 | |
196 | #[inline ] |
197 | pub(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 ] |
204 | pub(super) fn slice_mut<T: Sized, Num0: ArgNumber, Num1: ArgNumber>( |
205 | v: &mut [T], |
206 | ) -> (ArgReg<'_, Num0>, ArgReg<'_, Num1>) { |
207 | (raw_arg(raw:v.as_mut_ptr().cast()), pass_usize(v.len())) |
208 | } |
209 | |
210 | #[inline ] |
211 | pub(super) fn by_ref<T: Sized, Num: ArgNumber>(t: &T) -> ArgReg<'_, Num> { |
212 | let mut_ptr: *mut T = as_ptr(t) as *mut T; |
213 | raw_arg(raw:mut_ptr.cast()) |
214 | } |
215 | |
216 | #[inline ] |
217 | pub(super) fn by_mut<T: Sized, Num: ArgNumber>(t: &mut T) -> ArgReg<'_, Num> { |
218 | raw_arg(raw:as_mut_ptr(t).cast()) |
219 | } |
220 | |
221 | /// Convert an optional mutable reference into a `usize` for passing to a |
222 | /// syscall. |
223 | #[inline ] |
224 | pub(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: &mut T) => by_mut(t), |
229 | None => raw_arg(raw:null_mut()), |
230 | } |
231 | } |
232 | |
233 | /// Convert an optional immutable reference into a `usize` for passing to a |
234 | /// syscall. |
235 | #[inline ] |
236 | pub(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: &T) => by_ref(t), |
241 | None => raw_arg(raw: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 ] |
249 | pub(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 ] |
255 | pub(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 ] |
261 | pub(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 ] |
267 | pub(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" ))] |
274 | impl<'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" )] |
282 | impl<'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 ] |
291 | pub(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 | ))] |
309 | pub(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" )] |
439 | impl<'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" )] |
447 | impl<'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" )] |
455 | impl<'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" )] |
463 | impl<'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" )] |
471 | impl<'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" )] |
479 | impl<'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" )] |
487 | impl<'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" )] |
495 | impl<'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" )] |
503 | impl<'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 | |
510 | impl<'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" )] |
518 | impl<'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" )] |
526 | impl<'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 | |
533 | impl<'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 | |
540 | impl<'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" )] |
548 | impl<'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" )] |
556 | impl<'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" )] |
564 | impl<'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" )] |
572 | impl<'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" )] |
580 | impl<'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" )] |
588 | impl<'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" )] |
596 | impl<'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" )] |
604 | impl<'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" )] |
612 | impl<'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" )] |
620 | impl<'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" )] |
628 | impl<'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" )] |
636 | impl<'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" )] |
644 | impl<'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" )] |
652 | impl<'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" )] |
662 | impl<'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 ] |
671 | pub(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 ] |
677 | pub(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" )] |
683 | impl<'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" ))] |
691 | impl<'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 ] |
700 | pub(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" ))] |
705 | impl<'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" )] |
713 | impl<'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" )] |
721 | impl<'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" )] |
729 | impl<'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" )] |
737 | impl<'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" )] |
745 | impl<'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" )] |
753 | impl<'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" )] |
761 | impl<'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" )] |
769 | impl<'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" )] |
777 | impl<'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" )] |
787 | impl<'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" )] |
805 | impl<'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" )] |
813 | impl<'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 | |
823 | impl<'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(raw:t.as_mut_ptr().cast()) |
827 | } |
828 | } |
829 | |
830 | impl<'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(raw:t.as_mut_ptr().cast()) |
834 | } |
835 | } |
836 | |
837 | #[cfg (any(feature = "process" , feature = "thread" ))] |
838 | impl<'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" ))] |
846 | impl<'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" )] |
854 | impl<'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 ] |
869 | pub(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 ] |
881 | pub(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 ] |
893 | pub(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 ] |
905 | pub(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 ] |
912 | pub(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 ] |
920 | pub(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 ] |
927 | pub(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 ] |
939 | pub(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 ] |
958 | pub(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 ] |
977 | pub(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 ] |
996 | pub(super) unsafe fn ret_owned_fd(raw: RetReg<R0>) -> io::Result<OwnedFd> { |
997 | let raw_fd: as Try>::Output = 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 ] |
1011 | pub(super) unsafe fn ret_discarded_fd(raw: RetReg<R0>) -> io::Result<()> { |
1012 | let _raw_fd: as Try>::Output = 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 ] |
1019 | pub(super) fn ret_void_star(raw: RetReg<R0>) -> io::Result<*mut c::c_void> { |
1020 | try_decode_void_star(raw) |
1021 | } |
1022 | |