Skip to content

Commit b1113a3

Browse files
authored
Always set O_LARGEFILE when opening or F_SETFLing files. (#700)
1 parent 6b02e62 commit b1113a3

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

src/backend/linux_raw/c.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ pub(crate) use linux_raw_sys::general::epoll_event;
2323

2424
#[cfg(feature = "fs")]
2525
pub(crate) use linux_raw_sys::general::{
26-
AT_FDCWD, NFS_SUPER_MAGIC, PROC_SUPER_MAGIC, UTIME_NOW, UTIME_OMIT, XATTR_CREATE, XATTR_REPLACE,
26+
AT_FDCWD, NFS_SUPER_MAGIC, O_LARGEFILE, PROC_SUPER_MAGIC, UTIME_NOW, UTIME_OMIT, XATTR_CREATE,
27+
XATTR_REPLACE,
2728
};
2829

2930
#[cfg(feature = "io_uring")]

src/backend/linux_raw/fs/syscalls.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ use {
4848

4949
#[inline]
5050
pub(crate) fn open(path: &CStr, flags: OFlags, mode: Mode) -> io::Result<OwnedFd> {
51+
// Always enable support for large files.
52+
let flags = flags | OFlags::from_bits_retain(c::O_LARGEFILE);
53+
5154
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
5255
{
5356
openat(CWD.as_fd(), path, flags, mode)
@@ -65,6 +68,9 @@ pub(crate) fn openat(
6568
flags: OFlags,
6669
mode: Mode,
6770
) -> io::Result<OwnedFd> {
71+
// Always enable support for large files.
72+
let flags = flags | OFlags::from_bits_retain(c::O_LARGEFILE);
73+
6874
unsafe { ret_owned_fd(syscall_readonly!(__NR_openat, dirfd, path, flags, mode)) }
6975
}
7076

@@ -76,6 +82,9 @@ pub(crate) fn openat2(
7682
mode: Mode,
7783
resolve: ResolveFlags,
7884
) -> io::Result<OwnedFd> {
85+
// Always enable support for large files.
86+
let flags = flags | OFlags::from_bits_retain(c::O_LARGEFILE);
87+
7988
unsafe {
8089
ret_owned_fd(syscall_readonly!(
8190
__NR_openat2,
@@ -883,17 +892,19 @@ pub(crate) fn fcntl_getfl(fd: BorrowedFd<'_>) -> io::Result<OFlags> {
883892
#[cfg(target_pointer_width = "32")]
884893
unsafe {
885894
ret_c_uint(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_GETFL)))
886-
.map(OFlags::from_bits_truncate)
895+
.map(OFlags::from_bits_retain)
887896
}
888897
#[cfg(target_pointer_width = "64")]
889898
unsafe {
890-
ret_c_uint(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETFL)))
891-
.map(OFlags::from_bits_truncate)
899+
ret_c_uint(syscall_readonly!(__NR_fcntl, fd, c_uint(F_GETFL))).map(OFlags::from_bits_retain)
892900
}
893901
}
894902

895903
#[inline]
896904
pub(crate) fn fcntl_setfl(fd: BorrowedFd<'_>, flags: OFlags) -> io::Result<()> {
905+
// Always enable support for large files.
906+
let flags = flags | OFlags::from_bits_retain(c::O_LARGEFILE);
907+
897908
#[cfg(target_pointer_width = "32")]
898909
unsafe {
899910
ret(syscall_readonly!(__NR_fcntl64, fd, c_uint(F_SETFL), flags))

tests/fs/file.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,9 @@ fn test_file() {
8888
rustix::io::fcntl_getfd(&file).unwrap(),
8989
rustix::io::FdFlags::empty()
9090
);
91+
// Use `from_bits_truncate` to ignore `O_LARGEFILE` if present.
9192
assert_eq!(
92-
rustix::fs::fcntl_getfl(&file).unwrap(),
93+
rustix::fs::OFlags::from_bits_truncate(rustix::fs::fcntl_getfl(&file).unwrap().bits()),
9394
rustix::fs::OFlags::empty()
9495
);
9596

@@ -120,3 +121,35 @@ fn test_file() {
120121

121122
assert_ne!(rustix::io::ioctl_fionread(&file).unwrap(), 0);
122123
}
124+
125+
#[test]
126+
fn test_setfl_append() {
127+
use rustix::fs::{Mode, OFlags};
128+
129+
let tmp = tempfile::tempdir().unwrap();
130+
131+
// Write some bytes to a file.
132+
let file = rustix::fs::open(
133+
tmp.path().join("test.file"),
134+
OFlags::WRONLY | OFlags::CREATE,
135+
Mode::RWXU,
136+
)
137+
.unwrap();
138+
assert_eq!(rustix::io::write(&file, b"abcdefghijklmnop"), Ok(16));
139+
140+
// Overwite the first few bytes.
141+
let file =
142+
rustix::fs::open(tmp.path().join("test.file"), OFlags::WRONLY, Mode::empty()).unwrap();
143+
assert_eq!(rustix::io::write(&file, b"uvw"), Ok(3));
144+
145+
// Append a few bytes.
146+
rustix::fs::fcntl_setfl(&file, OFlags::APPEND).unwrap();
147+
assert_eq!(rustix::io::write(&file, b"xyz"), Ok(3));
148+
149+
// Check the final contents.
150+
let file =
151+
rustix::fs::open(tmp.path().join("test.file"), OFlags::RDONLY, Mode::empty()).unwrap();
152+
let mut buf = [0_u8; 32];
153+
assert_eq!(rustix::io::read(&file, &mut buf), Ok(19));
154+
assert_eq!(&buf, b"uvwdefghijklmnopxyz\0\0\0\0\0\0\0\0\0\0\0\0\0");
155+
}

0 commit comments

Comments
 (0)