@@ -6,7 +6,7 @@ use alloc::boxed::Box;
66use crate :: bindings;
77use crate :: c_types;
88use crate :: error:: { Error , KernelResult } ;
9- use crate :: user_ptr:: { UserSlicePtr , UserSlicePtrWriter } ;
9+ use crate :: user_ptr:: { UserSlicePtr , UserSlicePtrReader , UserSlicePtrWriter } ;
1010
1111pub struct File {
1212 ptr : * const bindings:: file ,
@@ -70,6 +70,33 @@ unsafe extern "C" fn read_callback<T: Read>(
7070 }
7171}
7272
73+ unsafe extern "C" fn write_callback < T : Write > (
74+ file : * mut bindings:: file ,
75+ buf : * const c_types:: c_char ,
76+ len : c_types:: c_size_t ,
77+ offset : * mut bindings:: loff_t ,
78+ ) -> c_types:: c_ssize_t {
79+ let mut data = match UserSlicePtr :: new ( buf as * mut c_types:: c_void , len) {
80+ Ok ( ptr) => ptr. reader ( ) ,
81+ Err ( e) => return e. to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
82+ } ;
83+ let f = & * ( ( * file) . private_data as * const T ) ;
84+ // No FMODE_UNSIGNED_OFFSET support, so offset must be in [0, 2^63).
85+ // See discussion in #113
86+ let positive_offset = match ( * offset) . try_into ( ) {
87+ Ok ( v) => v,
88+ Err ( _) => return Error :: EINVAL . to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
89+ } ;
90+ match f. write ( & mut data, positive_offset) {
91+ Ok ( ( ) ) => {
92+ let read = len - data. len ( ) ;
93+ ( * offset) += bindings:: loff_t:: try_from ( read) . unwrap ( ) ;
94+ read. try_into ( ) . unwrap ( )
95+ }
96+ Err ( e) => e. to_kernel_errno ( ) . try_into ( ) . unwrap ( ) ,
97+ }
98+ }
99+
73100unsafe extern "C" fn release_callback < T : FileOperations > (
74101 _inode : * mut bindings:: inode ,
75102 file : * mut bindings:: file ,
@@ -168,6 +195,13 @@ impl<T: Read> FileOperationsVtableBuilder<T> {
168195 }
169196}
170197
198+ impl < T : Write > FileOperationsVtableBuilder < T > {
199+ pub const fn write ( mut self ) -> FileOperationsVtableBuilder < T > {
200+ self . 0 . write = Some ( write_callback :: < T > ) ;
201+ self
202+ }
203+ }
204+
171205impl < T : Seek > FileOperationsVtableBuilder < T > {
172206 pub const fn seek ( mut self ) -> FileOperationsVtableBuilder < T > {
173207 self . 0 . llseek = Some ( llseek_callback :: < T > ) ;
@@ -199,6 +233,12 @@ pub trait Read {
199233 fn read ( & self , buf : & mut UserSlicePtrWriter , offset : u64 ) -> KernelResult < ( ) > ;
200234}
201235
236+ pub trait Write {
237+ /// Writes data from userspace o this file. Corresponds to the `write`
238+ /// function pointer in `struct file_operations`.
239+ fn write ( & self , buf : & mut UserSlicePtrReader , offset : u64 ) -> KernelResult < ( ) > ;
240+ }
241+
202242pub trait Seek {
203243 /// Changes the position of the file. Corresponds to the `llseek` function
204244 /// pointer in `struct file_operations`.
0 commit comments