>(buf: &Path, parts: Vec) -> PathBuf {
152 | let mut buf = buf.to_path_buf();
153 | for part in parts {
154 | let path = part.as_ref();
155 | let path = if path.starts_with("/") {
156 | path.strip_prefix("/").unwrap()
157 | } else {
158 | path
159 | };
160 |
161 | buf.push(path);
162 | }
163 | buf
164 | }
165 |
166 | #[cfg(test)]
167 | mod tests {
168 | use super::*;
169 |
170 | use color_eyre::Result;
171 |
172 | #[test]
173 | fn test_append_all() {
174 | let buf = PathBuf::from("/tmp");
175 | let parts = vec!["foo", "bar", "baz"];
176 | let expected = PathBuf::from("/tmp/foo/bar/baz");
177 | assert_eq!(append_all(&buf, parts), expected);
178 | }
179 |
180 | #[test]
181 | fn test_fs_driver_creates_and_destroys_roots() -> Result<()> {
182 | let driver = FsDriver::new();
183 | let name = "test-create-destroy-root";
184 | let root = driver.container_root(name);
185 | driver.setup_root(name)?;
186 | assert!(root.exists());
187 | driver.cleanup_root(name)?;
188 | assert!(!root.exists());
189 |
190 | Ok(())
191 | }
192 |
193 | #[test]
194 | fn test_fs_driver_touches_files() -> Result<()> {
195 | let driver = FsDriver::new();
196 | let name = "test-touch-file";
197 | let root = driver.container_root(name);
198 | driver.setup_root(name)?;
199 | let file = append_all(&root, vec!["foo"]);
200 | driver.touch(&file)?;
201 | assert!(file.exists());
202 | driver.cleanup_root(name)?;
203 | assert!(!root.exists());
204 |
205 | Ok(())
206 | }
207 |
208 | #[test]
209 | fn test_fs_driver_touches_dirs() -> Result<()> {
210 | let driver = FsDriver::new();
211 | let name = "test-touch-dir";
212 | let root = driver.container_root(name);
213 | driver.setup_root(name)?;
214 | let dir = append_all(&root, vec!["foo"]);
215 | driver.touch_dir(&dir)?;
216 | assert!(dir.exists());
217 | driver.cleanup_root(name)?;
218 | assert!(!root.exists());
219 |
220 | Ok(())
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/src/enclosure/linux.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashMap;
2 | use std::process::Command;
3 |
4 | use color_eyre::Result;
5 | use log::*;
6 | use nix::unistd::{Gid, Uid};
7 | use regex::Regex;
8 |
9 | pub fn map_uids>(pid: I, uids: &mut HashMap) -> Result<()> {
10 | let pid = pid.into();
11 | let mut args = vec![pid.to_string()];
12 | for (old_uid, new_uid) in uids.iter() {
13 | args.push(old_uid.to_string());
14 | args.push(new_uid.to_string());
15 | args.push("1".to_string());
16 | }
17 |
18 | let newuidmap = Command::new("newuidmap").args(args).output();
19 |
20 | if newuidmap.is_err() {
21 | return newuidmap.map(|_| ()).map_err(|e| e.into());
22 | }
23 |
24 | let newuidmap = newuidmap?;
25 | let stderr = String::from_utf8(newuidmap.stderr)?;
26 | if let Some(bad_uid) = check_mapping_regex(r"newuidmap: uid range \[(\d+)-.*", &stderr)? {
27 | // Remove bad uid, continue to call newuidmap until it works
28 | uids.remove(&Uid::from_raw(bad_uid));
29 | return map_uids(pid, uids);
30 | }
31 |
32 | debug!("mapped uids {:#?}", uids);
33 |
34 | Ok(())
35 | }
36 |
37 | pub fn map_gids>(pid: I, gids: &mut HashMap) -> Result<()> {
38 | let pid = pid.into();
39 | let mut args = vec![pid.to_string()];
40 | for (old_gid, new_gid) in gids.iter() {
41 | args.push(old_gid.to_string());
42 | args.push(new_gid.to_string());
43 | args.push("1".to_string());
44 | }
45 |
46 | let newgidmap = Command::new("newgidmap").args(args).output();
47 |
48 | if newgidmap.is_err() {
49 | return newgidmap.map(|_| ()).map_err(|e| e.into());
50 | }
51 |
52 | let newgidmap = newgidmap?;
53 | let stderr = String::from_utf8(newgidmap.stderr)?;
54 | if let Some(bad_gid) = check_mapping_regex(r"newgidmap: gid range \[(\d+)-.*", &stderr)? {
55 | // Remove bad gid, continue to call newgidmap until it works
56 | gids.remove(&Gid::from_raw(bad_gid));
57 | return map_gids(pid, gids);
58 | }
59 |
60 | debug!("mapped gids {:#?}", gids);
61 |
62 | Ok(())
63 | }
64 |
65 | fn check_mapping_regex(regex: &str, stderr: &str) -> Result