Skip to content

Commit 5e79bf7

Browse files
authored
Support SEEK_DATA and SEEK_HOLE for lseek (#486)
* Support `SEEK_DATA` and `SEEK_HOLE` for `lseek` * Add `sparse` support to `libc` backend * Do not use `std::io::Seekfrom` * Remove `std::io::SeekFrom` from tests * Remove `staged_api` * Add more `cfg` * Re-enable `seek_from` on Windows * Enable for all supported OSes * Improve docs
1 parent 60841f1 commit 5e79bf7

File tree

5 files changed

+57
-6
lines changed

5 files changed

+57
-6
lines changed

src/backend/libc/fs/syscalls.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,20 @@ pub(crate) fn seek(fd: BorrowedFd<'_>, pos: SeekFrom) -> io::Result<u64> {
900900
}
901901
SeekFrom::End(offset) => (c::SEEK_END, offset),
902902
SeekFrom::Current(offset) => (c::SEEK_CUR, offset),
903+
#[cfg(any(
904+
target_os = "linux",
905+
target_os = "solaris",
906+
target_os = "freebsd",
907+
target_os = "dragonfly",
908+
))]
909+
SeekFrom::Data(offset) => (c::SEEK_DATA, offset),
910+
#[cfg(any(
911+
target_os = "linux",
912+
target_os = "solaris",
913+
target_os = "freebsd",
914+
target_os = "dragonfly",
915+
))]
916+
SeekFrom::Hole(offset) => (c::SEEK_HOLE, offset),
903917
};
904918
let offset = unsafe { ret_off_t(libc_lseek(borrowed_fd(fd), offset, whence))? };
905919
Ok(offset as u64)

src/backend/linux_raw/fs/syscalls.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ use linux_raw_sys::general::stat as linux_stat64;
3737
use linux_raw_sys::general::{
3838
__kernel_fsid_t, __kernel_timespec, open_how, statx, AT_EACCESS, AT_FDCWD, AT_REMOVEDIR,
3939
AT_SYMLINK_NOFOLLOW, F_ADD_SEALS, F_GETFL, F_GETLEASE, F_GETOWN, F_GETPIPE_SZ, F_GETSIG,
40-
F_GET_SEALS, F_SETFL, F_SETPIPE_SZ, SEEK_CUR, SEEK_END, SEEK_SET, STATX__RESERVED,
40+
F_GET_SEALS, F_SETFL, F_SETPIPE_SZ, SEEK_CUR, SEEK_DATA, SEEK_END, SEEK_HOLE, SEEK_SET,
41+
STATX__RESERVED,
4142
};
4243
#[cfg(target_pointer_width = "32")]
4344
use {
@@ -214,6 +215,20 @@ pub(crate) fn seek(fd: BorrowedFd<'_>, pos: SeekFrom) -> io::Result<u64> {
214215
}
215216
SeekFrom::End(offset) => (SEEK_END, offset),
216217
SeekFrom::Current(offset) => (SEEK_CUR, offset),
218+
#[cfg(any(
219+
target_os = "linux",
220+
target_os = "solaris",
221+
target_os = "freebsd",
222+
target_os = "dragonfly",
223+
))]
224+
SeekFrom::Data(offset) => (SEEK_DATA, offset),
225+
#[cfg(any(
226+
target_os = "linux",
227+
target_os = "solaris",
228+
target_os = "freebsd",
229+
target_os = "dragonfly",
230+
))]
231+
SeekFrom::Hole(offset) => (SEEK_HOLE, offset),
217232
};
218233
_seek(fd, offset, whence)
219234
}

src/io/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ mod poll;
2020
mod procfs;
2121
#[cfg(not(windows))]
2222
mod read_write;
23-
#[cfg(not(feature = "std"))]
2423
mod seek_from;
2524
#[cfg(not(windows))]
2625
mod stdio;
@@ -87,10 +86,7 @@ pub use read_write::{pread, pwrite, read, readv, write, writev, IoSlice, IoSlice
8786
pub use read_write::{preadv, pwritev};
8887
#[cfg(any(target_os = "android", target_os = "linux"))]
8988
pub use read_write::{preadv2, pwritev2, ReadWriteFlags};
90-
#[cfg(not(feature = "std"))]
9189
pub use seek_from::SeekFrom;
92-
#[cfg(feature = "std")]
93-
pub use std::io::SeekFrom;
9490
#[cfg(not(windows))]
9591
pub use stdio::{
9692
raw_stderr, raw_stdin, raw_stdout, stderr, stdin, stdout, take_stderr, take_stdin, take_stdout,

src/io/seek_from.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,30 @@ pub enum SeekFrom {
2727
/// to seek before byte 0.
2828
#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
2929
Current(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] i64),
30+
31+
/// Sets the offset to the current position plus the specified number of bytes,
32+
/// plus the distance to the next byte which is not in a hole.
33+
///
34+
/// If the offset is in a hole at the end of the file, the seek will produce
35+
/// an `NXIO` error.
36+
#[cfg(any(
37+
target_os = "linux",
38+
target_os = "solaris",
39+
target_os = "freebsd",
40+
target_os = "dragonfly",
41+
))]
42+
Data(i64),
43+
44+
/// Sets the offset to the current position plus the specified number of bytes,
45+
/// plus the distance to the next byte which is in a hole.
46+
///
47+
/// If there is no hole past the offset, it will be set to the end of the file
48+
/// i.e. there is an implicit hole at the end of any file.
49+
#[cfg(any(
50+
target_os = "linux",
51+
target_os = "solaris",
52+
target_os = "freebsd",
53+
target_os = "dragonfly",
54+
))]
55+
Hole(i64),
3056
}

tests/io/read_write.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ fn test_readwrite_v() {
9696
#[test]
9797
fn test_readwrite() {
9898
use rustix::fs::{cwd, openat, seek, Mode, OFlags};
99+
use rustix::io::SeekFrom;
99100
use rustix::io::{read, write};
100-
use std::io::SeekFrom;
101101

102102
let tmp = tempfile::tempdir().unwrap();
103103
let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap();

0 commit comments

Comments
 (0)