/rust/registry/src/index.crates.io-6f17d22bba15001f/rustix-1.0.7/src/ioctl/patterns.rs
Line | Count | Source (jump to first uncovered line) |
1 | | //! Implements typical patterns for `ioctl` usage. |
2 | | |
3 | | use super::{Ioctl, IoctlOutput, Opcode}; |
4 | | |
5 | | use crate::backend::c; |
6 | | use crate::io::Result; |
7 | | |
8 | | use core::ptr::addr_of_mut; |
9 | | use core::{fmt, mem}; |
10 | | |
11 | | /// Implements an `ioctl` with no real arguments. |
12 | | /// |
13 | | /// To compute a value for the `OPCODE` argument, see the functions in the |
14 | | /// [`opcode`] module. |
15 | | /// |
16 | | /// [`opcode`]: crate::ioctl::opcode |
17 | | pub struct NoArg<const OPCODE: Opcode> {} |
18 | | |
19 | | impl<const OPCODE: Opcode> fmt::Debug for NoArg<OPCODE> { |
20 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
21 | 0 | f.debug_tuple("NoArg").field(&OPCODE).finish() |
22 | 0 | } |
23 | | } |
24 | | |
25 | | impl<const OPCODE: Opcode> NoArg<OPCODE> { |
26 | | /// Create a new no-argument `ioctl` object. |
27 | | /// |
28 | | /// # Safety |
29 | | /// |
30 | | /// - `OPCODE` must provide a valid opcode. |
31 | | #[inline] |
32 | 0 | pub const unsafe fn new() -> Self { |
33 | 0 | Self {} |
34 | 0 | } |
35 | | } |
36 | | |
37 | | unsafe impl<const OPCODE: Opcode> Ioctl for NoArg<OPCODE> { |
38 | | type Output = (); |
39 | | |
40 | | const IS_MUTATING: bool = false; |
41 | | |
42 | 0 | fn opcode(&self) -> self::Opcode { |
43 | 0 | OPCODE |
44 | 0 | } |
45 | | |
46 | 0 | fn as_ptr(&mut self) -> *mut c::c_void { |
47 | 0 | core::ptr::null_mut() |
48 | 0 | } |
49 | | |
50 | 0 | unsafe fn output_from_ptr(_: IoctlOutput, _: *mut c::c_void) -> Result<Self::Output> { |
51 | 0 | Ok(()) |
52 | 0 | } |
53 | | } |
54 | | |
55 | | /// Implements the traditional “getter” pattern for `ioctl`s. |
56 | | /// |
57 | | /// Some `ioctl`s just read data into the userspace. As this is a popular |
58 | | /// pattern, this structure implements it. |
59 | | /// |
60 | | /// To compute a value for the `OPCODE` argument, see the functions in the |
61 | | /// [`opcode`] module. |
62 | | /// |
63 | | /// [`opcode`]: crate::ioctl::opcode |
64 | | pub struct Getter<const OPCODE: Opcode, Output> { |
65 | | /// The output data. |
66 | | output: mem::MaybeUninit<Output>, |
67 | | } |
68 | | |
69 | | impl<const OPCODE: Opcode, Output> fmt::Debug for Getter<OPCODE, Output> { |
70 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
71 | 0 | f.debug_tuple("Getter").field(&OPCODE).finish() |
72 | 0 | } |
73 | | } |
74 | | |
75 | | impl<const OPCODE: Opcode, Output> Getter<OPCODE, Output> { |
76 | | /// Create a new getter-style `ioctl` object. |
77 | | /// |
78 | | /// # Safety |
79 | | /// |
80 | | /// - `OPCODE` must provide a valid opcode. |
81 | | /// - For this opcode, `Output` must be the type that the kernel expects |
82 | | /// to write into. |
83 | | #[inline] |
84 | 0 | pub const unsafe fn new() -> Self { |
85 | 0 | Self { |
86 | 0 | output: mem::MaybeUninit::uninit(), |
87 | 0 | } |
88 | 0 | } |
89 | | } |
90 | | |
91 | | unsafe impl<const OPCODE: Opcode, Output> Ioctl for Getter<OPCODE, Output> { |
92 | | type Output = Output; |
93 | | |
94 | | const IS_MUTATING: bool = true; |
95 | | |
96 | 0 | fn opcode(&self) -> self::Opcode { |
97 | 0 | OPCODE |
98 | 0 | } |
99 | | |
100 | 0 | fn as_ptr(&mut self) -> *mut c::c_void { |
101 | 0 | self.output.as_mut_ptr().cast() |
102 | 0 | } |
103 | | |
104 | 0 | unsafe fn output_from_ptr(_: IoctlOutput, ptr: *mut c::c_void) -> Result<Self::Output> { |
105 | 0 | Ok(ptr.cast::<Output>().read()) |
106 | 0 | } |
107 | | } |
108 | | |
109 | | /// Implements the pattern for `ioctl`s where a pointer argument is given to |
110 | | /// the `ioctl`. |
111 | | /// |
112 | | /// The opcode must be read-only. |
113 | | /// |
114 | | /// To compute a value for the `OPCODE` argument, see the functions in the |
115 | | /// [`opcode`] module. |
116 | | /// |
117 | | /// [`opcode`]: crate::ioctl::opcode |
118 | | pub struct Setter<const OPCODE: Opcode, Input> { |
119 | | /// The input data. |
120 | | input: Input, |
121 | | } |
122 | | |
123 | | impl<const OPCODE: Opcode, Input: fmt::Debug> fmt::Debug for Setter<OPCODE, Input> { |
124 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
125 | 0 | f.debug_tuple("Setter") |
126 | 0 | .field(&OPCODE) |
127 | 0 | .field(&self.input) |
128 | 0 | .finish() |
129 | 0 | } |
130 | | } |
131 | | |
132 | | impl<const OPCODE: Opcode, Input> Setter<OPCODE, Input> { |
133 | | /// Create a new pointer setter-style `ioctl` object. |
134 | | /// |
135 | | /// # Safety |
136 | | /// |
137 | | /// - `OPCODE` must provide a valid opcode. |
138 | | /// - For this opcode, `Input` must be the type that the kernel expects to |
139 | | /// get. |
140 | | #[inline] |
141 | 0 | pub const unsafe fn new(input: Input) -> Self { |
142 | 0 | Self { input } |
143 | 0 | } |
144 | | } |
145 | | |
146 | | unsafe impl<const OPCODE: Opcode, Input> Ioctl for Setter<OPCODE, Input> { |
147 | | type Output = (); |
148 | | |
149 | | const IS_MUTATING: bool = false; |
150 | | |
151 | 0 | fn opcode(&self) -> self::Opcode { |
152 | 0 | OPCODE |
153 | 0 | } |
154 | | |
155 | 0 | fn as_ptr(&mut self) -> *mut c::c_void { |
156 | 0 | addr_of_mut!(self.input).cast::<c::c_void>() |
157 | 0 | } |
158 | | |
159 | 0 | unsafe fn output_from_ptr(_: IoctlOutput, _: *mut c::c_void) -> Result<Self::Output> { |
160 | 0 | Ok(()) |
161 | 0 | } |
162 | | } |
163 | | |
164 | | /// Implements an “updater” pattern for `ioctl`s. |
165 | | /// |
166 | | /// The ioctl takes a reference to a struct that it reads its input from, |
167 | | /// then writes output to the same struct. |
168 | | /// |
169 | | /// To compute a value for the `OPCODE` argument, see the functions in the |
170 | | /// [`opcode`] module. |
171 | | /// |
172 | | /// [`opcode`]: crate::ioctl::opcode |
173 | | pub struct Updater<'a, const OPCODE: Opcode, Value> { |
174 | | /// Reference to input/output data. |
175 | | value: &'a mut Value, |
176 | | } |
177 | | |
178 | | impl<'a, const OPCODE: Opcode, Value> Updater<'a, OPCODE, Value> { |
179 | | /// Create a new pointer updater-style `ioctl` object. |
180 | | /// |
181 | | /// # Safety |
182 | | /// |
183 | | /// - `OPCODE` must provide a valid opcode. |
184 | | /// - For this opcode, `Value` must be the type that the kernel expects to |
185 | | /// get. |
186 | | #[inline] |
187 | 0 | pub unsafe fn new(value: &'a mut Value) -> Self { |
188 | 0 | Self { value } |
189 | 0 | } |
190 | | } |
191 | | |
192 | | unsafe impl<'a, const OPCODE: Opcode, T> Ioctl for Updater<'a, OPCODE, T> { |
193 | | type Output = (); |
194 | | |
195 | | const IS_MUTATING: bool = true; |
196 | | |
197 | 0 | fn opcode(&self) -> self::Opcode { |
198 | 0 | OPCODE |
199 | 0 | } |
200 | | |
201 | 0 | fn as_ptr(&mut self) -> *mut c::c_void { |
202 | 0 | (self.value as *mut T).cast() |
203 | 0 | } |
204 | | |
205 | 0 | unsafe fn output_from_ptr(_output: IoctlOutput, _ptr: *mut c::c_void) -> Result<()> { |
206 | 0 | Ok(()) |
207 | 0 | } |
208 | | } |
209 | | |
210 | | /// Implements an `ioctl` that passes an integer into the `ioctl`. |
211 | | /// |
212 | | /// To compute a value for the `OPCODE` argument, see the functions in the |
213 | | /// [`opcode`] module. |
214 | | /// |
215 | | /// [`opcode`]: crate::ioctl::opcode |
216 | | pub struct IntegerSetter<const OPCODE: Opcode> { |
217 | | /// The value to pass in. |
218 | | /// |
219 | | /// For strict provenance preservation, this is a pointer. |
220 | | value: *mut c::c_void, |
221 | | } |
222 | | |
223 | | impl<const OPCODE: Opcode> IntegerSetter<OPCODE> { |
224 | | /// Create a new integer `Ioctl` helper containing a `usize`. |
225 | | /// |
226 | | /// # Safety |
227 | | /// |
228 | | /// - `OPCODE` must provide a valid opcode. |
229 | | /// - For this opcode, it must expect an integer. |
230 | | /// - The integer is in the valid range for this opcode. |
231 | | #[inline] |
232 | 0 | pub const unsafe fn new_usize(value: usize) -> Self { |
233 | 0 | Self { value: value as _ } |
234 | 0 | } |
235 | | |
236 | | /// Create a new integer `Ioctl` helper containing a `*mut c_void`. |
237 | | /// |
238 | | /// # Safety |
239 | | /// |
240 | | /// - `OPCODE` must provide a valid opcode. |
241 | | /// - For this opcode, it must expect an integer. |
242 | | /// - The integer is in the valid range for this opcode. |
243 | | #[inline] |
244 | 0 | pub const unsafe fn new_pointer(value: *mut c::c_void) -> Self { |
245 | 0 | Self { value } |
246 | 0 | } |
247 | | } |
248 | | |
249 | | unsafe impl<const OPCODE: Opcode> Ioctl for IntegerSetter<OPCODE> { |
250 | | type Output = (); |
251 | | |
252 | | const IS_MUTATING: bool = false; |
253 | | |
254 | 0 | fn opcode(&self) -> self::Opcode { |
255 | 0 | OPCODE |
256 | 0 | } |
257 | | |
258 | 0 | fn as_ptr(&mut self) -> *mut c::c_void { |
259 | 0 | self.value |
260 | 0 | } |
261 | | |
262 | 0 | unsafe fn output_from_ptr( |
263 | 0 | _out: IoctlOutput, |
264 | 0 | _extract_output: *mut c::c_void, |
265 | 0 | ) -> Result<Self::Output> { |
266 | 0 | Ok(()) |
267 | 0 | } |
268 | | } |