use crate::global::IDMapItem;
use crate::LogCommand;
use anyhow::Result as AResult;
use os_pipe::PipeReader;
use polling::{Event, Events, Poller};
use serde::Deserialize;
use std::io::Read;
use std::os::fd::AsRawFd;
use std::process::Command;
#[allow(dead_code)]
#[derive(Deserialize, Debug)]
pub(super) struct BWInfo {
#[serde(rename = "child-pid")]
pub child_pid: u64,
#[serde(rename = "cgroup-namespace")]
pub cgroup_namespace: Option<u64>,
#[serde(rename = "ipc-namespace")]
pub ipc_namespace: Option<u64>,
#[serde(rename = "mnt-namespace")]
pub mnt_namespace: Option<u64>,
#[serde(rename = "pid-namespace")]
pub pid_namespace: Option<u64>,
#[serde(rename = "uts-namespace")]
pub uts_namespace: Option<u64>,
}
impl BWInfo {
pub(super) fn acquire(pipe: &mut PipeReader) -> AResult<Self> {
let mut part = [0u8; 512];
let mut full: Vec<u8> = Vec::new();
let fd = pipe.as_raw_fd();
let poller = Poller::new()?;
let mut events = Events::new();
unsafe {
poller.add(fd, Event::readable(1))?;
}
loop {
events.clear();
poller.wait(&mut events, None)?;
let size = pipe.read(&mut part)?;
let mut seg = part[..size].to_vec();
full.append(&mut seg);
if size >= 2 && &part[(size - 2)..size] == b"}\n" {
break;
} else {
poller.modify(&pipe, Event::readable(1))?;
}
}
Ok(serde_json::from_str(std::str::from_utf8(&full)?)?)
}
pub(super) fn map_ids(&self, uidmaps: &[IDMapItem], gidmaps: &[IDMapItem]) -> AResult<()> {
let pid = self.child_pid;
let mut newuidmap = Command::new("newuidmap");
newuidmap.arg(pid.to_string());
for (upper, lower, count) in uidmaps {
newuidmap.arg(upper.to_string());
newuidmap.arg(lower.to_string());
newuidmap.arg(count.to_string());
}
newuidmap.log("UID Mapping");
if !newuidmap.status()?.success() {
const NUMERR: &str = "Failed to set UID map";
log::error!("{NUMERR}");
anyhow::bail!(NUMERR);
}
let mut newgidmap = Command::new("newgidmap");
newgidmap.arg(pid.to_string());
for (upper, lower, count) in gidmaps {
newgidmap.arg(upper.to_string());
newgidmap.arg(lower.to_string());
newgidmap.arg(count.to_string());
}
newgidmap.log("GID Mapping");
if !newgidmap.status()?.success() {
const NGMERR: &str = "Failed to set GID map";
log::error!("{NGMERR}");
anyhow::bail!(NGMERR);
}
Ok(())
}
}