Skip to content

Commit b9a8fcd

Browse files
committed
fixup! File: preadv2: Call the syscall directly rather than via glibc
1 parent 35667af commit b9a8fcd

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

tokio/src/fs/file.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -843,7 +843,7 @@ mod preadv2 {
843843

844844
#[test]
845845
fn test_preadv2_safe() {
846-
use std::io::Write;
846+
use std::io::{Seek, Write};
847847
use std::mem::MaybeUninit;
848848
use tempfile::tempdir;
849849

@@ -883,6 +883,19 @@ mod preadv2 {
883883
br.clear();
884884
preadv2_safe(&f, &mut br, -1, 0).unwrap();
885885
assert_eq!(br.filled(), b" test");
886+
887+
// Test handling large offsets
888+
{
889+
// I hope the underlying filesystem supports sparse files
890+
let mut w = std::fs::OpenOptions::new().write(true).open(&filename).unwrap();
891+
w.set_len(0x1_0000_0000).unwrap();
892+
w.seek(std::io::SeekFrom::Start(0x1_0000_0000)).unwrap();
893+
w.write(b"This is a Large File").unwrap();
894+
}
895+
896+
br.clear();
897+
preadv2_safe(&f, &mut br, 0x1_0000_0008, 0).unwrap();
898+
assert_eq!(br.filled(), b"a Large File");
886899
}
887900
}
888901

@@ -900,14 +913,18 @@ mod preadv2 {
900913
)
901914
}
902915

903-
const RWF_NOWAIT: c_int = 0x00000008;
916+
pub(crate) const RWF_NOWAIT: c_int = 0x00000008;
904917
unsafe fn preadv2(
905918
fd: c_int,
906919
iov: *const iovec,
907920
iovcnt: c_int,
908921
offset: off_t,
909922
flags: c_int,
910923
) -> ssize_t {
924+
// Call via libc::syscall rather than libc::preadv2. preadv2 is only supported by glibc
925+
// and only since v2.26. By using syscall we don't need to worry about compatiblity with
926+
// old glibc versions and it will work on Android and musl too. The downside is that you
927+
// can't use `LD_PRELOAD` tricks any more to intercept these calls.
911928
let (lo, hi) = pos_to_lohi(offset);
912929
libc::syscall(libc::SYS_preadv2, fd, iov, iovcnt, lo, hi, flags) as ssize_t
913930
}

0 commit comments

Comments
 (0)