extern crate libc;
pub mod process;
use std::ffi::{CStr, CString};
use std::io::{Error, ErrorKind};
use std::mem;
macro_rules! iovec {
($value:expr, $size:expr) => {
libc::iovec {
iov_base: $value as *mut libc::c_void,
iov_len: $size,
}
};
($name:expr) => {
libc::iovec {
iov_base: $name.as_ptr() as *mut libc::c_void,
iov_len: $name.len(),
}
};
}
#[cfg(target_os = "freebsd")]
pub fn jail_getname(jid: i32) -> Result<String, Error> {
let mut namebuf: [u8; 256] = unsafe { mem::zeroed() };
let mut errmsg: [u8; 256] = unsafe { mem::zeroed() };
let mut jid = jid;
let mut jiov: Vec<libc::iovec> = vec![
iovec!(b"jid\0"),
iovec!(&mut jid as *mut _, mem::size_of::<i32>()),
iovec!(b"name\0"),
iovec!(namebuf.as_mut_ptr(), namebuf.len()),
iovec!(b"errmsg\0"),
iovec!(errmsg.as_mut_ptr(), errmsg.len()),
];
let jid = unsafe {
libc::jail_get(
jiov[..].as_mut_ptr() as *mut libc::iovec,
jiov.len() as u32,
0,
)
};
let err = unsafe { CStr::from_ptr(errmsg.as_ptr() as *mut i8) };
let name = unsafe { CStr::from_ptr(namebuf.as_ptr() as *mut i8) };
match jid {
e if e < 0 => match errmsg[0] {
0 => Err(Error::last_os_error()),
_ => Err(Error::new(
ErrorKind::Other,
format!("{}", err.to_string_lossy()),
)),
},
_ => Ok(name.to_string_lossy().into_owned()),
}
}
#[cfg(target_os = "freebsd")]
pub fn jail_getid(name: &str) -> Result<i32, Error> {
let mut errmsg: [u8; 256] = unsafe { mem::zeroed() };
if let Ok(jid) = name.parse::<i32>() {
return Ok(jid);
};
let name = CString::new(name).unwrap().into_bytes_with_nul();
let mut jiov = vec![
iovec!(b"name\0"),
iovec!(name),
iovec!(b"errmsg\0"),
iovec!(errmsg.as_mut_ptr(), errmsg.len()),
];
let jid = unsafe {
libc::jail_get(
jiov[..].as_mut_ptr() as *mut libc::iovec,
jiov.len() as u32,
0,
)
};
let err = unsafe { CStr::from_ptr(errmsg.as_ptr() as *mut i8) };
match jid {
e if e < 0 => match errmsg[0] {
0 => Err(Error::last_os_error()),
_ => Err(Error::new(
ErrorKind::Other,
format!("{}", err.to_string_lossy()),
)),
},
_ => Ok(jid),
}
}
pub fn jail_remove(jid: i32) -> Result<(), Error> {
let ret = unsafe { libc::jail_remove(jid) };
match ret {
0 => Ok(()),
-1 => Err(Error::last_os_error()),
_ => Err(Error::new(
ErrorKind::Other,
"invalid return value from jail_remove",
)),
}
}
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
#[cfg(target_os = "freebsd")]
pub struct Jail {
pub jid: i32,
}
impl Default for Jail {
fn default() -> Jail {
Jail { jid: -1 }
}
}
impl Jail {
pub fn from_jid(jid: i32) -> Jail {
Jail { jid: jid }
}
pub fn from_name(name: &str) -> Result<Jail, Error> {
jail_getid(name).map(Jail::from_jid)
}
pub fn name(self: &Jail) -> Result<String, Error> {
jail_getname(self.jid)
}
pub fn kill(self: &Jail) -> Result<(), Error> {
jail_remove(self.jid)
}
}