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