]> git.proxmox.com Git - proxmox-backup.git/blame - src/tools.rs
file_chunker: use Read trait
[proxmox-backup.git] / src / tools.rs
CommitLineData
f12f8ff1
DM
1use failure::*;
2use nix::unistd;
3use nix::sys::stat;
4
5use std::fs::File;
6use std::io::Write;
7use std::path::Path;
8
9pub fn file_set_contents<P: AsRef<Path>>(
10 path: P,
11 data: &[u8],
12 perm: Option<stat::Mode>,
13) -> Result<(), Error> {
14
15 let path = path.as_ref();
16
d64d80d2
DM
17 // Note: we use mkstemp heŕe, because this worka with different
18 // processes, threads, and even tokio tasks.
f12f8ff1
DM
19 let mut template = path.to_owned();
20 template.set_extension("tmp_XXXXXX");
21 let (fd, tmp_path) = match unistd::mkstemp(&template) {
22 Ok((fd, path)) => (fd, path),
23 Err(err) => bail!("mkstemp {:?} failed: {}", template, err),
24 };
25
26 let tmp_path = tmp_path.as_path();
27
1a7bc3dd 28 let mode : stat::Mode = perm.unwrap_or(stat::Mode::from(
f12f8ff1
DM
29 stat::Mode::S_IRUSR | stat::Mode::S_IWUSR |
30 stat::Mode::S_IRGRP | stat::Mode::S_IROTH
1a7bc3dd 31 ));
f12f8ff1
DM
32
33 if let Err(err) = stat::fchmod(fd, mode) {
34 let _ = unistd::unlink(tmp_path);
35 bail!("fchmod {:?} failed: {}", tmp_path, err);
36 }
37
38 use std::os::unix::io::FromRawFd;
39 let mut file = unsafe { File::from_raw_fd(fd) };
40
41 if let Err(err) = file.write_all(data) {
42 let _ = unistd::unlink(tmp_path);
43 bail!("write failed: {}", err);
44 }
45
46 if let Err(err) = std::fs::rename(tmp_path, path) {
47 let _ = unistd::unlink(tmp_path);
48 bail!("Atomic rename failed for file {:?} - {}", path, err);
49 }
50
51 Ok(())
52}