Skip to content

Commit

Permalink
Add process_vm_readv and process_vm_writev
Browse files Browse the repository at this point in the history
  • Loading branch information
geofft committed Apr 4, 2017
1 parent c086d23 commit 5dee86a
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
<!--### Added-->
- Added `nix::unistd::{openat, fstatat, readlink, readlinkat}`
([#497](https://github.com/nix-rust/nix/pull/551))
- Added `nix::sys::uio::{process_vm_readv, process_vm_writev}`
([#568](https://github.com/nix-rust/nix/pull/568))

### Changed
- Marked `sys::mman::{ mmap, munmap, madvise, munlock, msync }` as unsafe.
Expand Down
20 changes: 20 additions & 0 deletions src/sys/uio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,26 @@ pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize>{
Errno::result(res).map(|r| r as usize)
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn process_vm_writev(pid: libc::pid_t, local_iov: &[IoVec<&[u8]>], remote_iov: &mut [IoVec<&mut [u8]>]) -> Result<usize> {
let res = unsafe {
libc::process_vm_writev(pid, local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
};

Errno::result(res).map(|r| r as usize)
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub fn process_vm_readv(pid: libc::pid_t, local_iov: &mut [IoVec<&mut [u8]>], remote_iov: &[IoVec<&[u8]>]) -> Result<usize> {
let res = unsafe {
libc::process_vm_readv(pid, local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
};

Errno::result(res).map(|r| r as usize)
}

#[repr(C)]
pub struct IoVec<T>(libc::iovec, PhantomData<T>);

Expand Down
45 changes: 45 additions & 0 deletions test/sys/test_uio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,48 @@ fn test_preadv() {
let all = buffers.concat();
assert_eq!(all, expected);
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn test_process_vm_readv() {
use nix::unistd::ForkResult::*;
use nix::sys::signal::*;
use nix::sys::wait::*;
use std::{str, slice};

let (r, w) = pipe().unwrap();
match fork() {
Ok(Parent { child }) => {
close(w).unwrap();
let mut msg = vec![0u8; 32];
let bytes_read = read(r, &mut msg).unwrap();
msg.truncate(bytes_read);
close(r).unwrap();

let ptr: usize = str::from_utf8(&msg).unwrap().parse().unwrap();
let remote_iov = IoVec::from_slice(unsafe {
slice::from_raw_parts(ptr as *const _, 4)
});
let mut buf = vec![0u8; 4];

let ret = process_vm_readv(child,
&mut [IoVec::from_mut_slice(&mut buf)],
&[remote_iov]);

kill(child, SIGTERM).unwrap();
waitpid(child, None).unwrap();

assert_eq!(Ok(4), ret);
assert_eq!(&buf, b"test");
},
Ok(Child) => {
close(r).unwrap();
let s = String::from("test");
let msg = format!("{}", s.as_bytes().as_ptr() as usize);
write(w, msg.as_bytes()).unwrap();
close(w).unwrap();
pause().unwrap();
},
Err(_) => panic!("fork failed")
}
}

0 comments on commit 5dee86a

Please sign in to comment.