1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use std::{
ffi::CString,
path::{Path, PathBuf},
};
use crate::Process;
#[derive(Debug, Clone)]
pub(crate) enum DiskWritePolicy {
TempDir,
WriteDir(PathBuf),
}
type Hook = dyn FnOnce() -> nix::Result<()>;
#[must_use]
pub struct Command {
pub(crate) path: CString,
pub(crate) args: Vec<CString>,
pub(crate) layers: Vec<PathBuf>,
pub(crate) disk_write: DiskWritePolicy,
pub(crate) pre_pivot: Vec<Box<Hook>>,
pub(crate) pre_exec: Vec<Box<Hook>>,
}
impl Command {
pub fn new<P: AsRef<Path>>(root_fs: P, path: &str) -> Self {
let path = CString::new(path.as_bytes().to_vec()).expect("Nul byte in target path");
Self {
path: path.clone(),
args: vec![path],
layers: vec![root_fs.as_ref().to_owned()],
disk_write: DiskWritePolicy::TempDir,
pre_pivot: Vec::new(),
pre_exec: Vec::new(),
}
}
pub fn args(mut self, args: &[&str]) -> Self {
self.args =
std::iter::once(self.path.clone())
.chain(args.iter().map(|arg| {
CString::new(arg.as_bytes().to_vec()).expect("Nul byte in an argument")
}))
.collect();
self
}
pub fn layer<P: AsRef<Path>>(mut self, path: P) -> Self {
self.layers.push(path.as_ref().to_owned());
self
}
pub fn disk_write_tempdir(mut self) -> Self {
self.disk_write = DiskWritePolicy::TempDir;
self
}
pub fn disk_write_to<P: AsRef<Path>>(mut self, path: P) -> Self {
self.disk_write = DiskWritePolicy::WriteDir(path.as_ref().to_owned());
self
}
pub fn hook_pre_pivot(mut self, hook: Box<Hook>) -> Self {
self.pre_pivot.push(hook);
self
}
pub fn hook_pre_exec(mut self, hook: Box<Hook>) -> Self {
self.pre_exec.push(hook);
self
}
pub fn spawn(self) -> nix::Result<Process> {
Process::spawn(self)
}
}