pH/src/init/sys.rs
2019-09-20 17:29:55 -04:00

203 lines
5.4 KiB
Rust

use std::io;
use std::ptr;
use std::ffi::{CString, OsStr};
use std::os::unix::ffi::OsStrExt;
use crate::error::{Result,Error};
use libc;
use std::path::Path;
pub fn mount_tmpfs(target: &str) -> Result<()> {
mount("tmpfs", target, "tmpfs", 0, Some("mode=755"))
.map_err(|e| Error::MountTmpFS(target.to_string(), e))
}
pub fn mount_procfs() -> Result<()> {
mount("proc", "/proc", "proc", 0, None)
.map_err(Error::MountProcFS)
}
pub fn mount_sysfs() -> Result<()> {
mount("sysfs", "/sys", "sysfs", 0, None)
.map_err(Error::MountSysFS)
}
pub fn mount_devtmpfs() -> Result<()> {
mount("devtmpfs", "/dev", "devtmpfs", 0, None)
.map_err(Error::MountDevTmpFS)
}
pub fn mount_devpts() -> Result<()> {
let target = "/dev/pts";
if !Path::new(target).exists() {
mkdir(target)?;
}
mount("devpts", target, "devpts", 0, None)
.map_err(Error::MountDevPts)
}
pub fn mount_overlay(target: &str, args: &str) -> Result<()> {
mount("overlay", target, "overlay", 0, Some(args))
.map_err(Error::MountOverlay)
}
pub fn move_mount(source: &str, target: &str) -> Result<()> {
mount(source, target, "", libc::MS_MOVE, None)
.map_err(|e| Error::MoveMount(source.to_string(), target.to_string(), e))
}
pub fn mount_9p(name: &str, target: &str) -> Result<()> {
const MS_LAZYTIME: libc::c_ulong = (1 << 25);
mount(name, target, "9p", libc::MS_NOATIME|MS_LAZYTIME, Some("trans=virtio,cache=loose"))
.map_err(|e| Error::Mount9P(name.to_string(), target.to_string(), e))
}
fn cstr(s: &str) -> CString {
CString::new(s).unwrap()
}
pub fn create_directories<P: AsRef<Path>>(directories: &[P]) -> Result<()> {
for dir in directories {
mkdir(dir)?;
}
Ok(())
}
pub fn mkdir<P: AsRef<Path>>(path: P) -> Result<()> {
let path = path.as_ref();
let path_cstr = CString::new(path.as_os_str().as_bytes()).map_err(|_| Error::CStringConv)?;
unsafe {
if libc::mkdir(path_cstr.as_ptr(), 0o755) == -1 {
return Err(Error::MkDir(path.display().to_string(), io::Error::last_os_error()))
}
}
Ok(())
}
pub fn sethostname<S: AsRef<OsStr>>(name: S) -> Result<()> {
let ptr = name.as_ref().as_bytes().as_ptr() as *const libc::c_char;
let len = name.as_ref().len() as libc::size_t;
unsafe {
if libc::sethostname(ptr, len) < 0 {
let last = io::Error::last_os_error();
return Err(Error::SetHostname(last))
}
}
Ok(())
}
pub fn setsid() -> Result<u32> {
unsafe {
let res = libc::setsid();
if res == -1 {
let last = io::Error::last_os_error();
return Err(Error::SetSid(last))
}
Ok(res as u32)
}
}
pub fn mount(source: &str, target: &str, fstype: &str, flags: u64, data: Option<&str>)
-> io::Result<()> where {
let source = cstr(source);
let target = cstr(target);
let fstype = cstr(fstype);
let data = data.map(|s| cstr(s) );
let data_ptr = match data {
Some(ref s) => s.as_ptr(),
None => ptr::null(),
};
unsafe {
if libc::mount(source.as_ptr(),
target.as_ptr(),
fstype.as_ptr(),
flags,
data_ptr as *const libc::c_void) == -1 {
return Err(io::Error::last_os_error());
}
}
Ok(())
}
pub fn pivot_root(new_root: &str, put_old: &str) -> Result<()> {
let _new_root = cstr(new_root);
let _put_old = cstr(put_old);
unsafe {
if libc::syscall(libc::SYS_pivot_root, _new_root.as_ptr(), _put_old.as_ptr()) == -1 {
let last = io::Error::last_os_error();
return Err(Error::PivotRoot(new_root.to_string(), put_old.to_string(), last))
}
}
Ok(())
}
pub fn umount(path: &str) -> Result<()> {
let _path = cstr(path);
unsafe {
if libc::umount(_path.as_ptr()) == -1 {
let last = io::Error::last_os_error();
return Err(Error::Umount(path.to_string(), last))
}
}
Ok(())
}
pub fn set_controlling_tty(fd: libc::c_int, force: bool) -> Result<()> {
let flag: libc::c_int = if force { 1 } else { 0 };
unsafe {
if libc::ioctl(fd, libc::TIOCSCTTY, flag) == -1 {
let last = io::Error::last_os_error();
return Err(Error::SetControllingTty(last))
}
Ok(())
}
}
pub fn waitpid(pid: libc::pid_t, options: libc::c_int) -> io::Result<i32> {
let mut status = 0 as libc::c_int;
unsafe {
if libc::waitpid(pid, &mut status, options) == -1 {
return Err(io::Error::last_os_error())
}
}
Ok(status)
}
pub fn getpid() -> i32 {
unsafe { libc::getpid() }
}
pub fn chmod(path: &str, mode: u32) -> Result<()> {
let path = cstr(path);
unsafe {
if libc::chmod(path.as_ptr(), mode) == -1 {
let last = io::Error::last_os_error();
return Err(Error::ChmodFailed(last));
}
}
Ok(())
}
pub fn chown(path: &str, uid: u32, gid: u32) -> Result<()> {
let path = cstr(path);
unsafe {
if libc::chown(path.as_ptr(), uid, gid) == -1 {
let last = io::Error::last_os_error();
return Err(Error::ChmodFailed(last));
}
}
Ok(())
}
pub fn reboot(cmd: libc::c_int) -> io::Result<()> {
unsafe {
if libc::reboot(cmd) == -1 {
return Err(io::Error::last_os_error());
}
Ok(())
}
}