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
|
use std::{
fs, io,
path::{Path, PathBuf},
};
use nix::mount::{self, MsFlags};
use crate::util::error::*;
pub fn open<P: AsRef<Path>>(path: P) -> Result<fs::File> {
fs::File::open(path.as_ref())
.with_context(|| format!("Failed to open file {:?} for reading", path.as_ref()))
}
pub fn create<P: AsRef<Path>>(path: P) -> Result<fs::File> {
fs::File::create(path.as_ref())
.with_context(|| format!("Failed to open file {:?} for writing", path.as_ref()))
}
pub fn rename<P1: AsRef<Path>, P2: AsRef<Path>>(from: P1, to: P2) -> Result<()> {
fs::rename(from.as_ref(), to.as_ref())
.with_context(|| format!("Failed to rename {:?} to {:?}", from.as_ref(), to.as_ref()))
}
// Unlike fs::copy, this doesn't preserve file flags
pub fn copy<P1: AsRef<Path>, P2: AsRef<Path>>(from: P1, to: P2) -> Result<()> {
(|| -> Result<()> {
let mut src = open(from.as_ref())?;
let mut dest = create(to.as_ref())?;
io::copy(&mut src, &mut dest)?;
dest.sync_all()?;
Ok(())
})()
.with_context(|| format!("Failed to copy {:?} to {:?}", from.as_ref(), to.as_ref()))
}
pub fn mkdir<P: AsRef<Path>>(path: P) -> Result<()> {
let mut builder = fs::DirBuilder::new();
builder.recursive(true);
builder
.create(path.as_ref())
.with_context(|| format!("Failed to create directory {:?}", path.as_ref()))
}
pub fn ensure_removed<P: AsRef<Path>>(path: P) -> Result<()> {
rm_rf::ensure_removed(path.as_ref())
.map_err(Error::new)
.with_context(|| format!("Failed to delete directory {:?}", path.as_ref()))
}
pub fn is_dir_empty<P: AsRef<Path>>(path: P) -> Result<bool> {
Ok(fs::read_dir(path)?.next().is_none())
}
#[must_use]
pub struct Mount(PathBuf);
impl Drop for Mount {
fn drop(&mut self) {
mount::umount(&self.0)
.with_context(|| format!("Failed to unmount {:?}", self.0))
.unwrap();
}
}
pub fn mount<P1: AsRef<Path>, P2: AsRef<Path>>(
source: P1,
target: P2,
fstype: &str,
flags: MsFlags,
data: Option<&str>,
) -> Result<Mount> {
mkdir(target.as_ref()).with_context(|| format!("Failed to create {:?}", target.as_ref()))?;
let canon_target = target
.as_ref()
.canonicalize()
.with_context(|| format!("Failed to get absolute path for {:?}", target.as_ref()))?;
mount::mount(
Some(source.as_ref()),
&canon_target,
Some(fstype),
flags,
data,
)
.with_context(|| format!("Failed to mount {:?}", canon_target))?;
Ok(Mount(canon_target))
}
|