1- use core:: convert:: { TryFrom , TryInto } ;
1+ use core:: convert:: TryInto ;
2+ use core:: mem;
23use core:: ops:: Range ;
3- use core:: { mem, ptr} ;
44
55use alloc:: boxed:: Box ;
66use alloc:: vec;
@@ -9,8 +9,8 @@ use alloc::vec::Vec;
99use crate :: bindings;
1010use crate :: c_types;
1111use crate :: error:: { Error , KernelResult } ;
12+ use crate :: file_operations;
1213use crate :: types:: CStr ;
13- use crate :: user_ptr:: { UserSlicePtr , UserSlicePtrWriter } ;
1414
1515pub fn builder ( name : & ' static CStr , minors : Range < u16 > ) -> KernelResult < Builder > {
1616 Ok ( Builder {
@@ -23,11 +23,11 @@ pub fn builder(name: &'static CStr, minors: Range<u16>) -> KernelResult<Builder>
2323pub struct Builder {
2424 name : & ' static CStr ,
2525 minors : Range < u16 > ,
26- file_ops : Vec < & ' static FileOperationsVtable > ,
26+ file_ops : Vec < & ' static file_operations :: FileOperationsVtable > ,
2727}
2828
2929impl Builder {
30- pub fn register_device < T : FileOperations > ( mut self ) -> Builder {
30+ pub fn register_device < T : file_operations :: FileOperations > ( mut self ) -> Builder {
3131 if self . file_ops . len ( ) >= self . minors . len ( ) {
3232 panic ! ( "More devices registered than minor numbers allocated." )
3333 }
@@ -95,174 +95,3 @@ impl Drop for Registration {
9595 }
9696 }
9797}
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