summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--src/sys/sendfile.rs26
-rw-r--r--test/test_sendfile.rs22
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() {