implement tools::file_set_contents
This commit is contained in:
parent
652c11900d
commit
f12f8ff1a6
|
@ -4,6 +4,7 @@ use std::fs::{OpenOptions};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
//use std::sync::Arc;
|
//use std::sync::Arc;
|
||||||
|
use crate::tools;
|
||||||
use crate::api::schema::*;
|
use crate::api::schema::*;
|
||||||
|
|
||||||
use crate::section_config::*;
|
use crate::section_config::*;
|
||||||
|
@ -71,9 +72,7 @@ pub fn save_config(config: &SectionConfigData) -> Result<(), Error> {
|
||||||
|
|
||||||
//fixme: compute and compare digest
|
//fixme: compute and compare digest
|
||||||
|
|
||||||
//fixme: impl file_set_contents() (atomic write)
|
tools::file_set_contents(DATASTORE_CFG_FILENAME, raw.as_bytes(), None)?;
|
||||||
file.set_len(0)?;
|
|
||||||
file.write_all(raw.as_bytes())?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ pub mod static_map;
|
||||||
/// hierarchy of API entries, and provides ways to find an API
|
/// hierarchy of API entries, and provides ways to find an API
|
||||||
/// definition by path.
|
/// definition by path.
|
||||||
|
|
||||||
|
pub mod tools;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod api {
|
pub mod api {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
use failure::*;
|
||||||
|
use nix::unistd;
|
||||||
|
use nix::sys::stat;
|
||||||
|
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
pub fn file_set_contents<P: AsRef<Path>>(
|
||||||
|
path: P,
|
||||||
|
data: &[u8],
|
||||||
|
perm: Option<stat::Mode>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
|
||||||
|
let path = path.as_ref();
|
||||||
|
|
||||||
|
let mut template = path.to_owned();
|
||||||
|
template.set_extension("tmp_XXXXXX");
|
||||||
|
let (fd, tmp_path) = match unistd::mkstemp(&template) {
|
||||||
|
Ok((fd, path)) => (fd, path),
|
||||||
|
Err(err) => bail!("mkstemp {:?} failed: {}", template, err),
|
||||||
|
};
|
||||||
|
|
||||||
|
let tmp_path = tmp_path.as_path();
|
||||||
|
|
||||||
|
let mode : stat::Mode = stat::Mode::from(
|
||||||
|
stat::Mode::S_IRUSR | stat::Mode::S_IWUSR |
|
||||||
|
stat::Mode::S_IRGRP | stat::Mode::S_IROTH
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Err(err) = stat::fchmod(fd, mode) {
|
||||||
|
let _ = unistd::unlink(tmp_path);
|
||||||
|
bail!("fchmod {:?} failed: {}", tmp_path, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
use std::os::unix::io::FromRawFd;
|
||||||
|
let mut file = unsafe { File::from_raw_fd(fd) };
|
||||||
|
|
||||||
|
if let Err(err) = file.write_all(data) {
|
||||||
|
let _ = unistd::unlink(tmp_path);
|
||||||
|
bail!("write failed: {}", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(err) = std::fs::rename(tmp_path, path) {
|
||||||
|
let _ = unistd::unlink(tmp_path);
|
||||||
|
bail!("Atomic rename failed for file {:?} - {}", path, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue