diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 24 | ||||
-rw-r--r-- | src/sys/ptrace.rs | 45 |
2 files changed, 49 insertions, 20 deletions
@@ -75,7 +75,6 @@ use std::{ptr, result}; use std::ffi::{CStr, OsStr}; use std::path::{Path, PathBuf}; use std::os::unix::ffi::OsStrExt; -use std::io; use std::fmt; use std::error; use libc::PATH_MAX; @@ -97,6 +96,9 @@ pub enum Error { /// The operation involved a conversion to Rust's native String type, which failed because the /// string did not contain all valid UTF-8. InvalidUtf8, + /// The operation is not supported by Nix, in this instance either use the libc bindings or + /// consult the module documentation to see if there is a more appropriate interface available. + UnsupportedOperation, } impl Error { @@ -116,14 +118,6 @@ impl Error { Error::Sys(errno::EINVAL) } - /// Get the errno associated with this error - pub fn errno(&self) -> errno::Errno { - match *self { - Error::InvalidPath => errno::Errno::EINVAL, - Error::InvalidUtf8 => errno::Errno::UnknownErrno, - Error::Sys(errno) => errno, - } - } } impl From<errno::Errno> for Error { @@ -139,6 +133,7 @@ impl error::Error for Error { match self { &Error::InvalidPath => "Invalid path", &Error::InvalidUtf8 => "Invalid UTF-8 string", + &Error::UnsupportedOperation => "Unsupported Operation", &Error::Sys(ref errno) => errno.desc(), } } @@ -149,21 +144,12 @@ impl fmt::Display for Error { match self { &Error::InvalidPath => write!(f, "Invalid path"), &Error::InvalidUtf8 => write!(f, "Invalid UTF-8 string"), + &Error::UnsupportedOperation => write!(f, "Unsupported Operation"), &Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()), } } } -impl From<Error> for io::Error { - fn from(err: Error) -> Self { - match err { - Error::InvalidPath => io::Error::new(io::ErrorKind::InvalidInput, err), - Error::InvalidUtf8 => io::Error::new(io::ErrorKind::Other, err), - Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32), - } - } -} - pub trait NixPath { fn len(&self) -> usize; diff --git a/src/sys/ptrace.rs b/src/sys/ptrace.rs index edbc9734..bf6ee8bb 100644 --- a/src/sys/ptrace.rs +++ b/src/sys/ptrace.rs @@ -1,5 +1,6 @@ +use std::{mem, ptr}; use {Errno, Error, Result}; -use libc::{pid_t, c_void, c_long}; +use libc::{pid_t, c_void, c_long, siginfo_t}; #[cfg(all(target_os = "linux", any(target_arch = "x86", @@ -71,11 +72,14 @@ mod ffi { } } +/// Performs a ptrace request. If the request in question is provided by a specialised function +/// this function will return an unsupported operation error. pub fn ptrace(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<c_long> { use self::ptrace::*; match request { PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_PEEKUSER => ptrace_peek(request, pid, addr, data), + PTRACE_GETSIGINFO | PTRACE_GETEVENTMSG | PTRACE_SETSIGINFO | PTRACE_SETOPTIONS => Err(Error::UnsupportedOperation), _ => ptrace_other(request, pid, addr, data) } } @@ -91,6 +95,20 @@ fn ptrace_peek(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, da } } +/// Function for ptrace requests that return values from the data field. +/// Some ptrace get requests populate structs or larger elements than c_long +/// and therefore use the data field to return values. This function handles these +/// requests. +fn ptrace_get_data<T>(request: ptrace::PtraceRequest, pid: pid_t) -> Result<T> { + // Creates an uninitialized pointer to store result in + let data: Box<T> = Box::new(unsafe { mem::uninitialized() }); + let data: *mut c_void = unsafe { mem::transmute(data) }; + ptrace(request, pid, ptr::null_mut(), data)?; + // Convert back into the original data format and return unboxed value + let data: Box<T> = unsafe { mem::transmute(data) }; + Ok(*data) +} + fn ptrace_other(request: ptrace::PtraceRequest, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> Result<c_long> { Errno::result(unsafe { ffi::ptrace(request, pid, addr, data) }).map(|_| 0) } @@ -102,3 +120,28 @@ pub fn ptrace_setoptions(pid: pid_t, options: ptrace::PtraceOptions) -> Result<( ptrace(PTRACE_SETOPTIONS, pid, ptr::null_mut(), options as *mut c_void).map(drop) } + +/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)` +pub fn ptrace_getevent(pid: pid_t) -> Result<c_long> { + use self::ptrace::*; + ptrace_get_data::<c_long>(PTRACE_GETEVENTMSG, pid) +} + +/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)` +pub fn ptrace_getsiginfo(pid: pid_t) -> Result<siginfo_t> { + use self::ptrace::*; + ptrace_get_data::<siginfo_t>(PTRACE_GETSIGINFO, pid) +} + +/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)` +pub fn ptrace_setsiginfo(pid: pid_t, sig: &siginfo_t) -> Result<()> { + use self::ptrace::*; + let ret = unsafe{ + Errno::clear(); + ffi::ptrace(PTRACE_SETSIGINFO, pid, ptr::null_mut(), sig as *const _ as *const c_void) + }; + match Errno::result(ret) { + Ok(_) => Ok(()), + Err(e) => Err(e), + } +} |