diff options
-rw-r--r-- | src/sys/uio.rs | 36 | ||||
-rw-r--r-- | test/sys/test_uio.rs | 38 |
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(); +} |