use std::any::Any;
use std::ffi::OsStr;
use std::os::fd::{BorrowedFd, RawFd};
use std::os::unix::io::OwnedFd;
use std::path::Path;
use std::sync::Arc;
use caps::{CapSet, CapsHashSet};
use libc;
use nix::mount::{MntFlags, MsFlags};
use nix::sched::CloneFlags;
use nix::sys::stat::{Mode, SFlag};
use nix::unistd::{Gid, Uid};
use oci_spec::runtime::PosixRlimit;
use crate::config::PersonalityDomain;
use crate::syscall::Result;
use crate::syscall::linux::{LinuxSyscall, MountAttr};
use crate::syscall::test::TestHelperSyscall;
pub trait Syscall {
fn as_any(&self) -> &dyn Any;
fn pivot_rootfs(&self, path: &Path) -> Result<()>;
fn chroot(&self, path: &Path) -> Result<()>;
fn set_ns(&self, rawfd: i32, nstype: CloneFlags) -> Result<()>;
fn set_id(&self, uid: Uid, gid: Gid) -> Result<()>;
fn unshare(&self, flags: CloneFlags) -> Result<()>;
fn set_capability(&self, cset: CapSet, value: &CapsHashSet) -> Result<()>;
fn set_hostname(&self, hostname: &str) -> Result<()>;
fn set_domainname(&self, domainname: &str) -> Result<()>;
fn set_rlimit(&self, rlimit: &PosixRlimit) -> Result<()>;
fn get_pwuid(&self, uid: u32) -> Option<Arc<OsStr>>;
fn mount(
&self,
source: Option<&Path>,
target: &Path,
fstype: Option<&str>,
flags: MsFlags,
data: Option<&str>,
) -> Result<()>;
fn mount_from_fd(&self, source_fd: &OwnedFd, target: &Path) -> Result<()>;
fn move_mount(
&self,
from_dirfd: BorrowedFd<'_>,
from_path: Option<&str>,
to_dirfd: BorrowedFd<'_>,
to_path: Option<&str>,
flags: u32,
) -> Result<()>;
fn fsopen(&self, fstype: Option<&str>, flags: u32) -> Result<OwnedFd>;
fn fsconfig(
&self,
fsfd: BorrowedFd<'_>,
cmd: u32,
key: Option<&str>,
val: Option<&str>,
aux: libc::c_int,
) -> Result<()>;
fn fsmount(&self, fsfd: BorrowedFd<'_>, flags: u32, attr_flags: Option<u64>)
-> Result<OwnedFd>;
fn open_tree(&self, dirfd: RawFd, path: Option<&str>, flags: u32) -> Result<OwnedFd>;
fn symlink(&self, original: &Path, link: &Path) -> Result<()>;
fn mknod(&self, path: &Path, kind: SFlag, perm: Mode, dev: u64) -> Result<()>;
fn chown(&self, path: &Path, owner: Option<Uid>, group: Option<Gid>) -> Result<()>;
fn set_groups(&self, groups: &[Gid]) -> Result<()>;
fn close_range(&self, preserve_fds: i32) -> Result<()>;
fn mount_setattr(
&self,
dirfd: BorrowedFd<'_>,
pathname: &Path,
flags: u32,
mount_attr: &MountAttr,
size: libc::size_t,
) -> Result<()>;
fn set_io_priority(&self, class: i64, priority: i64) -> Result<()>;
fn set_mempolicy(&self, mode: i32, nodemask: &[libc::c_ulong], maxnode: u64) -> Result<()>;
fn umount2(&self, target: &Path, flags: MntFlags) -> Result<()>;
fn get_uid(&self) -> Uid;
fn get_gid(&self) -> Gid;
fn get_euid(&self) -> Uid;
fn get_egid(&self) -> Gid;
fn personality(&self, domain: PersonalityDomain) -> Result<()>;
}
#[derive(Clone, Copy)]
pub enum SyscallType {
Linux,
Test,
}
impl Default for SyscallType {
fn default() -> Self {
if cfg!(test) {
SyscallType::Test
} else {
SyscallType::Linux
}
}
}
impl SyscallType {
pub fn create_syscall(&self) -> Box<dyn Syscall> {
match self {
SyscallType::Linux => Box::new(LinuxSyscall),
SyscallType::Test => Box::<TestHelperSyscall>::default(),
}
}
}
pub fn create_syscall() -> Box<dyn Syscall> {
SyscallType::default().create_syscall()
}