use crate::error::ErrorKind::*;
use crate::error::{Result, SeccompError};
use libseccomp_sys::*;
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ScmpArch {
Native,
X86,
X8664,
X32,
Arm,
Aarch64,
Loongarch64,
M68k,
Mips,
Mips64,
Mips64N32,
Mipsel,
Mipsel64,
Mipsel64N32,
Ppc,
Ppc64,
Ppc64Le,
S390,
S390X,
Parisc,
Parisc64,
Riscv64,
Sheb,
Sh,
}
impl ScmpArch {
pub(crate) fn to_sys(self) -> u32 {
match self {
Self::Native => SCMP_ARCH_NATIVE,
Self::X86 => SCMP_ARCH_X86,
Self::X8664 => SCMP_ARCH_X86_64,
Self::X32 => SCMP_ARCH_X32,
Self::Arm => SCMP_ARCH_ARM,
Self::Aarch64 => SCMP_ARCH_AARCH64,
Self::Loongarch64 => SCMP_ARCH_LOONGARCH64,
Self::M68k => SCMP_ARCH_M68K,
Self::Mips => SCMP_ARCH_MIPS,
Self::Mips64 => SCMP_ARCH_MIPS64,
Self::Mips64N32 => SCMP_ARCH_MIPS64N32,
Self::Mipsel => SCMP_ARCH_MIPSEL,
Self::Mipsel64 => SCMP_ARCH_MIPSEL64,
Self::Mipsel64N32 => SCMP_ARCH_MIPSEL64N32,
Self::Ppc => SCMP_ARCH_PPC,
Self::Ppc64 => SCMP_ARCH_PPC64,
Self::Ppc64Le => SCMP_ARCH_PPC64LE,
Self::S390 => SCMP_ARCH_S390,
Self::S390X => SCMP_ARCH_S390X,
Self::Parisc => SCMP_ARCH_PARISC,
Self::Parisc64 => SCMP_ARCH_PARISC64,
Self::Riscv64 => SCMP_ARCH_RISCV64,
Self::Sheb => SCMP_ARCH_SHEB,
Self::Sh => SCMP_ARCH_SH,
}
}
pub(crate) fn from_sys(arch: u32) -> Result<Self> {
match arch {
SCMP_ARCH_NATIVE => Ok(Self::Native),
SCMP_ARCH_X86 => Ok(Self::X86),
SCMP_ARCH_X86_64 => Ok(Self::X8664),
SCMP_ARCH_X32 => Ok(Self::X32),
SCMP_ARCH_ARM => Ok(Self::Arm),
SCMP_ARCH_AARCH64 => Ok(Self::Aarch64),
SCMP_ARCH_LOONGARCH64 => Ok(Self::Loongarch64),
SCMP_ARCH_M68K => Ok(Self::M68k),
SCMP_ARCH_MIPS => Ok(Self::Mips),
SCMP_ARCH_MIPS64 => Ok(Self::Mips64),
SCMP_ARCH_MIPS64N32 => Ok(Self::Mips64N32),
SCMP_ARCH_MIPSEL => Ok(Self::Mipsel),
SCMP_ARCH_MIPSEL64 => Ok(Self::Mipsel64),
SCMP_ARCH_MIPSEL64N32 => Ok(Self::Mipsel64N32),
SCMP_ARCH_PPC => Ok(Self::Ppc),
SCMP_ARCH_PPC64 => Ok(Self::Ppc64),
SCMP_ARCH_PPC64LE => Ok(Self::Ppc64Le),
SCMP_ARCH_S390 => Ok(Self::S390),
SCMP_ARCH_S390X => Ok(Self::S390X),
SCMP_ARCH_PARISC => Ok(Self::Parisc),
SCMP_ARCH_PARISC64 => Ok(Self::Parisc64),
SCMP_ARCH_RISCV64 => Ok(Self::Riscv64),
SCMP_ARCH_SHEB => Ok(Self::Sheb),
SCMP_ARCH_SH => Ok(Self::Sh),
_ => Err(SeccompError::new(InvalidArch(arch))),
}
}
pub fn native() -> Self {
Self::from_sys(unsafe { seccomp_arch_native() }).expect("Could not get native architecture")
}
}
impl FromStr for ScmpArch {
type Err = SeccompError;
fn from_str(arch: &str) -> Result<Self> {
match arch {
"SCMP_ARCH_NATIVE" => Ok(Self::Native),
"SCMP_ARCH_X86" => Ok(Self::X86),
"SCMP_ARCH_X86_64" => Ok(Self::X8664),
"SCMP_ARCH_X32" => Ok(Self::X32),
"SCMP_ARCH_ARM" => Ok(Self::Arm),
"SCMP_ARCH_AARCH64" => Ok(Self::Aarch64),
"SCMP_ARCH_LOONGARCH64" => Ok(Self::Loongarch64),
"SCMP_ARCH_M68K" => Ok(Self::M68k),
"SCMP_ARCH_MIPS" => Ok(Self::Mips),
"SCMP_ARCH_MIPS64" => Ok(Self::Mips64),
"SCMP_ARCH_MIPS64N32" => Ok(Self::Mips64N32),
"SCMP_ARCH_MIPSEL" => Ok(Self::Mipsel),
"SCMP_ARCH_MIPSEL64" => Ok(Self::Mipsel64),
"SCMP_ARCH_MIPSEL64N32" => Ok(Self::Mipsel64N32),
"SCMP_ARCH_PPC" => Ok(Self::Ppc),
"SCMP_ARCH_PPC64" => Ok(Self::Ppc64),
"SCMP_ARCH_PPC64LE" => Ok(Self::Ppc64Le),
"SCMP_ARCH_S390" => Ok(Self::S390),
"SCMP_ARCH_S390X" => Ok(Self::S390X),
"SCMP_ARCH_PARISC" => Ok(Self::Parisc),
"SCMP_ARCH_PARISC64" => Ok(Self::Parisc64),
"SCMP_ARCH_RISCV64" => Ok(Self::Riscv64),
"SCMP_ARCH_SHEB" => Ok(Self::Sheb),
"SCMP_ARCH_SH" => Ok(Self::Sh),
_ => Err(SeccompError::new(FromStr(arch.to_string()))),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_arch() {
let test_data = &[
("SCMP_ARCH_NATIVE", ScmpArch::Native),
("SCMP_ARCH_X86", ScmpArch::X86),
("SCMP_ARCH_X86_64", ScmpArch::X8664),
("SCMP_ARCH_X32", ScmpArch::X32),
("SCMP_ARCH_ARM", ScmpArch::Arm),
("SCMP_ARCH_AARCH64", ScmpArch::Aarch64),
("SCMP_ARCH_LOONGARCH64", ScmpArch::Loongarch64),
("SCMP_ARCH_M68K", ScmpArch::M68k),
("SCMP_ARCH_MIPS", ScmpArch::Mips),
("SCMP_ARCH_MIPS64", ScmpArch::Mips64),
("SCMP_ARCH_MIPS64N32", ScmpArch::Mips64N32),
("SCMP_ARCH_MIPSEL", ScmpArch::Mipsel),
("SCMP_ARCH_MIPSEL64", ScmpArch::Mipsel64),
("SCMP_ARCH_MIPSEL64N32", ScmpArch::Mipsel64N32),
("SCMP_ARCH_PPC", ScmpArch::Ppc),
("SCMP_ARCH_PPC64", ScmpArch::Ppc64),
("SCMP_ARCH_PPC64LE", ScmpArch::Ppc64Le),
("SCMP_ARCH_S390", ScmpArch::S390),
("SCMP_ARCH_S390X", ScmpArch::S390X),
("SCMP_ARCH_PARISC", ScmpArch::Parisc),
("SCMP_ARCH_PARISC64", ScmpArch::Parisc64),
("SCMP_ARCH_RISCV64", ScmpArch::Riscv64),
("SCMP_ARCH_SHEB", ScmpArch::Sheb),
("SCMP_ARCH_SH", ScmpArch::Sh),
];
for data in test_data {
assert_eq!(
ScmpArch::from_sys(ScmpArch::from_str(data.0).unwrap().to_sys()).unwrap(),
data.1
);
}
assert!(ScmpArch::from_str("SCMP_INVALID_FLAG").is_err());
assert!(ScmpArch::from_sys(1).is_err());
}
}