From a643cb94d727eddfe4f808b57f85c8a976bc3ce0 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 13 Jan 2025 08:05:49 -0800 Subject: [PATCH 1/2] Make the offsets for `SeekFrom`'s `Hole` and `Data` unsigned. These represent absolute offsets from the start of the file, so they should be unsigned, for consistency with `Start`. --- src/backend/libc/fs/syscalls.rs | 12 ++++++++++-- src/backend/linux_raw/fs/syscalls.rs | 12 ++++++++++-- src/fs/seek_from.rs | 4 ++-- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/backend/libc/fs/syscalls.rs b/src/backend/libc/fs/syscalls.rs index 2d2f4c674..74a9865cc 100644 --- a/src/backend/libc/fs/syscalls.rs +++ b/src/backend/libc/fs/syscalls.rs @@ -1293,9 +1293,17 @@ pub(crate) fn seek(fd: BorrowedFd<'_>, pos: SeekFrom) -> io::Result { SeekFrom::End(offset) => (c::SEEK_END, offset), SeekFrom::Current(offset) => (c::SEEK_CUR, offset), #[cfg(any(apple, freebsdlike, linux_kernel, solarish))] - SeekFrom::Data(offset) => (c::SEEK_DATA, offset), + SeekFrom::Data(pos) => { + let pos: u64 = pos; + // Silently cast; we'll get `EINVAL` if the value is negative. + (c::SEEK_DATA, pos as i64) + } #[cfg(any(apple, freebsdlike, linux_kernel, solarish))] - SeekFrom::Hole(offset) => (c::SEEK_HOLE, offset), + SeekFrom::Hole(pos) => { + let pos: u64 = pos; + // Silently cast; we'll get `EINVAL` if the value is negative. + (c::SEEK_HOLE, pos as i64) + } }; // ESP-IDF and Vita don't support 64-bit offsets. diff --git a/src/backend/linux_raw/fs/syscalls.rs b/src/backend/linux_raw/fs/syscalls.rs index 0c4b03ba1..81c36fe0e 100644 --- a/src/backend/linux_raw/fs/syscalls.rs +++ b/src/backend/linux_raw/fs/syscalls.rs @@ -238,8 +238,16 @@ pub(crate) fn seek(fd: BorrowedFd<'_>, pos: SeekFrom) -> io::Result { } SeekFrom::End(offset) => (SEEK_END, offset), SeekFrom::Current(offset) => (SEEK_CUR, offset), - SeekFrom::Data(offset) => (SEEK_DATA, offset), - SeekFrom::Hole(offset) => (SEEK_HOLE, offset), + SeekFrom::Data(pos) => { + let pos: u64 = pos; + // Silently cast; we'll get `EINVAL` if the value is negative. + (SEEK_DATA, pos as i64) + } + SeekFrom::Hole(pos) => { + let pos: u64 = pos; + // Silently cast; we'll get `EINVAL` if the value is negative. + (SEEK_HOLE, pos as i64) + } }; _seek(fd, offset, whence) } diff --git a/src/fs/seek_from.rs b/src/fs/seek_from.rs index c08abd2e6..bc0907cae 100644 --- a/src/fs/seek_from.rs +++ b/src/fs/seek_from.rs @@ -41,7 +41,7 @@ pub enum SeekFrom { /// /// [`Errno::NXIO`]: crate::io::Errno::NXIO #[cfg(any(apple, freebsdlike, linux_kernel, solarish))] - Data(i64), + Data(u64), /// 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. @@ -49,5 +49,5 @@ pub enum SeekFrom { /// 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(apple, freebsdlike, linux_kernel, solarish))] - Hole(i64), + Hole(u64), } From ecadbdf3d96c39d199bf773140636a6d3f8499e8 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 13 Jan 2025 09:03:56 -0800 Subject: [PATCH 2/2] Update tests. --- tests/fs/seek.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/fs/seek.rs b/tests/fs/seek.rs index c483817fd..e25f8ff85 100644 --- a/tests/fs/seek.rs +++ b/tests/fs/seek.rs @@ -43,18 +43,15 @@ fn test_seek_holes() { assert_eq!(seek(&file, SeekFrom::Start(0)), Ok(0)); assert_eq!(seek(&file, SeekFrom::Current(0)), Ok(0)); assert_eq!(seek(&file, SeekFrom::Hole(0)), Ok(hole_size)); - assert_eq!(seek(&file, SeekFrom::Hole(hole_size as i64)), Ok(hole_size)); + assert_eq!(seek(&file, SeekFrom::Hole(hole_size)), Ok(hole_size)); assert_eq!( - seek(&file, SeekFrom::Hole(hole_size as i64 * 2)), + seek(&file, SeekFrom::Hole(hole_size * 2)), Ok(hole_size * 2 + 6) ); assert_eq!(seek(&file, SeekFrom::Data(0)), Ok(0)); + assert_eq!(seek(&file, SeekFrom::Data(hole_size)), Ok(hole_size * 2)); assert_eq!( - seek(&file, SeekFrom::Data(hole_size as i64)), - Ok(hole_size * 2) - ); - assert_eq!( - seek(&file, SeekFrom::Data(hole_size as i64 * 2)), + seek(&file, SeekFrom::Data(hole_size * 2)), Ok(hole_size * 2) ); }