bootc_internal_utils/
bwrap.rs1use std::borrow::Cow;
3use std::ffi::OsStr;
4use std::os::fd::AsRawFd;
5use std::process::Command;
6
7use anyhow::Result;
8use cap_std_ext::camino::{Utf8Path, Utf8PathBuf};
9use cap_std_ext::cap_std::fs::Dir;
10
11use crate::CommandRunExt;
12
13#[derive(Debug)]
15pub struct BwrapCmd<'a> {
16 chroot_path: Cow<'a, Utf8Path>,
18 bind_mounts: Vec<(&'a str, &'a str)>,
20 devices: Vec<&'a str>,
22 env_vars: Vec<(&'a str, &'a str)>,
24}
25
26impl<'a> BwrapCmd<'a> {
27 #[allow(dead_code)]
29 pub fn new_with_dir(path: &'a Dir) -> Self {
30 let fd_path: String = format!("/proc/self/fd/{}", path.as_raw_fd());
31 Self {
32 chroot_path: Cow::Owned(Utf8PathBuf::from(&fd_path)),
33 bind_mounts: Vec::new(),
34 devices: Vec::new(),
35 env_vars: Vec::new(),
36 }
37 }
38
39 pub fn new(path: &'a Utf8Path) -> Self {
41 Self {
42 chroot_path: Cow::Borrowed(path),
43 bind_mounts: Vec::new(),
44 devices: Vec::new(),
45 env_vars: Vec::new(),
46 }
47 }
48
49 pub fn bind(
51 mut self,
52 source: &'a impl AsRef<Utf8Path>,
53 target: &'a impl AsRef<Utf8Path>,
54 ) -> Self {
55 self.bind_mounts
56 .push((source.as_ref().as_str(), target.as_ref().as_str()));
57 self
58 }
59
60 pub fn bind_device(mut self, device: &'a str) -> Self {
62 self.devices.push(device);
63 self
64 }
65
66 pub fn setenv(mut self, key: &'a str, value: &'a str) -> Self {
68 self.env_vars.push((key, value));
69 self
70 }
71
72 pub fn run<S: AsRef<OsStr>>(self, args: impl IntoIterator<Item = S>) -> Result<()> {
74 let mut cmd = Command::new("bwrap");
75
76 cmd.args(["--bind", self.chroot_path.as_str(), "/"]);
78
79 cmd.args(["--proc", "/proc"]);
82 cmd.args(["--dev", "/dev"]);
83 cmd.args(["--bind", "/sys", "/sys"]);
84
85 for (source, target) in &self.bind_mounts {
87 cmd.args(["--bind", source, target]);
88 }
89
90 for device in self.devices {
92 cmd.args(["--dev-bind", device, device]);
93 }
94
95 for (key, value) in &self.env_vars {
97 cmd.args(["--setenv", key, value]);
98 }
99
100 cmd.arg("--");
102 cmd.args(args);
103
104 cmd.log_debug().run_inherited_with_cmd_context()
105 }
106}