Skip to content

Commit 7632f2a

Browse files
committed
Add process_vm_readv and process_vm_writev
1 parent c086d23 commit 7632f2a

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
88
<!--### Added-->
99
- Added `nix::unistd::{openat, fstatat, readlink, readlinkat}`
1010
([#497](https://github.com/nix-rust/nix/pull/551))
11+
- Added `nix::sys::ui::{process_vm_readv, process_vm_writev}`
12+
([#568](https://github.com/nix-rust/nix/pull/568))
1113

1214
### Changed
1315
- Marked `sys::mman::{ mmap, munmap, madvise, munlock, msync }` as unsafe.

src/sys/uio.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,26 @@ pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize>{
5656
Errno::result(res).map(|r| r as usize)
5757
}
5858

59+
#[cfg(any(target_os = "linux", target_os = "android"))]
60+
pub fn process_vm_writev(pid: libc::pid_t, local_iov: &[IoVec<&[u8]>], remote_iov: &mut [IoVec<&mut [u8]>]) -> Result<usize> {
61+
let res = unsafe {
62+
libc::process_vm_writev(pid, local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
63+
remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
64+
};
65+
66+
Errno::result(res).map(|r| r as usize)
67+
}
68+
69+
#[cfg(any(target_os = "linux", target_os = "android"))]
70+
pub fn process_vm_readv(pid: libc::pid_t, local_iov: &mut [IoVec<&mut [u8]>], remote_iov: &[IoVec<&[u8]>]) -> Result<usize> {
71+
let res = unsafe {
72+
libc::process_vm_readv(pid, local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
73+
remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
74+
};
75+
76+
Errno::result(res).map(|r| r as usize)
77+
}
78+
5979
#[repr(C)]
6080
pub struct IoVec<T>(libc::iovec, PhantomData<T>);
6181

test/sys/test_uio.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,48 @@ fn test_preadv() {
190190
let all = buffers.concat();
191191
assert_eq!(all, expected);
192192
}
193+
194+
#[test]
195+
#[cfg(any(target_os = "linux", target_os = "android"))]
196+
fn test_process_vm_readv() {
197+
use nix::unistd::ForkResult::*;
198+
use nix::sys::signal::*;
199+
use nix::sys::wait::*;
200+
use std::{str, slice};
201+
202+
let (r, w) = pipe().unwrap();
203+
match fork() {
204+
Ok(Parent { child }) => {
205+
close(w).unwrap();
206+
let mut msg = vec![0u8; 32];
207+
let bytes_read = read(r, &mut msg).unwrap();
208+
msg.truncate(bytes_read);
209+
close(r).unwrap();
210+
211+
let ptr: usize = str::from_utf8(&msg).unwrap().parse().unwrap();
212+
let remote_iov = IoVec::from_slice(unsafe {
213+
slice::from_raw_parts(ptr as *const _, 4)
214+
});
215+
let mut buf = vec![0u8; 4];
216+
217+
let ret = process_vm_readv(child,
218+
&mut [IoVec::from_mut_slice(&mut buf)],
219+
&[remote_iov]);
220+
221+
kill(child, SIGTERM).unwrap();
222+
waitpid(child, None).unwrap();
223+
224+
assert_eq!(Ok(4), ret);
225+
assert_eq!(&buf, b"test");
226+
},
227+
Ok(Child) => {
228+
close(r).unwrap();
229+
let s = String::from("test");
230+
let msg = format!("{}", s.as_bytes().as_ptr() as usize);
231+
write(w, msg.as_bytes()).unwrap();
232+
close(w).unwrap();
233+
pause().unwrap();
234+
},
235+
Err(_) => panic!("fork failed")
236+
}
237+
}

0 commit comments

Comments
 (0)