-
Notifications
You must be signed in to change notification settings - Fork 135
/
seek.rs
79 lines (69 loc) · 2.42 KB
/
seek.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/// Test seek positions related to file "holes".
#[cfg(any(apple, freebsdlike, linux_kernel, solarish))]
#[test]
fn test_seek_holes() {
use rustix::fs::{fstat, openat, seek, Mode, OFlags, SeekFrom, CWD};
use std::io::Write;
let tmp = tempfile::tempdir().unwrap();
let dir = openat(CWD, tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();
let foo = openat(
&dir,
"foo",
OFlags::RDWR | OFlags::CREATE | OFlags::TRUNC,
Mode::RUSR | Mode::WUSR,
)
.unwrap();
let mut foo = std::fs::File::from(foo);
let stat = fstat(&foo).unwrap();
let hole_size = stat.st_blksize as u64;
#[cfg(any(solarish, freebsdlike, netbsdlike))]
let hole_size = unsafe {
use std::os::unix::io::AsRawFd;
let r = libc::fpathconf(foo.as_raw_fd(), libc::_PC_MIN_HOLE_SIZE);
if r < 0 {
// Holes not supported.
return;
}
// Holes are supported.
core::cmp::max(hole_size, r as u64)
};
foo.write_all(b"prefix").unwrap();
assert_eq!(
seek(&foo, SeekFrom::Start(hole_size * 2)),
Ok(hole_size * 2)
);
foo.write_all(b"suffix").unwrap();
assert_eq!(seek(&foo, SeekFrom::Start(0)), Ok(0));
assert_eq!(seek(&foo, SeekFrom::Current(0)), Ok(0));
assert_eq!(seek(&foo, SeekFrom::Hole(0)), Ok(hole_size));
assert_eq!(seek(&foo, SeekFrom::Hole(hole_size as i64)), Ok(hole_size));
assert_eq!(
seek(&foo, SeekFrom::Hole(hole_size as i64 * 2)),
Ok(hole_size * 2 + 6)
);
assert_eq!(seek(&foo, SeekFrom::Data(0)), Ok(0));
assert_eq!(
seek(&foo, SeekFrom::Data(hole_size as i64)),
Ok(hole_size * 2)
);
assert_eq!(
seek(&foo, SeekFrom::Data(hole_size as i64 * 2)),
Ok(hole_size * 2)
);
}
#[test]
fn test_seek_offsets() {
use rustix::fs::{openat, seek, Mode, OFlags, SeekFrom, CWD};
let f = openat(CWD, "Cargo.toml", OFlags::RDONLY, Mode::empty()).unwrap();
match seek(&f, SeekFrom::Start(0)) {
Ok(_) => {}
Err(e) => panic!("seek failed with an unexpected error: {:?}", e),
}
for invalid_offset in [i32::MIN as u64, !1 as u64, i64::MIN as u64] {
match seek(&f, SeekFrom::Start(invalid_offset)) {
Err(rustix::io::Errno::INVAL) => {}
Ok(_) => panic!("seek unexpectedly succeeded"),
Err(e) => panic!("seek failed with an unexpected error: {:?}", e),
}
}
}