capo 0.0.1

Linux capabilities interface
Documentation
// Copyright (C) 2020 - Will Glozer. All rights reserved.

use std::os::raw::c_int;
use errno::errno;
use libc::{prctl, syscall};
use crate::Error;
use crate::ffi::{Data, Header};

#[derive(Copy, Clone, Debug)]
pub struct Cmd(c_int);

impl Cmd {
    pub const AMBIENT_RAISE:     Cmd = Self(libc::PR_CAP_AMBIENT_RAISE);
    pub const AMBIENT_LOWER:     Cmd = Self(libc::PR_CAP_AMBIENT_LOWER);
    pub const AMBIENT_IS_SET:    Cmd = Self(libc::PR_CAP_AMBIENT_IS_SET);
    pub const AMBIENT_CLEAR_ALL: Cmd = Self(libc::PR_CAP_AMBIENT_CLEAR_ALL);
    pub const BOUNDING_READ:     Cmd = Self(libc::PR_CAPBSET_READ);
    pub const BOUNDING_DROP:     Cmd = Self(libc::PR_CAPBSET_DROP);
}

pub fn ambient(cmd: Cmd, cap: impl Into<c_int>) -> Result<c_int, Error> {
    unsafe {
        match prctl(libc::PR_CAP_AMBIENT, cmd.0, cap.into(), 0, 0) {
            n @ 0..=1 => Ok(n),
            _         => Err(error()),
        }
    }
}

pub fn bounding(cmd: Cmd, cap: impl Into<c_int>) -> Result<c_int, Error> {
    unsafe {
        match prctl(cmd.0, cap.into(), 0, 0, 0) {
            n @ 0..=1 => Ok(n),
            _         => Err(error()),
        }
    }
}

pub fn capget(head: &Header, data: &mut [Data]) -> Result<(), Error> {
    unsafe {
        match syscall(libc::SYS_capget, head, data.as_mut_ptr()) {
            0 => Ok(()),
            _ => Err(error()),
        }
    }
}

pub fn capset(head: &Header, data: &[Data]) -> Result<(), Error> {
    unsafe {
        match syscall(libc::SYS_capset, head, data.as_ptr()) {
            0 => Ok(()),
            _ => Err(error()),
        }
    }
}

fn error() -> Error {
    Error::from(errno())
}