summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs24
-rw-r--r--src/sys/ptrace.rs45
2 files changed, 49 insertions, 20 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 42f23334..f0cdb581 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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),
+ }
+}