1
- use core:: convert:: { TryFrom , TryInto } ;
1
+ use core:: convert:: TryInto ;
2
+ use core:: mem;
2
3
use core:: ops:: Range ;
3
- use core:: { mem, ptr} ;
4
4
5
5
use alloc:: boxed:: Box ;
6
6
use alloc:: vec;
@@ -9,8 +9,8 @@ use alloc::vec::Vec;
9
9
use crate :: bindings;
10
10
use crate :: c_types;
11
11
use crate :: error:: { Error , KernelResult } ;
12
+ use crate :: file_operations;
12
13
use crate :: types:: CStr ;
13
- use crate :: user_ptr:: { UserSlicePtr , UserSlicePtrWriter } ;
14
14
15
15
pub fn builder ( name : & ' static CStr , minors : Range < u16 > ) -> KernelResult < Builder > {
16
16
Ok ( Builder {
@@ -23,11 +23,11 @@ pub fn builder(name: &'static CStr, minors: Range<u16>) -> KernelResult<Builder>
23
23
pub struct Builder {
24
24
name : & ' static CStr ,
25
25
minors : Range < u16 > ,
26
- file_ops : Vec < & ' static FileOperationsVtable > ,
26
+ file_ops : Vec < & ' static file_operations :: FileOperationsVtable > ,
27
27
}
28
28
29
29
impl Builder {
30
- pub fn register_device < T : FileOperations > ( mut self ) -> Builder {
30
+ pub fn register_device < T : file_operations :: FileOperations > ( mut self ) -> Builder {
31
31
if self . file_ops . len ( ) >= self . minors . len ( ) {
32
32
panic ! ( "More devices registered than minor numbers allocated." )
33
33
}
@@ -95,174 +95,3 @@ impl Drop for Registration {
95
95
}
96
96
}
97
97
}
98
-
99
- pub struct File {
100
- ptr : * const bindings:: file ,
101
- }
102
-
103
- impl File {
104
- unsafe fn from_ptr ( ptr : * const bindings:: file ) -> File {
105
- File { ptr }
106
- }
107
-
108
- pub fn pos ( & self ) -> u64 {
109
- unsafe { ( * self . ptr ) . f_pos as u64 }
110
- }
111
- }
112
-
113
- // Matches std::io::SeekFrom in the Rust stdlib
114
- pub enum SeekFrom {
115
- Start ( u64 ) ,
116
- End ( i64 ) ,
117
- Current ( i64 ) ,
118
- }
119
-
120
- pub struct FileOperationsVtable ( bindings:: file_operations ) ;
121
-
122
- unsafe extern "C" fn open_callback < T : FileOperations > (
123
- _inode : * mut bindings:: inode ,
124
- file : * mut bindings:: file ,
125
- ) -> c_types:: c_int {
126
- let f = match T :: open ( ) {
127
- Ok ( f) => Box :: new ( f) ,
128
- Err ( e) => return e. to_kernel_errno ( ) ,
129
- } ;
130
- ( * file) . private_data = Box :: into_raw ( f) as * mut c_types:: c_void ;
131
- 0
132
- }
133
-
134
- unsafe extern "C" fn read_callback < T : FileOperations > (
135
- file : * mut bindings:: file ,
136
- buf : * mut c_types:: c_char ,
137
- len : c_types:: c_size_t ,
138
- offset : * mut bindings:: loff_t ,
139
- ) -> c_types:: c_ssize_t {
140
- let mut data = match UserSlicePtr :: new ( buf as * mut c_types:: c_void , len) {
141
- Ok ( ptr) => ptr. writer ( ) ,
142
- Err ( e) => return e. to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
143
- } ;
144
- let f = & * ( ( * file) . private_data as * const T ) ;
145
- // No FMODE_UNSIGNED_OFFSET support, so offset must be in [0, 2^63).
146
- // See discussion in #113
147
- let positive_offset = match ( * offset) . try_into ( ) {
148
- Ok ( v) => v,
149
- Err ( _) => return Error :: EINVAL . to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
150
- } ;
151
- match f. read ( & mut data, positive_offset) {
152
- Ok ( ( ) ) => {
153
- let written = len - data. len ( ) ;
154
- ( * offset) += bindings:: loff_t:: try_from ( written) . unwrap ( ) ;
155
- written. try_into ( ) . unwrap ( )
156
- }
157
- Err ( e) => e. to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
158
- }
159
- }
160
-
161
- unsafe extern "C" fn release_callback < T : FileOperations > (
162
- _inode : * mut bindings:: inode ,
163
- file : * mut bindings:: file ,
164
- ) -> c_types:: c_int {
165
- let ptr = mem:: replace ( & mut ( * file) . private_data , ptr:: null_mut ( ) ) ;
166
- drop ( Box :: from_raw ( ptr as * mut T ) ) ;
167
- 0
168
- }
169
-
170
- unsafe extern "C" fn llseek_callback < T : FileOperations > (
171
- file : * mut bindings:: file ,
172
- offset : bindings:: loff_t ,
173
- whence : c_types:: c_int ,
174
- ) -> bindings:: loff_t {
175
- let off = match whence as u32 {
176
- bindings:: SEEK_SET => match offset. try_into ( ) {
177
- Ok ( v) => SeekFrom :: Start ( v) ,
178
- Err ( _) => return Error :: EINVAL . to_kernel_errno ( ) . into ( ) ,
179
- } ,
180
- bindings:: SEEK_CUR => SeekFrom :: Current ( offset) ,
181
- bindings:: SEEK_END => SeekFrom :: End ( offset) ,
182
- _ => return Error :: EINVAL . to_kernel_errno ( ) . into ( ) ,
183
- } ;
184
- let f = & * ( ( * file) . private_data as * const T ) ;
185
- match f. seek ( & File :: from_ptr ( file) , off) {
186
- Ok ( off) => off as bindings:: loff_t ,
187
- Err ( e) => e. to_kernel_errno ( ) . into ( ) ,
188
- }
189
- }
190
-
191
- impl FileOperationsVtable {
192
- pub const fn new < T : FileOperations > ( ) -> FileOperationsVtable {
193
- FileOperationsVtable ( bindings:: file_operations {
194
- open : Some ( open_callback :: < T > ) ,
195
- read : Some ( read_callback :: < T > ) ,
196
- release : Some ( release_callback :: < T > ) ,
197
- llseek : Some ( llseek_callback :: < T > ) ,
198
-
199
- check_flags : None ,
200
- #[ cfg( not( kernel_4_20_0_or_greater) ) ]
201
- clone_file_range : None ,
202
- compat_ioctl : None ,
203
- copy_file_range : None ,
204
- #[ cfg( not( kernel_4_20_0_or_greater) ) ]
205
- dedupe_file_range : None ,
206
- fallocate : None ,
207
- #[ cfg( kernel_4_19_0_or_greater) ]
208
- fadvise : None ,
209
- fasync : None ,
210
- flock : None ,
211
- flush : None ,
212
- fsync : None ,
213
- get_unmapped_area : None ,
214
- iterate : None ,
215
- iterate_shared : None ,
216
- #[ cfg( kernel_5_1_0_or_greater) ]
217
- iopoll : None ,
218
- lock : None ,
219
- mmap : None ,
220
- #[ cfg( kernel_4_15_0_or_greater) ]
221
- mmap_supported_flags : 0 ,
222
- owner : ptr:: null_mut ( ) ,
223
- poll : None ,
224
- read_iter : None ,
225
- #[ cfg( kernel_4_20_0_or_greater) ]
226
- remap_file_range : None ,
227
- sendpage : None ,
228
- #[ cfg( kernel_aufs_setfl) ]
229
- setfl : None ,
230
- setlease : None ,
231
- show_fdinfo : None ,
232
- splice_read : None ,
233
- splice_write : None ,
234
- unlocked_ioctl : None ,
235
- write : None ,
236
- write_iter : None ,
237
- } )
238
- }
239
- }
240
-
241
- /// `FileOperations` corresponds to the kernel's `struct file_operations`. You
242
- /// implement this trait whenever you'd create a `struct file_operations`. File
243
- /// descriptors may be used from multiple threads (or processes) concurrently,
244
- /// so your type must be `Sync`.
245
- pub trait FileOperations : Sync + Sized {
246
- /// A container for the actual `file_operations` value. This will always be:
247
- /// ```
248
- /// const VTABLE: linux_kernel_module::chrdev::FileOperationsVtable =
249
- /// linux_kernel_module::chrdev::FileOperationsVtable::new::<Self>();
250
- /// ```
251
- const VTABLE : FileOperationsVtable ;
252
-
253
- /// Creates a new instance of this file. Corresponds to the `open` function
254
- /// pointer in `struct file_operations`.
255
- fn open ( ) -> KernelResult < Self > ;
256
-
257
- /// Reads data from this file to userspace. Corresponds to the `read`
258
- /// function pointer in `struct file_operations`.
259
- fn read ( & self , _buf : & mut UserSlicePtrWriter , _offset : u64 ) -> KernelResult < ( ) > {
260
- Err ( Error :: EINVAL )
261
- }
262
-
263
- /// Changes the position of the file. Corresponds to the `llseek` function
264
- /// pointer in `struct file_operations`.
265
- fn seek ( & self , _file : & File , _offset : SeekFrom ) -> KernelResult < u64 > {
266
- Err ( Error :: ESPIPE )
267
- }
268
- }
0 commit comments