Skip to content

Commit 509c0e8

Browse files
bors[bot]tdryer
andauthored
Merge #1439
1439: Add sendfile64 r=asomers a=tdryer `sendfile64` is a Linux-specific call with a wider type for the `offset` argument than `sendfile`. This is largely a copy of the existing `sendfile` function and associated test. Co-authored-by: Tom Dryer <tomdryer.com@gmail.com>
2 parents 33df3e7 + fb5d942 commit 509c0e8

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
77
### Added
88
- Added TIMESTAMPNS support for linux
99
(#[1402](https://github.com/nix-rust/nix/pull/1402))
10+
- Added `sendfile64` (#[1439](https://github.com/nix-rust/nix/pull/1439))
1011

1112
### Changed
1213
- Made `forkpty` unsafe, like `fork`

src/sys/sendfile.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,32 @@ pub fn sendfile(
3333
Errno::result(ret).map(|r| r as usize)
3434
}
3535

36+
/// Copy up to `count` bytes to `out_fd` from `in_fd` starting at `offset`.
37+
///
38+
/// Returns a `Result` with the number of bytes written.
39+
///
40+
/// If `offset` is `None`, `sendfile` will begin reading at the current offset of `in_fd`and will
41+
/// update the offset of `in_fd`. If `offset` is `Some`, `sendfile` will begin at the specified
42+
/// offset and will not update the offset of `in_fd`. Instead, it will mutate `offset` to point to
43+
/// the byte after the last byte copied.
44+
///
45+
/// `in_fd` must support `mmap`-like operations and therefore cannot be a socket.
46+
///
47+
/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html)
48+
#[cfg(target_os = "linux")]
49+
pub fn sendfile64(
50+
out_fd: RawFd,
51+
in_fd: RawFd,
52+
offset: Option<&mut libc::off64_t>,
53+
count: usize,
54+
) -> Result<usize> {
55+
let offset = offset
56+
.map(|offset| offset as *mut _)
57+
.unwrap_or(ptr::null_mut());
58+
let ret = unsafe { libc::sendfile64(out_fd, in_fd, offset, count) };
59+
Errno::result(ret).map(|r| r as usize)
60+
}
61+
3662
cfg_if! {
3763
if #[cfg(any(target_os = "freebsd",
3864
target_os = "ios",

test/test_sendfile.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,28 @@ fn test_sendfile_linux() {
3636
close(wr).unwrap();
3737
}
3838

39+
#[cfg(target_os = "linux")]
40+
#[test]
41+
fn test_sendfile64_linux() {
42+
const CONTENTS: &[u8] = b"abcdef123456";
43+
let mut tmp = tempfile().unwrap();
44+
tmp.write_all(CONTENTS).unwrap();
45+
46+
let (rd, wr) = pipe().unwrap();
47+
let mut offset: libc::off64_t = 5;
48+
let res = sendfile64(wr, tmp.as_raw_fd(), Some(&mut offset), 2).unwrap();
49+
50+
assert_eq!(2, res);
51+
52+
let mut buf = [0u8; 1024];
53+
assert_eq!(2, read(rd, &mut buf).unwrap());
54+
assert_eq!(b"f1", &buf[0..2]);
55+
assert_eq!(7, offset);
56+
57+
close(rd).unwrap();
58+
close(wr).unwrap();
59+
}
60+
3961
#[cfg(target_os = "freebsd")]
4062
#[test]
4163
fn test_sendfile_freebsd() {

0 commit comments

Comments
 (0)