pub mod errors;
pub mod runtime;
pub mod securebits;
mod ambient;
mod base;
mod bounding;
mod nr;
use bitflags::bitflags;
use nix::errno::Errno;
use crate::caps::errors::CapsError;
#[derive(Debug, Clone, Copy)]
pub enum CapSet {
Ambient,
Bounding,
Effective,
Inheritable,
Permitted,
}
#[cfg(feature = "oci")]
use oci_spec::runtime::Capability as SpecCapability;
#[expect(clippy::manual_non_exhaustive)]
#[expect(non_camel_case_types)]
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
#[repr(u8)]
pub enum Capability {
CAP_CHOWN = nr::CAP_CHOWN,
CAP_DAC_OVERRIDE = nr::CAP_DAC_OVERRIDE,
CAP_DAC_READ_SEARCH = nr::CAP_DAC_READ_SEARCH,
CAP_FOWNER = nr::CAP_FOWNER,
CAP_FSETID = nr::CAP_FSETID,
CAP_KILL = nr::CAP_KILL,
CAP_SETGID = nr::CAP_SETGID,
CAP_SETUID = nr::CAP_SETUID,
CAP_SETPCAP = nr::CAP_SETPCAP,
CAP_LINUX_IMMUTABLE = nr::CAP_LINUX_IMMUTABLE,
CAP_NET_BIND_SERVICE = nr::CAP_NET_BIND_SERVICE,
CAP_NET_BROADCAST = nr::CAP_NET_BROADCAST,
CAP_NET_ADMIN = nr::CAP_NET_ADMIN,
CAP_NET_RAW = nr::CAP_NET_RAW,
CAP_IPC_LOCK = nr::CAP_IPC_LOCK,
CAP_IPC_OWNER = nr::CAP_IPC_OWNER,
CAP_SYS_MODULE = nr::CAP_SYS_MODULE,
CAP_SYS_RAWIO = nr::CAP_SYS_RAWIO,
CAP_SYS_CHROOT = nr::CAP_SYS_CHROOT,
CAP_SYS_PTRACE = nr::CAP_SYS_PTRACE,
CAP_SYS_PACCT = nr::CAP_SYS_PACCT,
CAP_SYS_ADMIN = nr::CAP_SYS_ADMIN,
CAP_SYS_BOOT = nr::CAP_SYS_BOOT,
CAP_SYS_NICE = nr::CAP_SYS_NICE,
CAP_SYS_RESOURCE = nr::CAP_SYS_RESOURCE,
CAP_SYS_TIME = nr::CAP_SYS_TIME,
CAP_SYS_TTY_CONFIG = nr::CAP_SYS_TTY_CONFIG,
CAP_MKNOD = nr::CAP_MKNOD,
CAP_LEASE = nr::CAP_LEASE,
CAP_AUDIT_WRITE = nr::CAP_AUDIT_WRITE,
CAP_AUDIT_CONTROL = nr::CAP_AUDIT_CONTROL,
CAP_SETFCAP = nr::CAP_SETFCAP,
CAP_MAC_OVERRIDE = nr::CAP_MAC_OVERRIDE,
CAP_MAC_ADMIN = nr::CAP_MAC_ADMIN,
CAP_SYSLOG = nr::CAP_SYSLOG,
CAP_WAKE_ALARM = nr::CAP_WAKE_ALARM,
CAP_BLOCK_SUSPEND = nr::CAP_BLOCK_SUSPEND,
CAP_AUDIT_READ = nr::CAP_AUDIT_READ,
CAP_PERFMON = nr::CAP_PERFMON,
CAP_BPF = nr::CAP_BPF,
CAP_CHECKPOINT_RESTORE = nr::CAP_CHECKPOINT_RESTORE,
#[doc(hidden)]
__Nonexhaustive,
}
impl std::fmt::Display for Capability {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let name = match *self {
Capability::CAP_CHOWN => "cap_chown",
Capability::CAP_DAC_OVERRIDE => "cap_dac_override",
Capability::CAP_DAC_READ_SEARCH => "cap_dac_read_search",
Capability::CAP_FOWNER => "cap_fowner",
Capability::CAP_FSETID => "cap_fsetid",
Capability::CAP_KILL => "cap_kill",
Capability::CAP_SETGID => "cap_setgid",
Capability::CAP_SETUID => "cap_setuid",
Capability::CAP_SETPCAP => "cap_setpcap",
Capability::CAP_LINUX_IMMUTABLE => "cap_linux_immutable",
Capability::CAP_NET_BIND_SERVICE => "cap_net_bind_service",
Capability::CAP_NET_BROADCAST => "cap_net_broadcast",
Capability::CAP_NET_ADMIN => "cap_net_admin",
Capability::CAP_NET_RAW => "cap_net_raw",
Capability::CAP_IPC_LOCK => "cap_ipc_lock",
Capability::CAP_IPC_OWNER => "cap_ipc_owner",
Capability::CAP_SYS_MODULE => "cap_sys_module",
Capability::CAP_SYS_RAWIO => "cap_sys_rawio",
Capability::CAP_SYS_CHROOT => "cap_sys_chroot",
Capability::CAP_SYS_PTRACE => "cap_sys_ptrace",
Capability::CAP_SYS_PACCT => "cap_sys_pacct",
Capability::CAP_SYS_ADMIN => "cap_sys_admin",
Capability::CAP_SYS_BOOT => "cap_sys_boot",
Capability::CAP_SYS_NICE => "cap_sys_nice",
Capability::CAP_SYS_RESOURCE => "cap_sys_resource",
Capability::CAP_SYS_TIME => "cap_sys_time",
Capability::CAP_SYS_TTY_CONFIG => "cap_sys_tty_config",
Capability::CAP_MKNOD => "cap_mknod",
Capability::CAP_LEASE => "cap_lease",
Capability::CAP_AUDIT_WRITE => "cap_audit_write",
Capability::CAP_AUDIT_CONTROL => "cap_audit_control",
Capability::CAP_SETFCAP => "cap_setfcap",
Capability::CAP_MAC_OVERRIDE => "cap_mac_override",
Capability::CAP_MAC_ADMIN => "cap_mac_admin",
Capability::CAP_SYSLOG => "cap_syslog",
Capability::CAP_WAKE_ALARM => "cap_wake_alarm",
Capability::CAP_BLOCK_SUSPEND => "cap_block_suspend",
Capability::CAP_AUDIT_READ => "cap_audit_read",
Capability::CAP_PERFMON => "cap_perfmon",
Capability::CAP_BPF => "cap_bpf",
Capability::CAP_CHECKPOINT_RESTORE => "cap_checkpoint_restore",
Capability::__Nonexhaustive => unreachable!("invalid capability"),
};
write!(f, "{name}")
}
}
impl std::str::FromStr for Capability {
type Err = CapsError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s.to_ascii_lowercase().as_str() {
"cap_chown" => Ok(Capability::CAP_CHOWN),
"cap_dac_override" => Ok(Capability::CAP_DAC_OVERRIDE),
"cap_dac_read_search" => Ok(Capability::CAP_DAC_READ_SEARCH),
"cap_fowner" => Ok(Capability::CAP_FOWNER),
"cap_fsetid" => Ok(Capability::CAP_FSETID),
"cap_kill" => Ok(Capability::CAP_KILL),
"cap_setgid" => Ok(Capability::CAP_SETGID),
"cap_setuid" => Ok(Capability::CAP_SETUID),
"cap_setpcap" => Ok(Capability::CAP_SETPCAP),
"cap_linux_immutable" => Ok(Capability::CAP_LINUX_IMMUTABLE),
"cap_net_bind_service" => Ok(Capability::CAP_NET_BIND_SERVICE),
"cap_net_broadcast" => Ok(Capability::CAP_NET_BROADCAST),
"cap_net_admin" => Ok(Capability::CAP_NET_ADMIN),
"cap_net_raw" => Ok(Capability::CAP_NET_RAW),
"cap_ipc_lock" => Ok(Capability::CAP_IPC_LOCK),
"cap_ipc_owner" => Ok(Capability::CAP_IPC_OWNER),
"cap_sys_module" => Ok(Capability::CAP_SYS_MODULE),
"cap_sys_rawio" => Ok(Capability::CAP_SYS_RAWIO),
"cap_sys_chroot" => Ok(Capability::CAP_SYS_CHROOT),
"cap_sys_ptrace" => Ok(Capability::CAP_SYS_PTRACE),
"cap_sys_pacct" => Ok(Capability::CAP_SYS_PACCT),
"cap_sys_admin" => Ok(Capability::CAP_SYS_ADMIN),
"cap_sys_boot" => Ok(Capability::CAP_SYS_BOOT),
"cap_sys_nice" => Ok(Capability::CAP_SYS_NICE),
"cap_sys_resource" => Ok(Capability::CAP_SYS_RESOURCE),
"cap_sys_time" => Ok(Capability::CAP_SYS_TIME),
"cap_sys_tty_config" => Ok(Capability::CAP_SYS_TTY_CONFIG),
"cap_mknod" => Ok(Capability::CAP_MKNOD),
"cap_lease" => Ok(Capability::CAP_LEASE),
"cap_audit_write" => Ok(Capability::CAP_AUDIT_WRITE),
"cap_audit_control" => Ok(Capability::CAP_AUDIT_CONTROL),
"cap_setfcap" => Ok(Capability::CAP_SETFCAP),
"cap_mac_override" => Ok(Capability::CAP_MAC_OVERRIDE),
"cap_mac_admin" => Ok(Capability::CAP_MAC_ADMIN),
"cap_syslog" => Ok(Capability::CAP_SYSLOG),
"cap_wake_alarm" => Ok(Capability::CAP_WAKE_ALARM),
"cap_block_suspend" => Ok(Capability::CAP_BLOCK_SUSPEND),
"cap_audit_read" => Ok(Capability::CAP_AUDIT_READ),
"cap_perfmon" => Ok(Capability::CAP_PERFMON),
"cap_bpf" => Ok(Capability::CAP_BPF),
"cap_checkpoint_restore" => Ok(Capability::CAP_CHECKPOINT_RESTORE),
_ => Err(CapsError(Errno::EINVAL)),
}
}
}
#[cfg(feature = "oci")]
impl Capability {
pub fn spec(&self) -> SpecCapability {
match *self {
Capability::CAP_CHOWN => SpecCapability::Chown,
Capability::CAP_DAC_OVERRIDE => SpecCapability::DacOverride,
Capability::CAP_DAC_READ_SEARCH => SpecCapability::DacReadSearch,
Capability::CAP_FOWNER => SpecCapability::Fowner,
Capability::CAP_FSETID => SpecCapability::Fsetid,
Capability::CAP_KILL => SpecCapability::Kill,
Capability::CAP_SETGID => SpecCapability::Setgid,
Capability::CAP_SETUID => SpecCapability::Setuid,
Capability::CAP_SETPCAP => SpecCapability::Setpcap,
Capability::CAP_LINUX_IMMUTABLE => SpecCapability::LinuxImmutable,
Capability::CAP_NET_BIND_SERVICE => SpecCapability::NetBindService,
Capability::CAP_NET_BROADCAST => SpecCapability::NetBroadcast,
Capability::CAP_NET_ADMIN => SpecCapability::NetAdmin,
Capability::CAP_NET_RAW => SpecCapability::NetRaw,
Capability::CAP_IPC_LOCK => SpecCapability::IpcLock,
Capability::CAP_IPC_OWNER => SpecCapability::IpcOwner,
Capability::CAP_SYS_MODULE => SpecCapability::SysModule,
Capability::CAP_SYS_RAWIO => SpecCapability::SysRawio,
Capability::CAP_SYS_CHROOT => SpecCapability::SysChroot,
Capability::CAP_SYS_PTRACE => SpecCapability::SysPtrace,
Capability::CAP_SYS_PACCT => SpecCapability::SysPacct,
Capability::CAP_SYS_ADMIN => SpecCapability::SysAdmin,
Capability::CAP_SYS_BOOT => SpecCapability::SysBoot,
Capability::CAP_SYS_NICE => SpecCapability::SysNice,
Capability::CAP_SYS_RESOURCE => SpecCapability::SysResource,
Capability::CAP_SYS_TIME => SpecCapability::SysTime,
Capability::CAP_SYS_TTY_CONFIG => SpecCapability::SysTtyConfig,
Capability::CAP_MKNOD => SpecCapability::Mknod,
Capability::CAP_LEASE => SpecCapability::Lease,
Capability::CAP_AUDIT_WRITE => SpecCapability::AuditWrite,
Capability::CAP_AUDIT_CONTROL => SpecCapability::AuditControl,
Capability::CAP_SETFCAP => SpecCapability::Setfcap,
Capability::CAP_MAC_OVERRIDE => SpecCapability::MacOverride,
Capability::CAP_MAC_ADMIN => SpecCapability::MacAdmin,
Capability::CAP_SYSLOG => SpecCapability::Syslog,
Capability::CAP_WAKE_ALARM => SpecCapability::WakeAlarm,
Capability::CAP_BLOCK_SUSPEND => SpecCapability::BlockSuspend,
Capability::CAP_AUDIT_READ => SpecCapability::AuditRead,
Capability::CAP_PERFMON => SpecCapability::Perfmon,
Capability::CAP_BPF => SpecCapability::Bpf,
Capability::CAP_CHECKPOINT_RESTORE => SpecCapability::CheckpointRestore,
Capability::__Nonexhaustive => unreachable!("invalid capability"),
}
}
}
impl TryFrom<Capabilities> for Capability {
type Error = CapsError;
fn try_from(caps: Capabilities) -> Result<Self, Self::Error> {
let bits = caps.bits();
if bits == 0 || (bits & (bits - 1)) != 0 {
return Err(CapsError(Errno::EINVAL));
}
let idx = u8::try_from(bits.trailing_zeros()).or(Err(CapsError(Errno::EINVAL)))?;
Ok(unsafe { std::mem::transmute::<u8, Capability>(idx) })
}
}
impl From<Capability> for Capabilities {
#[inline]
fn from(c: Capability) -> Self {
Capabilities::from_bits_truncate(c.bitmask())
}
}
impl Capability {
pub const fn bitmask(self) -> u64 {
1u64 << (self as u8)
}
pub const fn index(self) -> u8 {
self as u8
}
}
bitflags! {
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct Capabilities: u64 {
const CAP_CHOWN = Capability::bitmask(Capability::CAP_CHOWN);
const CAP_DAC_OVERRIDE = Capability::bitmask(Capability::CAP_DAC_OVERRIDE);
const CAP_DAC_READ_SEARCH = Capability::bitmask(Capability::CAP_DAC_READ_SEARCH);
const CAP_FOWNER = Capability::bitmask(Capability::CAP_FOWNER);
const CAP_FSETID = Capability::bitmask(Capability::CAP_FSETID);
const CAP_KILL = Capability::bitmask(Capability::CAP_KILL);
const CAP_SETGID = Capability::bitmask(Capability::CAP_SETGID);
const CAP_SETUID = Capability::bitmask(Capability::CAP_SETUID);
const CAP_SETPCAP = Capability::bitmask(Capability::CAP_SETPCAP);
const CAP_LINUX_IMMUTABLE = Capability::bitmask(Capability::CAP_LINUX_IMMUTABLE);
const CAP_NET_BIND_SERVICE = Capability::bitmask(Capability::CAP_NET_BIND_SERVICE);
const CAP_NET_BROADCAST = Capability::bitmask(Capability::CAP_NET_BROADCAST);
const CAP_NET_ADMIN = Capability::bitmask(Capability::CAP_NET_ADMIN);
const CAP_NET_RAW = Capability::bitmask(Capability::CAP_NET_RAW);
const CAP_IPC_LOCK = Capability::bitmask(Capability::CAP_IPC_LOCK);
const CAP_IPC_OWNER = Capability::bitmask(Capability::CAP_IPC_OWNER);
const CAP_SYS_MODULE = Capability::bitmask(Capability::CAP_SYS_MODULE);
const CAP_SYS_RAWIO = Capability::bitmask(Capability::CAP_SYS_RAWIO);
const CAP_SYS_CHROOT = Capability::bitmask(Capability::CAP_SYS_CHROOT);
const CAP_SYS_PTRACE = Capability::bitmask(Capability::CAP_SYS_PTRACE);
const CAP_SYS_PACCT = Capability::bitmask(Capability::CAP_SYS_PACCT);
const CAP_SYS_ADMIN = Capability::bitmask(Capability::CAP_SYS_ADMIN);
const CAP_SYS_BOOT = Capability::bitmask(Capability::CAP_SYS_BOOT);
const CAP_SYS_NICE = Capability::bitmask(Capability::CAP_SYS_NICE);
const CAP_SYS_RESOURCE = Capability::bitmask(Capability::CAP_SYS_RESOURCE);
const CAP_SYS_TIME = Capability::bitmask(Capability::CAP_SYS_TIME);
const CAP_SYS_TTY_CONFIG = Capability::bitmask(Capability::CAP_SYS_TTY_CONFIG);
const CAP_MKNOD = Capability::bitmask(Capability::CAP_MKNOD);
const CAP_LEASE = Capability::bitmask(Capability::CAP_LEASE);
const CAP_AUDIT_WRITE = Capability::bitmask(Capability::CAP_AUDIT_WRITE);
const CAP_AUDIT_CONTROL = Capability::bitmask(Capability::CAP_AUDIT_CONTROL);
const CAP_SETFCAP = Capability::bitmask(Capability::CAP_SETFCAP);
const CAP_MAC_OVERRIDE = Capability::bitmask(Capability::CAP_MAC_OVERRIDE);
const CAP_MAC_ADMIN = Capability::bitmask(Capability::CAP_MAC_ADMIN);
const CAP_SYSLOG = Capability::bitmask(Capability::CAP_SYSLOG);
const CAP_WAKE_ALARM = Capability::bitmask(Capability::CAP_WAKE_ALARM);
const CAP_BLOCK_SUSPEND = Capability::bitmask(Capability::CAP_BLOCK_SUSPEND);
const CAP_AUDIT_READ = Capability::bitmask(Capability::CAP_AUDIT_READ);
const CAP_PERFMON = Capability::bitmask(Capability::CAP_PERFMON);
const CAP_BPF = Capability::bitmask(Capability::CAP_BPF);
const CAP_CHECKPOINT_RESTORE = Capability::bitmask(Capability::CAP_CHECKPOINT_RESTORE);
}
}
pub fn has_cap(tid: Option<i32>, cset: CapSet, cap: Capability) -> Result<bool, CapsError> {
let t = tid.unwrap_or(0);
match cset {
CapSet::Ambient if t == 0 => ambient::has_cap(cap),
CapSet::Bounding if t == 0 => bounding::has_cap(cap),
CapSet::Effective | CapSet::Inheritable | CapSet::Permitted => base::has_cap(t, cset, cap),
_ => Err(CapsError(Errno::EOPNOTSUPP)),
}
}
pub fn read(tid: Option<i32>, cset: CapSet) -> Result<Capabilities, CapsError> {
let t = tid.unwrap_or(0);
match cset {
CapSet::Ambient if t == 0 => ambient::read(),
CapSet::Bounding if t == 0 => bounding::read(),
CapSet::Effective | CapSet::Inheritable | CapSet::Permitted => base::read(t, cset),
_ => Err(CapsError(Errno::EOPNOTSUPP)),
}
}
pub fn set(tid: Option<i32>, cset: CapSet, value: Capabilities) -> Result<(), CapsError> {
let t = tid.unwrap_or(0);
match cset {
CapSet::Ambient if t == 0 => ambient::set(value),
CapSet::Effective | CapSet::Inheritable | CapSet::Permitted => base::set(t, cset, value),
_ => Err(CapsError(Errno::EOPNOTSUPP)),
}
}
pub fn set_all(
tid: Option<i32>,
eff: Capabilities,
perm: Capabilities,
inh: Capabilities,
) -> Result<(), CapsError> {
base::set_epi(tid.unwrap_or(0), eff, perm, inh)
}
pub fn clear(tid: Option<i32>, cset: CapSet) -> Result<(), CapsError> {
let t = tid.unwrap_or(0);
match cset {
CapSet::Ambient if t == 0 => ambient::clear(),
CapSet::Bounding if t == 0 => bounding::clear(),
CapSet::Effective | CapSet::Permitted | CapSet::Inheritable => base::clear(t, cset),
_ => Err(CapsError(Errno::EOPNOTSUPP)),
}
}
pub fn raise(tid: Option<i32>, cset: CapSet, cap: Capability) -> Result<(), CapsError> {
let t = tid.unwrap_or(0);
match cset {
CapSet::Ambient if t == 0 => ambient::raise(cap),
CapSet::Effective | CapSet::Permitted | CapSet::Inheritable => base::raise(t, cset, cap),
_ => Err(CapsError(Errno::EOPNOTSUPP)),
}
}
pub fn drop(tid: Option<i32>, cset: CapSet, cap: Capability) -> Result<(), CapsError> {
let t = tid.unwrap_or(0);
match cset {
CapSet::Ambient if t == 0 => ambient::drop(cap),
CapSet::Bounding if t == 0 => bounding::drop(cap),
CapSet::Effective | CapSet::Permitted | CapSet::Inheritable => base::drop(t, cset, cap),
_ => Err(CapsError(Errno::EOPNOTSUPP)),
}
}
pub fn to_canonical(name: &str) -> String {
let uppername = name.to_ascii_uppercase();
if uppername.starts_with("CAP_") {
uppername
} else {
["CAP_", &uppername].concat()
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use super::*;
#[test]
fn test_all_roundtrip() {
let all = Capabilities::all();
assert!(all.iter().count() > 0);
for c in all {
let c: Capability = c.try_into().unwrap();
let name = c.to_string();
let parsed: Capability = name.parse().unwrap();
assert_eq!(c, parsed);
}
}
#[test]
fn test_parse_invalid() {
let p1 = Capability::from_str("CAP_FOO");
let p1_err = p1.unwrap_err();
assert_eq!(p1_err.0, Errno::EINVAL);
let p2: Result<Capability, CapsError> = "CAP_BAR".parse();
assert!(p2.is_err());
}
#[test]
fn test_to_canonical() {
let p1 = "foo";
assert!(Capability::from_str(&to_canonical(p1)).is_err());
let p2 = "sys_admin";
assert!(Capability::from_str(&to_canonical(p2)).is_ok());
let p3 = "CAP_SYS_CHROOT";
assert!(Capability::from_str(&to_canonical(p3)).is_ok());
}
#[test]
fn test_to_canonical_1() {
assert_eq!(to_canonical("net_admin"), "CAP_NET_ADMIN");
}
#[test]
fn test_to_canonical_2() {
assert_eq!(to_canonical("CAP_NET_ADMIN"), "CAP_NET_ADMIN");
}
#[test]
fn test_to_canonical_3() {
assert_eq!(to_canonical("cap_sys_chroot"), "CAP_SYS_CHROOT");
}
#[test]
fn test_from_str_1() {
assert_eq!(
Capability::from_str("CAP_CHOWN").unwrap(),
Capability::CAP_CHOWN
);
}
#[test]
fn test_from_str_2() {
assert_eq!(
Capability::from_str("CAP_NET_RAW").unwrap(),
Capability::CAP_NET_RAW
);
}
#[test]
fn test_from_str_3() {
assert!(Capability::from_str("INVALID").is_err());
}
#[test]
fn test_display_1() {
assert_eq!(Capability::CAP_CHOWN.to_string(), "cap_chown");
}
#[test]
fn test_display_2() {
assert_eq!(Capability::CAP_NET_RAW.to_string(), "cap_net_raw");
}
#[test]
fn test_display_3() {
assert_eq!(Capability::CAP_SYS_ADMIN.to_string(), "cap_sys_admin");
}
#[test]
fn test_bitmask_chown_1() {
assert_eq!(Capability::CAP_CHOWN.bitmask(), 1u64 << 0);
}
#[test]
fn test_bitmask_dac_override_1() {
assert_eq!(Capability::CAP_DAC_OVERRIDE.bitmask(), 1u64 << 1);
}
#[test]
fn test_bitmask_kill_1() {
assert_eq!(Capability::CAP_KILL.bitmask(), 1u64 << 5);
}
#[test]
fn test_index_chown_1() {
assert_eq!(Capability::CAP_CHOWN.index(), 0u8);
}
#[test]
fn test_index_net_raw_1() {
assert_eq!(Capability::CAP_NET_RAW.index(), 13u8);
}
#[test]
fn test_index_sys_admin_1() {
assert_eq!(Capability::CAP_SYS_ADMIN.index(), 21u8);
}
#[test]
fn test_try_from_capabilities_1() {
let caps = Capabilities::CAP_CHOWN;
let cap: Capability = caps.try_into().unwrap();
assert_eq!(cap, Capability::CAP_CHOWN);
}
#[test]
fn test_try_from_capabilities_empty_1() {
let caps = Capabilities::empty();
let result: Result<Capability, _> = caps.try_into();
assert!(result.is_err());
}
#[test]
fn test_try_from_capabilities_multi_1() {
let caps = Capabilities::CAP_CHOWN | Capabilities::CAP_DAC_OVERRIDE;
let result: Result<Capability, _> = caps.try_into();
assert!(result.is_err());
}
#[test]
fn test_from_capability_into_capabilities_1() {
let caps: Capabilities = Capability::CAP_SYS_ADMIN.into();
assert!(caps.contains(Capabilities::CAP_SYS_ADMIN));
}
}