summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/sys/uio.rs36
-rw-r--r--test/sys/test_uio.rs38
2 files changed, 73 insertions, 1 deletions
diff --git a/src/sys/uio.rs b/src/sys/uio.rs
index 9f65cf09..99075b79 100644
--- a/src/sys/uio.rs
+++ b/src/sys/uio.rs
@@ -9,7 +9,7 @@ use std::os::unix::io::RawFd;
mod ffi {
use super::IoVec;
- use libc::{ssize_t, c_int};
+ use libc::{ssize_t, c_int, size_t, off_t, c_void};
use std::os::unix::io::RawFd;
extern {
@@ -20,6 +20,16 @@ mod ffi {
// vectorized version of read
// doc: http://man7.org/linux/man-pages/man2/readv.2.html
pub fn readv(fd: RawFd, iov: *const IoVec<&mut [u8]>, iovcnt: c_int) -> ssize_t;
+
+ // write to a file at a specified offset
+ // doc: http://man7.org/linux/man-pages/man2/pwrite.2.html
+ pub fn pwrite(fd: RawFd, buf: *const c_void, nbyte: size_t,
+ offset: off_t) -> ssize_t;
+
+ // read from a file at a specified offset
+ // doc: http://man7.org/linux/man-pages/man2/pread.2.html
+ pub fn pread(fd: RawFd, buf: *mut c_void, nbyte: size_t, offset: off_t)
+ -> ssize_t;
}
}
@@ -42,6 +52,30 @@ pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result<usize> {
return Ok(res as usize)
}
+pub fn pwrite(fd: RawFd, buf: &[u8], offset: i64) -> Result<usize> {
+ let res = unsafe {
+ ffi::pwrite(fd, buf.as_ptr() as *const c_void, buf.len() as size_t,
+ offset)
+ };
+ if res < 0 {
+ Err(Error::Sys(Errno::last()))
+ } else {
+ Ok(res as usize)
+ }
+}
+
+pub fn pread(fd: RawFd, buf: &mut [u8], offset: i64) -> Result<usize>{
+ let res = unsafe {
+ ffi::pread(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t,
+ offset)
+ };
+ if res < 0 {
+ Err(Error::Sys(Errno::last()))
+ } else {
+ Ok(res as usize)
+ }
+}
+
#[repr(C)]
pub struct IoVec<T> {
iov_base: *mut c_void,
diff --git a/test/sys/test_uio.rs b/test/sys/test_uio.rs
index 8f467001..0432b1e8 100644
--- a/test/sys/test_uio.rs
+++ b/test/sys/test_uio.rs
@@ -2,6 +2,8 @@ use nix::sys::uio::*;
use nix::unistd::*;
use rand::{thread_rng, Rng};
use std::{cmp, iter};
+use std::fs::{OpenOptions, remove_file};
+use std::os::unix::io::AsRawFd;
#[test]
fn test_writev() {
@@ -90,3 +92,39 @@ fn test_readv() {
let close_res = close(writer);
assert!(close_res.is_ok());
}
+
+#[test]
+fn test_pwrite() {
+ use std::io::Read;
+
+ let path = "pwrite_test_file";
+ let mut file = OpenOptions::new().write(true).read(true).create(true)
+ .truncate(true).open(path).unwrap();
+ let buf = [1u8;8];
+ assert_eq!(Ok(8), pwrite(file.as_raw_fd(), &buf, 8));
+ let mut file_content = Vec::new();
+ file.read_to_end(&mut file_content).unwrap();
+ let mut expected = vec![0u8;8];
+ expected.extend(vec![1;8]);
+ assert_eq!(file_content, expected);
+
+ remove_file(path).unwrap();
+}
+
+#[test]
+fn test_pread() {
+ use std::io::Write;
+
+ let path = "pread_test_file";
+ let mut file = OpenOptions::new().write(true).read(true).create(true)
+ .truncate(true).open(path).unwrap();
+ let file_content: Vec<u8> = (0..64).collect();
+ file.write_all(&file_content).unwrap();
+
+ let mut buf = [0u8;16];
+ assert_eq!(Ok(16), pread(file.as_raw_fd(), &mut buf, 16));
+ let expected: Vec<_> = (16..32).collect();
+ assert_eq!(&buf[..], &expected[..]);
+
+ remove_file(path).unwrap();
+}