Coverage Report

Created: 2025-07-11 06:22

/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
}