1 | //! linux_raw syscalls supporting `rustix::pipe`. |
2 | //! |
3 | //! # Safety |
4 | //! |
5 | //! See the `rustix::backend` module documentation for details. |
6 | #![allow (unsafe_code, clippy::undocumented_unsafe_blocks)] |
7 | |
8 | use crate::backend::conv::{c_int, c_uint, opt_mut, pass_usize, ret, ret_usize, slice}; |
9 | use crate::backend::{c, MAX_IOV}; |
10 | use crate::fd::{BorrowedFd, OwnedFd}; |
11 | use crate::io; |
12 | use crate::pipe::{IoSliceRaw, PipeFlags, SpliceFlags}; |
13 | use core::cmp; |
14 | use core::mem::MaybeUninit; |
15 | use linux_raw_sys::general::{F_GETPIPE_SZ, F_SETPIPE_SZ}; |
16 | |
17 | #[inline ] |
18 | pub(crate) fn pipe() -> io::Result<(OwnedFd, OwnedFd)> { |
19 | // aarch64 and risc64 omit `__NR_pipe`. On mips, `__NR_pipe` uses a special |
20 | // calling convention, but using it is not worth complicating our syscall |
21 | // wrapping infrastructure at this time. |
22 | #[cfg (any( |
23 | target_arch = "aarch64" , |
24 | target_arch = "mips" , |
25 | target_arch = "mips32r6" , |
26 | target_arch = "mips64" , |
27 | target_arch = "mips64r6" , |
28 | target_arch = "riscv64" , |
29 | ))] |
30 | { |
31 | pipe_with(PipeFlags::empty()) |
32 | } |
33 | #[cfg (not(any( |
34 | target_arch = "aarch64" , |
35 | target_arch = "mips" , |
36 | target_arch = "mips32r6" , |
37 | target_arch = "mips64" , |
38 | target_arch = "mips64r6" , |
39 | target_arch = "riscv64" , |
40 | )))] |
41 | unsafe { |
42 | let mut result = MaybeUninit::<[OwnedFd; 2]>::uninit(); |
43 | ret(syscall!(__NR_pipe, &mut result))?; |
44 | let [p0, p1] = result.assume_init(); |
45 | Ok((p0, p1)) |
46 | } |
47 | } |
48 | |
49 | #[inline ] |
50 | pub(crate) fn pipe_with(flags: PipeFlags) -> io::Result<(OwnedFd, OwnedFd)> { |
51 | unsafe { |
52 | let mut result: MaybeUninit<[OwnedFd; 2]> = MaybeUninit::<[OwnedFd; 2]>::uninit(); |
53 | ret(raw:syscall!(__NR_pipe2, &mut result, flags))?; |
54 | let [p0: OwnedFd, p1: OwnedFd] = result.assume_init(); |
55 | Ok((p0, p1)) |
56 | } |
57 | } |
58 | |
59 | #[inline ] |
60 | pub fn splice( |
61 | fd_in: BorrowedFd<'_>, |
62 | off_in: Option<&mut u64>, |
63 | fd_out: BorrowedFd<'_>, |
64 | off_out: Option<&mut u64>, |
65 | len: usize, |
66 | flags: SpliceFlags, |
67 | ) -> io::Result<usize> { |
68 | unsafe { |
69 | ret_usize(raw:syscall!( |
70 | __NR_splice, |
71 | fd_in, |
72 | opt_mut(off_in), |
73 | fd_out, |
74 | opt_mut(off_out), |
75 | pass_usize(len), |
76 | flags |
77 | )) |
78 | } |
79 | } |
80 | |
81 | #[inline ] |
82 | pub unsafe fn vmsplice( |
83 | fd: BorrowedFd<'_>, |
84 | bufs: &[IoSliceRaw<'_>], |
85 | flags: SpliceFlags, |
86 | ) -> io::Result<usize> { |
87 | let (bufs_addr: ArgReg<'_, A1>, bufs_len: ArgReg<'_, A2>) = slice(&bufs[..cmp::min(v1:bufs.len(), MAX_IOV)]); |
88 | ret_usize(raw:syscall!(__NR_vmsplice, fd, bufs_addr, bufs_len, flags)) |
89 | } |
90 | |
91 | #[inline ] |
92 | pub fn tee( |
93 | fd_in: BorrowedFd<'_>, |
94 | fd_out: BorrowedFd<'_>, |
95 | len: usize, |
96 | flags: SpliceFlags, |
97 | ) -> io::Result<usize> { |
98 | unsafe { ret_usize(raw:syscall!(__NR_tee, fd_in, fd_out, pass_usize(len), flags)) } |
99 | } |
100 | |
101 | #[inline ] |
102 | pub(crate) fn fcntl_getpipe_sz(fd: BorrowedFd<'_>) -> io::Result<usize> { |
103 | #[cfg (target_pointer_width = "32" )] |
104 | unsafe { |
105 | ret_usize(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETPIPE_SZ))) |
106 | } |
107 | #[cfg (target_pointer_width = "64" )] |
108 | unsafe { |
109 | ret_usize(raw:syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETPIPE_SZ))) |
110 | } |
111 | } |
112 | |
113 | #[inline ] |
114 | pub(crate) fn fcntl_setpipe_sz(fd: BorrowedFd<'_>, size: usize) -> io::Result<()> { |
115 | let size: c::c_int = size.try_into().map_err(|_| io::Errno::PERM)?; |
116 | |
117 | #[cfg (target_pointer_width = "32" )] |
118 | unsafe { |
119 | ret(syscall_readonly!( |
120 | __NR_fcntl64, |
121 | fd, |
122 | c_uint(F_SETPIPE_SZ), |
123 | c_int(size) |
124 | )) |
125 | } |
126 | #[cfg (target_pointer_width = "64" )] |
127 | unsafe { |
128 | ret(raw:syscall_readonly!( |
129 | __NR_fcntl, |
130 | fd, |
131 | c_uint(F_SETPIPE_SZ), |
132 | c_int(size) |
133 | )) |
134 | } |
135 | } |
136 | |