@@ -10,7 +10,7 @@ use crate::bindings;
1010use crate :: c_types;
1111use crate :: error:: { Error , KernelResult } ;
1212use crate :: types:: CStr ;
13- use crate :: user_ptr:: { UserSlicePtr , UserSlicePtrWriter } ;
13+ use crate :: user_ptr:: { UserSlicePtr , UserSlicePtrReader , UserSlicePtrWriter } ;
1414
1515pub fn builder ( name : & ' static CStr , minors : Range < u16 > ) -> KernelResult < Builder > {
1616 Ok ( Builder {
@@ -158,6 +158,32 @@ unsafe extern "C" fn read_callback<T: FileOperations>(
158158 }
159159}
160160
161+ unsafe extern "C" fn write_callback < T : FileOperations > (
162+ file : * mut bindings:: file ,
163+ buf : * const c_types:: c_char ,
164+ len : c_types:: c_size_t ,
165+ offset : * mut bindings:: loff_t ,
166+ ) -> c_types:: c_ssize_t {
167+ let mut data = match UserSlicePtr :: new ( buf as * mut c_types:: c_void , len) {
168+ Ok ( ptr) => ptr. reader ( ) ,
169+ Err ( e) => return e. to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
170+ } ;
171+ let f = & * ( ( * file) . private_data as * const T ) ;
172+ // No FMODE_UNSIGNED_OFFSET support, so offset must be in [0, 2^63).
173+ // See discussion in #113
174+ let positive_offset = match ( * offset) . try_into ( ) {
175+ Ok ( v) => v,
176+ Err ( _) => return Error :: EINVAL . to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
177+ } ;
178+ match f. write ( & mut data, positive_offset) {
179+ Ok ( ( ) ) => {
180+ let read = len - data. len ( ) ;
181+ read. try_into ( ) . unwrap ( )
182+ }
183+ Err ( e) => e. to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
184+ }
185+ }
186+
161187unsafe extern "C" fn release_callback < T : FileOperations > (
162188 _inode : * mut bindings:: inode ,
163189 file : * mut bindings:: file ,
@@ -193,6 +219,7 @@ impl FileOperationsVtable {
193219 FileOperationsVtable ( bindings:: file_operations {
194220 open : Some ( open_callback :: < T > ) ,
195221 read : Some ( read_callback :: < T > ) ,
222+ write : Some ( write_callback :: < T > ) ,
196223 release : Some ( release_callback :: < T > ) ,
197224 llseek : Some ( llseek_callback :: < T > ) ,
198225
@@ -232,7 +259,6 @@ impl FileOperationsVtable {
232259 splice_read : None ,
233260 splice_write : None ,
234261 unlocked_ioctl : None ,
235- write : None ,
236262 write_iter : None ,
237263 } )
238264 }
@@ -260,6 +286,12 @@ pub trait FileOperations: Sync + Sized {
260286 Err ( Error :: EINVAL )
261287 }
262288
289+ /// Writes data from userspace o this file. Corresponds to the `write`
290+ /// function pointer in `struct file_operations`.
291+ fn write ( & self , _buf : & mut UserSlicePtrReader , _offset : u64 ) -> KernelResult < ( ) > {
292+ Err ( Error :: EINVAL )
293+ }
294+
263295 /// Changes the position of the file. Corresponds to the `llseek` function
264296 /// pointer in `struct file_operations`.
265297 fn seek ( & self , _file : & File , _offset : SeekFrom ) -> KernelResult < u64 > {
0 commit comments