Skip to content

Support SEEK_DATA and SEEK_HOLE for lseek #486

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jan 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/backend/libc/fs/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,20 @@ pub(crate) fn seek(fd: BorrowedFd<'_>, pos: SeekFrom) -> io::Result<u64> {
}
SeekFrom::End(offset) => (c::SEEK_END, offset),
SeekFrom::Current(offset) => (c::SEEK_CUR, offset),
#[cfg(any(
target_os = "linux",
target_os = "solaris",
target_os = "freebsd",
target_os = "dragonfly",
))]
SeekFrom::Data(offset) => (c::SEEK_DATA, offset),
#[cfg(any(
target_os = "linux",
target_os = "solaris",
target_os = "freebsd",
target_os = "dragonfly",
))]
SeekFrom::Hole(offset) => (c::SEEK_HOLE, offset),
};
let offset = unsafe { ret_off_t(libc_lseek(borrowed_fd(fd), offset, whence))? };
Ok(offset as u64)
Expand Down
17 changes: 16 additions & 1 deletion src/backend/linux_raw/fs/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ use linux_raw_sys::general::stat as linux_stat64;
use linux_raw_sys::general::{
__kernel_fsid_t, __kernel_timespec, open_how, statx, AT_EACCESS, AT_FDCWD, AT_REMOVEDIR,
AT_SYMLINK_NOFOLLOW, F_ADD_SEALS, F_GETFL, F_GETLEASE, F_GETOWN, F_GETPIPE_SZ, F_GETSIG,
F_GET_SEALS, F_SETFL, F_SETPIPE_SZ, SEEK_CUR, SEEK_END, SEEK_SET, STATX__RESERVED,
F_GET_SEALS, F_SETFL, F_SETPIPE_SZ, SEEK_CUR, SEEK_DATA, SEEK_END, SEEK_HOLE, SEEK_SET,
STATX__RESERVED,
};
#[cfg(target_pointer_width = "32")]
use {
Expand Down Expand Up @@ -214,6 +215,20 @@ pub(crate) fn seek(fd: BorrowedFd<'_>, pos: SeekFrom) -> io::Result<u64> {
}
SeekFrom::End(offset) => (SEEK_END, offset),
SeekFrom::Current(offset) => (SEEK_CUR, offset),
#[cfg(any(
target_os = "linux",
target_os = "solaris",
target_os = "freebsd",
target_os = "dragonfly",
))]
SeekFrom::Data(offset) => (SEEK_DATA, offset),
#[cfg(any(
target_os = "linux",
target_os = "solaris",
target_os = "freebsd",
target_os = "dragonfly",
))]
SeekFrom::Hole(offset) => (SEEK_HOLE, offset),
};
_seek(fd, offset, whence)
}
Expand Down
4 changes: 0 additions & 4 deletions src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ mod poll;
mod procfs;
#[cfg(not(windows))]
mod read_write;
#[cfg(not(feature = "std"))]
mod seek_from;
#[cfg(not(windows))]
mod stdio;
Expand Down Expand Up @@ -89,10 +88,7 @@ pub use read_write::{pread, pwrite, read, readv, write, writev, IoSlice, IoSlice
pub use read_write::{preadv, pwritev};
#[cfg(any(target_os = "android", target_os = "linux"))]
pub use read_write::{preadv2, pwritev2, ReadWriteFlags};
#[cfg(not(feature = "std"))]
pub use seek_from::SeekFrom;
#[cfg(feature = "std")]
pub use std::io::SeekFrom;
#[cfg(not(windows))]
pub use stdio::{
raw_stderr, raw_stdin, raw_stdout, stderr, stdin, stdout, take_stderr, take_stdin, take_stdout,
Expand Down
26 changes: 26 additions & 0 deletions src/io/seek_from.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,30 @@ pub enum SeekFrom {
/// to seek before byte 0.
#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))]
Current(#[cfg_attr(staged_api, stable(feature = "rust1", since = "1.0.0"))] i64),

/// Sets the offset to the current position plus the specified number of bytes,
/// plus the distance to the next byte which is not in a hole.
///
/// If the offset is in a hole at the end of the file, the seek will produce
/// an `NXIO` error.
#[cfg(any(
target_os = "linux",
target_os = "solaris",
target_os = "freebsd",
target_os = "dragonfly",
))]
Data(i64),

/// Sets the offset to the current position plus the specified number of bytes,
/// plus the distance to the next byte which is in a hole.
///
/// If there is no hole past the offset, it will be set to the end of the file
/// i.e. there is an implicit hole at the end of any file.
#[cfg(any(
target_os = "linux",
target_os = "solaris",
target_os = "freebsd",
target_os = "dragonfly",
))]
Hole(i64),
}
2 changes: 1 addition & 1 deletion tests/io/read_write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ fn test_readwrite_v() {
#[test]
fn test_readwrite() {
use rustix::fs::{cwd, openat, seek, Mode, OFlags};
use rustix::io::SeekFrom;
use rustix::io::{read, write};
use std::io::SeekFrom;

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