use std::{ffi::CString, os::unix::ffi::OsStrExt};
use uhyve_interface::v2::parameters::*;
use crate::{
hypercall::{decode_guest_path, translate_last_errno},
isolation::filemap::{UhyveFileMap, UhyveMapLeaf},
mem::MmapMemory,
};
fn host_mkdir(host_path_c: &CString) -> MkdirResult {
if unsafe { libc::mkdir(host_path_c.as_ptr(), 0o777) } < 0 {
MkdirResult::Error(translate_last_errno().unwrap_or(EIO))
} else {
MkdirResult::Success
}
}
pub(crate) fn mkdir(mem: &MmapMemory, sysmkdir: &mut MkdirParams, file_map: &mut UhyveFileMap) {
let Some(guest_path) = (unsafe { decode_guest_path(mem, sysmkdir.path) }) else {
error!("The kernel requested to mkdir() a non-UTF8 path: Rejecting...");
sysmkdir.ret = MkdirResult::Error(EINVAL);
return;
};
sysmkdir.ret = match file_map.get_host_path(guest_path, false) {
Some(UhyveMapLeaf::OnHost(host_path)) => {
let host_path_c = CString::new(host_path.as_os_str().as_bytes()).unwrap();
host_mkdir(&host_path_c)
}
Some(UhyveMapLeaf::Virtual(_)) => {
debug!("mkdir {guest_path:?}: target is a read-only virtual file, rejecting...");
MkdirResult::Error(EROFS)
}
None => {
debug!("mkdir {guest_path:?}: not mapped, creating a temporary directory...");
match file_map.create_temporary_directory(guest_path) {
Some(host_path_c) => host_mkdir(&host_path_c),
None => MkdirResult::Error(EINVAL),
}
}
};
}