use hdrepresentation::*;
use penguincrab::*;
use std::env;
use std::io::{Error, ErrorKind};
pub fn exec(p: &Program, image_path: String, fs_type: String) -> Result<(), std::io::Error> {
let new_path = String::from(image_path.clone());
let server = LklSetup::new(LklSetupArgs {
filename: new_path.clone(),
boot_settings: Some(String::from("mem=128M\0")),
partition_num: None,
filesystem_type: Some(fs_type),
filesystem_options: None,
on_panic: None,
print: None,
})
.unwrap();
for sys in p.syscalls.iter() {
match exec_syscall(p, sys, server.mount_point.clone()) {
Ok(ret_val) => {
if ret_val < 0 {
eprintln!("{} => {ret_val} {}", get_syscall(p, sys),
strerror(&(ret_val as i32)).unwrap());
} else {
println!("{} => {ret_val}", get_syscall(p, sys));
}
}
Err(e) => {
eprintln!("exec_syscall failed {} => {e}", get_syscall(p, sys));
}
}
}
for fd in p.active_fds.iter() {
lkl_sys_close(*fd as i32);
}
Ok(())
}
pub fn exec_syscall(prog: &Program, syscall: &Syscall, mount_point: String) -> Result<i64, String> {
let mut vars = Vec::<VariableType>::new();
for arg in syscall.args.iter() {
if arg.is_variable {
vars.push(
*prog
.variables
.get(arg.index.expect("exec_syscall failed to unwrap index"))
.expect("exec_syscall failed to find anything at the provided index")
.var_type
.clone(),
);
} else {
vars.push(VariableType::Long(
arg.value.expect("exec syscall failed to unwrap value"),
));
}
}
match syscall.nr {
SysNo::Open => {
let path = var_to_path(&vars[0], &mount_point)?;
let flags = var_to_u32(&vars[1])?;
let mode = var_to_u32(&vars[2])?;
return Ok(lkl_sys_open(to_cstr(&path).unwrap(), flags, mode));
}
SysNo::Read => {
let fd = var_to_i32(&vars[0])?;
let mut buf = var_to_vec(&vars[1])?;
let count = var_to_usize(&vars[2])?;
return Ok(lkl_sys_read(fd, &mut buf[..], count));
}
SysNo::Write => {
let fd = var_to_i32(&vars[0])?;
let buf = var_to_str(&vars[1])?;
let count = var_to_usize(&vars[2])?;
return Ok(lkl_sys_write(fd, buf.as_bytes(), count));
}
SysNo::Lseek => {
let fd = var_to_i32(&vars[0])?;
let offset = var_to_u32(&vars[1])?;
let origin = var_to_u32(&vars[2])?;
return Ok(lkl_sys_lseek(fd, offset, origin));
}
SysNo::Getdents => {
let fd = var_to_i32(&vars[0])?;
let mut dirent = dirent64::default();
let count = var_to_usize(&vars[2])?;
return Ok(lkl_sys_getdents64(fd, &mut dirent, count));
}
SysNo::Pread => {
let fd = var_to_i32(&vars[0])?;
let mut buf = var_to_vec(&vars[1])?;
let count = var_to_usize(&vars[2])?;
let off = var_to_u64(&vars[3])?;
return Ok(lkl_sys_pread64(fd, &mut buf[..], count, off));
}
SysNo::Pwrite => {
let fd = var_to_i32(&vars[0])?;
let buf = var_to_vec(&vars[1])?;
let count = var_to_usize(&vars[2])?;
let off = var_to_u64(&vars[3])?;
return Ok(lkl_sys_pwrite64(fd, &buf[..], count, off));
}
SysNo::Fstat => {
let fd = var_to_i32(&vars[0])?;
let mut stat = stat::default();
return Ok(lkl_sys_fstat(fd, &mut stat));
}
SysNo::Rename => {
let path = var_to_path(&vars[0], &mount_point)?;
let newpath = var_to_path(&vars[1], &mount_point)?;
return Ok(lkl_sys_rename(
to_cstr(&path).unwrap(),
to_cstr(&newpath).unwrap(),
));
}
SysNo::Fsync => {
let fd = var_to_i32(&vars[0])?;
return Ok(lkl_sys_fsync(fd));
}
SysNo::Fdatasync => Ok(lkl_sys_fdatasync(var_to_i32(&vars[0])?)),
SysNo::Syncfs => Ok(lkl_sys_syncfs(var_to_i32(&vars[0])?)),
SysNo::Sendfile => {
let mut v = Vec::new();
v.push(var_to_i32(&vars[2])? as u8);
Ok(lkl_sys_sendfile(
var_to_i32(&vars[0])?,
var_to_i32(&vars[1])?,
&mut v[..],
var_to_usize(&vars[3])?,
))
}
SysNo::Access => Ok(lkl_sys_access(
to_cstr(&var_to_path(&vars[0], &mount_point)?).unwrap(),
var_to_i32(&vars[1])?,
)),
SysNo::Ftruncate => Ok(lkl_sys_ftruncate(
var_to_i32(&vars[0])?,
var_to_u64(&vars[1])?,
)),
SysNo::Truncate => Ok(lkl_sys_truncate(
to_cstr(&var_to_path(&vars[0], &mount_point)?).unwrap(),
var_to_i64(&vars[1])?,
)),
SysNo::Mkdir => Ok(lkl_sys_mkdir(
to_cstr(&var_to_path(&vars[0], &mount_point)?).unwrap(),
var_to_u32(&vars[1])?,
)),
SysNo::Rmdir => Ok(lkl_sys_rmdir(
to_cstr(&var_to_path(&vars[0], &mount_point)?).unwrap(),
)),
SysNo::Link => Ok(lkl_sys_link(
to_cstr(&var_to_path(&vars[0], &mount_point)?).unwrap(),
to_cstr(&var_to_path(&vars[1], &mount_point)?).unwrap(),
)),
SysNo::Unlink => Ok(lkl_sys_unlink(
to_cstr(&var_to_path(&vars[0], &mount_point)?).unwrap(),
)),
SysNo::Symlink => Ok(lkl_sys_symlink(
to_cstr(&var_to_path(&vars[0], &mount_point)?).unwrap(),
to_cstr(&var_to_path(&vars[1], &mount_point)?).unwrap(),
)),
SysNo::Setxattr => {
Ok(lkl_sys_setxattr(
to_cstr(&var_to_path(&vars[0], &mount_point)?).unwrap(),
to_cstr(&var_to_str(&vars[1])?).unwrap(),
to_cstr(&var_to_str(&vars[2])?).unwrap(),
var_to_usize(&vars[3])?,
var_to_u32(&vars[4])?,
))
},
SysNo::Listxattr => Ok(lkl_sys_listxattr(
to_cstr(&var_to_path(&vars[0], &mount_point)?).unwrap(),
&mut var_to_vec(&vars[1])?[..],
)),
SysNo::Removexattr => Ok(lkl_sys_removexattr(
to_cstr(&var_to_path(&vars[0], &mount_point)?).unwrap(),
to_cstr(&var_to_str(&vars[1])?).unwrap(),
)),
_ => {
return Err("not implemented".to_string());
}
}
}
fn var_to_str(v: &VariableType) -> Result<String, String> {
match v {
VariableType::Str(s) => {
let mut s_with_nul = String::from(s);
s_with_nul.push_str("\0");
Ok(s_with_nul.to_owned())
},
_ => Err(format!("failed to convert {:?} to str", v)),
}
}
fn var_to_u32(v: &VariableType) -> Result<u32, String> {
match v {
VariableType::Long(n) => Ok(*n as u32),
_ => Err(format!("failed to convert {:?} to u32", v)),
}
}
fn var_to_u64(v: &VariableType) -> Result<u64, String> {
match v {
VariableType::Long(n) => Ok(*n as u64),
_ => Err(format!("failed to convert {:?} to u64", v)),
}
}
fn var_to_i64(v: &VariableType) -> Result<i64, String> {
match v {
VariableType::Long(n) => Ok(*n as i64),
_ => Err(format!("invalid i64 {:?}", v)),
}
}
fn var_to_usize(v: &VariableType) -> Result<usize, String> {
match v {
VariableType::Long(n) => Ok(*n as usize),
_ => {
eprintln!("invalid usize {:?}", v);
return Err(format!("invalid usize {:?}", v));
}
}
}
fn var_to_i32(v: &VariableType) -> Result<i32, String> {
match v {
VariableType::Long(n) => Ok(*n as i32),
_ => Err(format!("invalid i32 {:?}", v)),
}
}
fn var_to_path(v: &VariableType, mount_point: &str) -> Result<String, String> {
match v {
VariableType::Str(s) => {
let mut mpoint = String::from(mount_point);
mpoint.push_str(&s);
mpoint.push_str("\0");
Ok(mpoint)
}
_ => Err(format!("invalid path {:?}", v)),
}
}
fn var_to_vec(v: &VariableType) -> Result<Vec<u8>, String> {
match v {
VariableType::UCharPtr(bytes, size) => match bytes {
None => Ok(vec![0; *size as usize]),
Some(buf) => Ok(buf.clone()),
},
_ => Err(format!("invalid vector {:?}", v)),
}
}
fn main() -> Result<(), std::io::Error> {
let args: Vec<String> = env::args().collect();
if args.len() != 4 {
eprintln!(
"Usage: {} [deserialized program] [filesystem image] [filesystem type(i.e. ext4, btrfs)]",
&args[0]
);
return Err(Error::new(ErrorKind::Other, "invalid arguments"));
}
let f = Program::from_path(&args[1]);
exec(&f, args[2].clone(), args[3].clone())?;
Ok(())
}