@@ -3,7 +3,7 @@ use crate::Test;
33use io_uring:: { cqueue, opcode, squeue, types, IoUring } ;
44use std:: ffi:: CString ;
55use std:: fs;
6- use std:: io:: Write ;
6+ use std:: io:: { Read , Write } ;
77use std:: os:: unix:: ffi:: OsStrExt ;
88use std:: os:: unix:: io:: { AsRawFd , FromRawFd , IntoRawFd } ;
99
@@ -810,3 +810,130 @@ pub fn test_file_splice<S: squeue::EntryMarker, C: cqueue::EntryMarker>(
810810
811811 Ok ( ( ) )
812812}
813+
814+ pub fn test_ftruncate < S : squeue:: EntryMarker , C : cqueue:: EntryMarker > (
815+ ring : & mut IoUring < S , C > ,
816+ test : & Test ,
817+ ) -> anyhow:: Result < ( ) > {
818+ require ! (
819+ test;
820+ test. probe. is_supported( opcode:: Ftruncate :: CODE ) ;
821+ ) ;
822+
823+ println ! ( "test ftruncate" ) ;
824+
825+ let dir = tempfile:: TempDir :: new_in ( "." ) ?;
826+ let dir = dir. path ( ) ;
827+ let file = dir. join ( "io-uring-test-file-input" ) ;
828+
829+ let input = & [ 0x9f ; 1024 ] ;
830+
831+ fs:: write ( & file, input) ?;
832+ let fd = fs:: OpenOptions :: new ( ) . write ( true ) . open ( & file) ?;
833+ let fd = types:: Fd ( fd. as_raw_fd ( ) ) ;
834+ let ftruncate_e = opcode:: Ftruncate :: new ( fd, 512 ) ;
835+
836+ unsafe {
837+ ring. submission ( )
838+ . push ( & ftruncate_e. build ( ) . user_data ( 0x33 ) . into ( ) )
839+ . expect ( "queue is full" ) ;
840+ }
841+
842+ ring. submit_and_wait ( 1 ) ?;
843+
844+ let cqes: Vec < cqueue:: Entry > = ring. completion ( ) . map ( Into :: into) . collect ( ) ;
845+
846+ assert_eq ! ( cqes. len( ) , 1 ) ;
847+ assert_eq ! ( cqes[ 0 ] . user_data( ) , 0x33 ) ;
848+ assert_eq ! ( cqes[ 0 ] . result( ) , 0 ) ;
849+ assert_eq ! (
850+ fs:: read( & file) . expect( "could not read truncated file" ) ,
851+ & input[ ..512 ]
852+ ) ;
853+
854+ let ftruncate_e = opcode:: Ftruncate :: new ( fd, 0 ) ;
855+
856+ unsafe {
857+ ring. submission ( )
858+ . push ( & ftruncate_e. build ( ) . user_data ( 0x34 ) . into ( ) )
859+ . expect ( "queue is full" ) ;
860+ }
861+
862+ ring. submit_and_wait ( 1 ) ?;
863+
864+ let cqes: Vec < cqueue:: Entry > = ring. completion ( ) . map ( Into :: into) . collect ( ) ;
865+
866+ assert_eq ! ( cqes. len( ) , 1 ) ;
867+ assert_eq ! ( cqes[ 0 ] . user_data( ) , 0x34 ) ;
868+ assert_eq ! ( cqes[ 0 ] . result( ) , 0 ) ;
869+ assert_eq ! (
870+ fs:: metadata( & file)
871+ . expect( "could not read truncated file" )
872+ . len( ) ,
873+ 0
874+ ) ;
875+
876+ Ok ( ( ) )
877+ }
878+
879+ pub fn test_fixed_fd_install < S : squeue:: EntryMarker , C : cqueue:: EntryMarker > (
880+ ring : & mut IoUring < S , C > ,
881+ test : & Test ,
882+ ) -> anyhow:: Result < ( ) > {
883+ require ! (
884+ test;
885+ test. probe. is_supported( opcode:: Read :: CODE ) ;
886+ test. probe. is_supported( opcode:: FixedFdInstall :: CODE ) ;
887+ ) ;
888+
889+ println ! ( "test fixed_fd_install" ) ;
890+
891+ let dir = tempfile:: TempDir :: new_in ( "." ) ?;
892+ let dir = dir. path ( ) ;
893+ let file = dir. join ( "io-uring-test-file-input" ) ;
894+
895+ let input = & [ 0x9f ; 1024 ] ;
896+ let mut output = vec ! [ 0 ; 1024 ] ;
897+
898+ fs:: write ( & file, input) ?;
899+ let fd = fs:: OpenOptions :: new ( ) . read ( true ) . open ( & file) ?;
900+ let fd = types:: Fd ( fd. as_raw_fd ( ) ) ;
901+ ring. submitter ( ) . register_files ( & [ fd. 0 ] ) ?;
902+ let fd = types:: Fixed ( 0 ) ;
903+
904+ let read_e = opcode:: Read :: new ( fd, output. as_mut_ptr ( ) , output. len ( ) as _ ) ;
905+ unsafe {
906+ ring. submission ( )
907+ . push ( & read_e. build ( ) . user_data ( 0x01 ) . into ( ) )
908+ . expect ( "queue is full" ) ;
909+ }
910+
911+ assert_eq ! ( ring. submit_and_wait( 1 ) ?, 1 ) ;
912+ let cqes: Vec < cqueue:: Entry > = ring. completion ( ) . map ( Into :: into) . collect ( ) ;
913+ assert_eq ! ( cqes. len( ) , 1 ) ;
914+ assert_eq ! ( cqes[ 0 ] . user_data( ) , 0x01 ) ;
915+ assert_eq ! ( cqes[ 0 ] . result( ) , 1024 ) ;
916+ assert_eq ! ( output, input) ;
917+
918+ let fixed_fd_install_e = opcode:: FixedFdInstall :: new ( fd, 0 ) ;
919+
920+ unsafe {
921+ ring. submission ( )
922+ . push ( & fixed_fd_install_e. build ( ) . user_data ( 0x02 ) . into ( ) )
923+ . expect ( "queue is full" ) ;
924+ }
925+
926+ ring. submit_and_wait ( 1 ) ?;
927+
928+ let cqes: Vec < cqueue:: Entry > = ring. completion ( ) . map ( Into :: into) . collect ( ) ;
929+
930+ assert_eq ! ( cqes. len( ) , 1 ) ;
931+ assert_eq ! ( cqes[ 0 ] . user_data( ) , 0x02 ) ;
932+ let fd = cqes[ 0 ] . result ( ) ;
933+ assert ! ( fd > 0 ) ;
934+ let mut file = unsafe { fs:: File :: from_raw_fd ( fd) } ;
935+ file. read_exact ( & mut output) ?;
936+ assert_eq ! ( output, input) ;
937+
938+ Ok ( ( ) )
939+ }
0 commit comments