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 (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(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) -> ArgReg<'a, Num> { |
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) -> ArgReg<'a, Num> { |
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: &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 >= 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: *mut T = v.as_ptr() as *mut T; |
191 | raw_arg(raw: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(raw: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(raw: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: *mut T = as_ptr(t) as *mut T; |
216 | raw_arg(raw: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(raw: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: &mut T) => by_mut(t), |
232 | None => raw_arg(raw: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 = "runtime" , |
307 | feature = "time" , |
308 | target_arch = "x86" , |
309 | ) |
310 | ) |
311 | ))] |
312 | pub(crate) mod fs { |
313 | use super::*; |
314 | use crate::fs::{FileType, Mode, OFlags}; |
315 | #[cfg (target_pointer_width = "32" )] |
316 | use linux_raw_sys::general::O_LARGEFILE; |
317 | |
318 | impl<'a, Num: ArgNumber> From<Mode> for ArgReg<'a, Num> { |
319 | #[inline ] |
320 | fn from(mode: Mode) -> Self { |
321 | pass_usize(mode.bits() as usize) |
322 | } |
323 | } |
324 | |
325 | impl<'a, Num: ArgNumber> From<(Mode, FileType)> for ArgReg<'a, Num> { |
326 | #[inline ] |
327 | fn from(pair: (Mode, FileType)) -> Self { |
328 | pass_usize(pair.0.as_raw_mode() as usize | pair.1.as_raw_mode() as usize) |
329 | } |
330 | } |
331 | |
332 | impl<'a, Num: ArgNumber> From<crate::fs::AtFlags> for ArgReg<'a, Num> { |
333 | #[inline ] |
334 | fn from(flags: crate::fs::AtFlags) -> Self { |
335 | c_uint(flags.bits()) |
336 | } |
337 | } |
338 | |
339 | impl<'a, Num: ArgNumber> From<crate::fs::XattrFlags> for ArgReg<'a, Num> { |
340 | #[inline ] |
341 | fn from(flags: crate::fs::XattrFlags) -> Self { |
342 | c_uint(flags.bits()) |
343 | } |
344 | } |
345 | |
346 | impl<'a, Num: ArgNumber> From<crate::fs::inotify::CreateFlags> for ArgReg<'a, Num> { |
347 | #[inline ] |
348 | fn from(flags: crate::fs::inotify::CreateFlags) -> Self { |
349 | c_uint(flags.bits()) |
350 | } |
351 | } |
352 | |
353 | impl<'a, Num: ArgNumber> From<crate::fs::inotify::WatchFlags> for ArgReg<'a, Num> { |
354 | #[inline ] |
355 | fn from(flags: crate::fs::inotify::WatchFlags) -> Self { |
356 | c_uint(flags.bits()) |
357 | } |
358 | } |
359 | |
360 | impl<'a, Num: ArgNumber> From<crate::fs::MemfdFlags> for ArgReg<'a, Num> { |
361 | #[inline ] |
362 | fn from(flags: crate::fs::MemfdFlags) -> Self { |
363 | c_uint(flags.bits()) |
364 | } |
365 | } |
366 | |
367 | impl<'a, Num: ArgNumber> From<crate::fs::RenameFlags> for ArgReg<'a, Num> { |
368 | #[inline ] |
369 | fn from(flags: crate::fs::RenameFlags) -> Self { |
370 | c_uint(flags.bits()) |
371 | } |
372 | } |
373 | |
374 | impl<'a, Num: ArgNumber> From<crate::fs::StatxFlags> for ArgReg<'a, Num> { |
375 | #[inline ] |
376 | fn from(flags: crate::fs::StatxFlags) -> Self { |
377 | c_uint(flags.bits()) |
378 | } |
379 | } |
380 | |
381 | #[cfg (target_pointer_width = "32" )] |
382 | #[inline ] |
383 | fn oflags_bits(oflags: OFlags) -> c::c_uint { |
384 | let mut bits = oflags.bits(); |
385 | // Add `O_LARGEFILE`, unless `O_PATH` is set, as Linux returns `EINVAL` |
386 | // when both are set. |
387 | if !oflags.contains(OFlags::PATH) { |
388 | bits |= O_LARGEFILE; |
389 | } |
390 | bits |
391 | } |
392 | |
393 | #[cfg (target_pointer_width = "64" )] |
394 | #[inline ] |
395 | const fn oflags_bits(oflags: OFlags) -> c::c_uint { |
396 | oflags.bits() |
397 | } |
398 | |
399 | impl<'a, Num: ArgNumber> From<OFlags> for ArgReg<'a, Num> { |
400 | #[inline ] |
401 | fn from(oflags: OFlags) -> Self { |
402 | pass_usize(oflags_bits(oflags) as usize) |
403 | } |
404 | } |
405 | |
406 | /// Convert an `OFlags` into a `u64` for use in the `open_how` struct. |
407 | #[inline ] |
408 | pub(crate) fn oflags_for_open_how(oflags: OFlags) -> u64 { |
409 | u64::from(oflags_bits(oflags)) |
410 | } |
411 | |
412 | impl<'a, Num: ArgNumber> From<crate::fs::FallocateFlags> for ArgReg<'a, Num> { |
413 | #[inline ] |
414 | fn from(flags: crate::fs::FallocateFlags) -> Self { |
415 | c_uint(flags.bits()) |
416 | } |
417 | } |
418 | |
419 | impl<'a, Num: ArgNumber> From<crate::fs::Advice> for ArgReg<'a, Num> { |
420 | #[inline ] |
421 | fn from(advice: crate::fs::Advice) -> Self { |
422 | c_uint(advice as c::c_uint) |
423 | } |
424 | } |
425 | |
426 | impl<'a, Num: ArgNumber> From<crate::fs::SealFlags> for ArgReg<'a, Num> { |
427 | #[inline ] |
428 | fn from(flags: crate::fs::SealFlags) -> Self { |
429 | c_uint(flags.bits()) |
430 | } |
431 | } |
432 | |
433 | impl<'a, Num: ArgNumber> From<crate::fs::Access> for ArgReg<'a, Num> { |
434 | #[inline ] |
435 | fn from(access: crate::fs::Access) -> Self { |
436 | c_uint(access.bits()) |
437 | } |
438 | } |
439 | } |
440 | |
441 | #[cfg (any(feature = "fs" , feature = "mount" ))] |
442 | impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MountFlagsArg> for ArgReg<'a, Num> { |
443 | #[inline ] |
444 | fn from(flags: crate::backend::mount::types::MountFlagsArg) -> Self { |
445 | c_uint(flags.0) |
446 | } |
447 | } |
448 | |
449 | // When the deprecated "fs" aliases are removed, we can remove the "fs" |
450 | // here too. |
451 | #[cfg (any(feature = "fs" , feature = "mount" ))] |
452 | impl<'a, Num: ArgNumber> From<crate::backend::mount::types::UnmountFlags> for ArgReg<'a, Num> { |
453 | #[inline ] |
454 | fn from(flags: crate::backend::mount::types::UnmountFlags) -> Self { |
455 | c_uint(flags.bits()) |
456 | } |
457 | } |
458 | |
459 | #[cfg (feature = "mount" )] |
460 | impl<'a, Num: ArgNumber> From<crate::mount::FsConfigCmd> for ArgReg<'a, Num> { |
461 | #[inline ] |
462 | fn from(cmd: crate::mount::FsConfigCmd) -> Self { |
463 | c_uint(cmd as c::c_uint) |
464 | } |
465 | } |
466 | |
467 | #[cfg (feature = "mount" )] |
468 | impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsOpenFlags> for ArgReg<'a, Num> { |
469 | #[inline ] |
470 | fn from(flags: crate::backend::mount::types::FsOpenFlags) -> Self { |
471 | c_uint(flags.bits()) |
472 | } |
473 | } |
474 | |
475 | #[cfg (feature = "mount" )] |
476 | impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsMountFlags> for ArgReg<'a, Num> { |
477 | #[inline ] |
478 | fn from(flags: crate::backend::mount::types::FsMountFlags) -> Self { |
479 | c_uint(flags.bits()) |
480 | } |
481 | } |
482 | |
483 | #[cfg (feature = "mount" )] |
484 | impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MountAttrFlags> for ArgReg<'a, Num> { |
485 | #[inline ] |
486 | fn from(flags: crate::backend::mount::types::MountAttrFlags) -> Self { |
487 | c_uint(flags.bits()) |
488 | } |
489 | } |
490 | |
491 | #[cfg (feature = "mount" )] |
492 | impl<'a, Num: ArgNumber> From<crate::backend::mount::types::OpenTreeFlags> for ArgReg<'a, Num> { |
493 | #[inline ] |
494 | fn from(flags: crate::backend::mount::types::OpenTreeFlags) -> Self { |
495 | c_uint(flags.bits()) |
496 | } |
497 | } |
498 | |
499 | #[cfg (feature = "mount" )] |
500 | impl<'a, Num: ArgNumber> From<crate::backend::mount::types::FsPickFlags> for ArgReg<'a, Num> { |
501 | #[inline ] |
502 | fn from(flags: crate::backend::mount::types::FsPickFlags) -> Self { |
503 | c_uint(flags.bits()) |
504 | } |
505 | } |
506 | |
507 | #[cfg (feature = "mount" )] |
508 | impl<'a, Num: ArgNumber> From<crate::backend::mount::types::MoveMountFlags> for ArgReg<'a, Num> { |
509 | #[inline ] |
510 | fn from(flags: crate::backend::mount::types::MoveMountFlags) -> Self { |
511 | c_uint(flags.bits()) |
512 | } |
513 | } |
514 | |
515 | impl<'a, Num: ArgNumber> From<crate::io::FdFlags> for ArgReg<'a, Num> { |
516 | #[inline ] |
517 | fn from(flags: crate::io::FdFlags) -> Self { |
518 | c_uint(flags.bits()) |
519 | } |
520 | } |
521 | |
522 | #[cfg (feature = "pipe" )] |
523 | impl<'a, Num: ArgNumber> From<crate::pipe::PipeFlags> for ArgReg<'a, Num> { |
524 | #[inline ] |
525 | fn from(flags: crate::pipe::PipeFlags) -> Self { |
526 | c_uint(flags.bits()) |
527 | } |
528 | } |
529 | |
530 | #[cfg (feature = "pipe" )] |
531 | impl<'a, Num: ArgNumber> From<crate::pipe::SpliceFlags> for ArgReg<'a, Num> { |
532 | #[inline ] |
533 | fn from(flags: crate::pipe::SpliceFlags) -> Self { |
534 | c_uint(flags.bits()) |
535 | } |
536 | } |
537 | |
538 | impl<'a, Num: ArgNumber> From<crate::io::DupFlags> for ArgReg<'a, Num> { |
539 | #[inline ] |
540 | fn from(flags: crate::io::DupFlags) -> Self { |
541 | c_uint(flags.bits()) |
542 | } |
543 | } |
544 | |
545 | impl<'a, Num: ArgNumber> From<crate::io::ReadWriteFlags> for ArgReg<'a, Num> { |
546 | #[inline ] |
547 | fn from(flags: crate::io::ReadWriteFlags) -> Self { |
548 | c_uint(flags.bits()) |
549 | } |
550 | } |
551 | |
552 | #[cfg (feature = "process" )] |
553 | impl<'a, Num: ArgNumber> From<crate::process::PidfdFlags> for ArgReg<'a, Num> { |
554 | #[inline ] |
555 | fn from(flags: crate::process::PidfdFlags) -> Self { |
556 | c_uint(flags.bits()) |
557 | } |
558 | } |
559 | |
560 | #[cfg (feature = "pty" )] |
561 | impl<'a, Num: ArgNumber> From<crate::pty::OpenptFlags> for ArgReg<'a, Num> { |
562 | #[inline ] |
563 | fn from(flags: crate::pty::OpenptFlags) -> Self { |
564 | c_uint(flags.bits()) |
565 | } |
566 | } |
567 | |
568 | #[cfg (feature = "thread" )] |
569 | impl<'a, Num: ArgNumber> From<crate::thread::UnshareFlags> for ArgReg<'a, Num> { |
570 | #[inline ] |
571 | fn from(flags: crate::thread::UnshareFlags) -> Self { |
572 | c_uint(flags.bits()) |
573 | } |
574 | } |
575 | |
576 | #[cfg (feature = "event" )] |
577 | impl<'a, Num: ArgNumber> From<crate::event::EventfdFlags> for ArgReg<'a, Num> { |
578 | #[inline ] |
579 | fn from(flags: crate::event::EventfdFlags) -> Self { |
580 | c_uint(flags.bits()) |
581 | } |
582 | } |
583 | |
584 | #[cfg (feature = "event" )] |
585 | impl<'a, Num: ArgNumber> From<crate::event::epoll::CreateFlags> for ArgReg<'a, Num> { |
586 | #[inline ] |
587 | fn from(flags: crate::event::epoll::CreateFlags) -> Self { |
588 | c_uint(flags.bits()) |
589 | } |
590 | } |
591 | |
592 | #[cfg (feature = "mm" )] |
593 | impl<'a, Num: ArgNumber> From<crate::backend::mm::types::ProtFlags> for ArgReg<'a, Num> { |
594 | #[inline ] |
595 | fn from(flags: crate::backend::mm::types::ProtFlags) -> Self { |
596 | c_uint(flags.bits()) |
597 | } |
598 | } |
599 | |
600 | #[cfg (feature = "mm" )] |
601 | impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MsyncFlags> for ArgReg<'a, Num> { |
602 | #[inline ] |
603 | fn from(flags: crate::backend::mm::types::MsyncFlags) -> Self { |
604 | c_uint(flags.bits()) |
605 | } |
606 | } |
607 | |
608 | #[cfg (feature = "mm" )] |
609 | impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MremapFlags> for ArgReg<'a, Num> { |
610 | #[inline ] |
611 | fn from(flags: crate::backend::mm::types::MremapFlags) -> Self { |
612 | c_uint(flags.bits()) |
613 | } |
614 | } |
615 | |
616 | #[cfg (feature = "mm" )] |
617 | impl<'a, Num: ArgNumber> From<crate::backend::mm::types::MlockFlags> for ArgReg<'a, Num> { |
618 | #[inline ] |
619 | fn from(flags: crate::backend::mm::types::MlockFlags) -> Self { |
620 | c_uint(flags.bits()) |
621 | } |
622 | } |
623 | |
624 | #[cfg (feature = "mm" )] |
625 | #[cfg (any(linux_kernel, freebsdlike, netbsdlike))] |
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(raw: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(raw: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 (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: i32 = 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: i32 = 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 | |