@@ -843,7 +843,7 @@ mod preadv2 {
843
843
844
844
#[ test]
845
845
fn test_preadv2_safe ( ) {
846
- use std:: io:: Write ;
846
+ use std:: io:: { Seek , Write } ;
847
847
use std:: mem:: MaybeUninit ;
848
848
use tempfile:: tempdir;
849
849
@@ -894,6 +894,22 @@ mod preadv2 {
894
894
Some ( libc:: ENOTSUP ) | Some ( libc:: EAGAIN )
895
895
) ) ,
896
896
}
897
+
898
+ // Test handling large offsets
899
+ {
900
+ // I hope the underlying filesystem supports sparse files
901
+ let mut w = std:: fs:: OpenOptions :: new ( )
902
+ . write ( true )
903
+ . open ( & filename)
904
+ . unwrap ( ) ;
905
+ w. set_len ( 0x1_0000_0000 ) . unwrap ( ) ;
906
+ w. seek ( std:: io:: SeekFrom :: Start ( 0x1_0000_0000 ) ) . unwrap ( ) ;
907
+ w. write ( b"This is a Large File" ) . unwrap ( ) ;
908
+ }
909
+
910
+ br. clear ( ) ;
911
+ preadv2_safe ( & f, & mut br, 0x1_0000_0008 , 0 ) . unwrap ( ) ;
912
+ assert_eq ! ( br. filled( ) , b"a Large File" ) ;
897
913
}
898
914
}
899
915
@@ -919,6 +935,10 @@ mod preadv2 {
919
935
offset : off_t ,
920
936
flags : c_int ,
921
937
) -> ssize_t {
938
+ // Call via libc::syscall rather than libc::preadv2. preadv2 is only supported by glibc
939
+ // and only since v2.26. By using syscall we don't need to worry about compatiblity with
940
+ // old glibc versions and it will work on Android and musl too. The downside is that you
941
+ // can't use `LD_PRELOAD` tricks any more to intercept these calls.
922
942
let ( lo, hi) = pos_to_lohi ( offset) ;
923
943
libc:: syscall ( libc:: SYS_preadv2 , fd, iov, iovcnt, lo, hi, flags) as ssize_t
924
944
}
0 commit comments