summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamal Marhubi <kamal@marhubi.com>2016-02-09 19:36:04 -0500
committerKamal Marhubi <kamal@marhubi.com>2016-02-12 21:12:14 -0500
commit4680d50a8a225309fc706d032a8dc5e71f819ab5 (patch)
tree276bb879f543c6522b3761e20471e88caa0b75d9
parentc33ba2908e20a6d74d472f934f7a4fa9b03cfc06 (diff)
downloadnix-4680d50a8a225309fc706d032a8dc5e71f819ab5.zip
linux: Add sendfile(2)
-rw-r--r--Cargo.toml3
-rw-r--r--src/sys/mod.rs3
-rw-r--r--src/sys/sendfile.rs12
-rw-r--r--test/test.rs3
-rw-r--r--test/test_sendfile.rs30
5 files changed, 50 insertions, 1 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 5df27ec8..093468da 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,12 +20,13 @@ preadv_pwritev = []
signalfd = []
[dependencies]
-libc = "0.2.4"
+libc = "0.2.7"
bitflags = "0.3.3"
[dev-dependencies]
rand = "0.3.8"
tempdir = "0.3"
+tempfile = "2"
nix-test = { path = "nix-test" }
[[test]]
diff --git a/src/sys/mod.rs b/src/sys/mod.rs
index c7fdc4dc..de449b76 100644
--- a/src/sys/mod.rs
+++ b/src/sys/mod.rs
@@ -16,6 +16,9 @@ pub mod memfd;
#[cfg(not(any(target_os = "ios", target_os = "freebsd", target_os = "dragonfly")))]
pub mod ioctl;
+#[cfg(any(target_os = "linux", target_os = "android"))]
+pub mod sendfile;
+
pub mod signal;
#[cfg(any(target_os = "linux", target_os = "android"))]
diff --git a/src/sys/sendfile.rs b/src/sys/sendfile.rs
new file mode 100644
index 00000000..2c39ea90
--- /dev/null
+++ b/src/sys/sendfile.rs
@@ -0,0 +1,12 @@
+use std::os::unix::io::RawFd;
+use std::ptr;
+
+use libc::{self, off_t};
+
+use {Errno, Result};
+
+pub fn sendfile(out_fd: RawFd, in_fd: RawFd, offset: Option<&mut off_t>, count: usize) -> Result<usize> {
+ let offset = offset.map(|offset| offset as *mut _).unwrap_or(ptr::null_mut());
+ let ret = unsafe { libc::sendfile(out_fd, in_fd, offset, count) };
+ Errno::result(ret).map(|r| r as usize)
+}
diff --git a/test/test.rs b/test/test.rs
index b5e9847e..53f61fb5 100644
--- a/test/test.rs
+++ b/test/test.rs
@@ -3,12 +3,15 @@ extern crate nix;
extern crate libc;
extern crate rand;
extern crate tempdir;
+extern crate tempfile;
extern crate nix_test as nixtest;
mod sys;
mod test_net;
mod test_nix_path;
+#[cfg(any(target_os = "linux", target_os = "android"))]
+mod test_sendfile;
mod test_stat;
mod test_unistd;
diff --git a/test/test_sendfile.rs b/test/test_sendfile.rs
new file mode 100644
index 00000000..7db65b9a
--- /dev/null
+++ b/test/test_sendfile.rs
@@ -0,0 +1,30 @@
+use std::io::prelude::*;
+use std::os::unix::prelude::*;
+
+use tempfile::tempfile;
+
+use libc::off_t;
+
+use nix::unistd::{close, pipe, read};
+use nix::sys::sendfile::sendfile;
+
+#[test]
+fn test_sendfile() {
+ const CONTENTS: &'static [u8] = b"abcdef123456";
+ let mut tmp = tempfile().unwrap();
+ tmp.write(CONTENTS).unwrap();
+
+ let (rd, wr) = pipe().unwrap();
+ let mut offset: off_t = 5;
+ let res = sendfile(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();
+}