diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-05-30 16:26:41 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-30 16:26:41 +0000 |
commit | df9ed9314d61cc0598de60a401800a24f9c68850 (patch) | |
tree | a0e4ba3b0d76096df355f2f4490022d9638f2602 | |
parent | 33df3e7cb638eb3c088f0def18a2d649562c4499 (diff) | |
parent | fb5d942c3cf35b842e913a4cd1ec9a5528a38664 (diff) | |
download | nix-df9ed9314d61cc0598de60a401800a24f9c68850.zip |
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>
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | src/sys/sendfile.rs | 26 | ||||
-rw-r--r-- | test/test_sendfile.rs | 22 |
3 files changed, 49 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fe6c7bf..1e163be9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ### Added - Added TIMESTAMPNS support for linux (#[1402](https://github.com/nix-rust/nix/pull/1402)) +- Added `sendfile64` (#[1439](https://github.com/nix-rust/nix/pull/1439)) ### Changed - Made `forkpty` unsafe, like `fork` diff --git a/src/sys/sendfile.rs b/src/sys/sendfile.rs index d44672c7..a12c0411 100644 --- a/src/sys/sendfile.rs +++ b/src/sys/sendfile.rs @@ -33,6 +33,32 @@ pub fn sendfile( Errno::result(ret).map(|r| r as usize) } +/// Copy up to `count` bytes to `out_fd` from `in_fd` starting at `offset`. +/// +/// Returns a `Result` with the number of bytes written. +/// +/// If `offset` is `None`, `sendfile` will begin reading at the current offset of `in_fd`and will +/// update the offset of `in_fd`. If `offset` is `Some`, `sendfile` will begin at the specified +/// offset and will not update the offset of `in_fd`. Instead, it will mutate `offset` to point to +/// the byte after the last byte copied. +/// +/// `in_fd` must support `mmap`-like operations and therefore cannot be a socket. +/// +/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html) +#[cfg(target_os = "linux")] +pub fn sendfile64( + out_fd: RawFd, + in_fd: RawFd, + offset: Option<&mut libc::off64_t>, + count: usize, +) -> Result<usize> { + let offset = offset + .map(|offset| offset as *mut _) + .unwrap_or(ptr::null_mut()); + let ret = unsafe { libc::sendfile64(out_fd, in_fd, offset, count) }; + Errno::result(ret).map(|r| r as usize) +} + cfg_if! { if #[cfg(any(target_os = "freebsd", target_os = "ios", diff --git a/test/test_sendfile.rs b/test/test_sendfile.rs index 3bc7932f..b6559d32 100644 --- a/test/test_sendfile.rs +++ b/test/test_sendfile.rs @@ -36,6 +36,28 @@ fn test_sendfile_linux() { close(wr).unwrap(); } +#[cfg(target_os = "linux")] +#[test] +fn test_sendfile64_linux() { + const CONTENTS: &[u8] = b"abcdef123456"; + let mut tmp = tempfile().unwrap(); + tmp.write_all(CONTENTS).unwrap(); + + let (rd, wr) = pipe().unwrap(); + let mut offset: libc::off64_t = 5; + let res = sendfile64(wr, tmp.as_raw_fd(), Some(&mut offset), 2).unwrap(); + + assert_eq!(2, res); + + let mut buf = [0u8; 1024]; + assert_eq!(2, read(rd, &mut buf).unwrap()); + assert_eq!(b"f1", &buf[0..2]); + assert_eq!(7, offset); + + close(rd).unwrap(); + close(wr).unwrap(); +} + #[cfg(target_os = "freebsd")] #[test] fn test_sendfile_freebsd() { |