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 env_vars: Vec<(&'a str, &'a str)>,
22}
23
24impl<'a> BwrapCmd<'a> {
25 #[allow(dead_code)]
27 pub fn new_with_dir(path: &'a Dir) -> Self {
28 let fd_path: String = format!("/proc/self/fd/{}", path.as_raw_fd());
29 Self {
30 chroot_path: Cow::Owned(Utf8PathBuf::from(&fd_path)),
31 bind_mounts: Vec::new(),
32 env_vars: Vec::new(),
33 }
34 }
35
36 pub fn new(path: &'a Utf8Path) -> Self {
38 Self {
39 chroot_path: Cow::Borrowed(path),
40 bind_mounts: Vec::new(),
41 env_vars: Vec::new(),
42 }
43 }
44
45 pub fn bind(
47 mut self,
48 source: &'a impl AsRef<Utf8Path>,
49 target: &'a impl AsRef<Utf8Path>,
50 ) -> Self {
51 self.bind_mounts
52 .push((source.as_ref().as_str(), target.as_ref().as_str()));
53 self
54 }
55
56 pub fn setenv(mut self, key: &'a str, value: &'a str) -> Self {
58 self.env_vars.push((key, value));
59 self
60 }
61
62 pub fn set_default_path(self) -> Self {
68 self.setenv(
69 "PATH",
70 "/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin",
71 )
72 }
73
74 fn build_command<S: AsRef<OsStr>>(&self, args: impl IntoIterator<Item = S>) -> Command {
76 let mut cmd = Command::new("bwrap");
77
78 cmd.args(["--bind", self.chroot_path.as_str(), "/"]);
80
81 cmd.args(["--proc", "/proc"]);
84 cmd.args(["--dev-bind", "/dev", "/dev"]);
85 cmd.args(["--bind", "/sys", "/sys"]);
86
87 cmd.args(["--tmpfs", "/run"]);
91 cmd.args(["--bind", "/run", "/run"]);
92
93 for (source, target) in &self.bind_mounts {
95 cmd.args(["--bind", source, target]);
96 }
97
98 for (key, value) in &self.env_vars {
100 cmd.args(["--setenv", key, value]);
101 }
102
103 cmd.arg("--");
105 cmd.args(args);
106
107 cmd
108 }
109
110 pub fn run<S: AsRef<OsStr>>(self, args: impl IntoIterator<Item = S>) -> Result<()> {
112 self.build_command(args)
113 .log_debug()
114 .run_inherited_with_cmd_context()
115 }
116
117 pub fn run_get_string<S: AsRef<OsStr>>(
119 self,
120 args: impl IntoIterator<Item = S>,
121 ) -> Result<String> {
122 self.build_command(args).log_debug().run_get_string()
123 }
124}