use std::ffi::OsString;
use std::io::{self, Write as _};
use std::path::Path;
pub fn replace_private(path: &Path, bytes: &[u8]) -> io::Result<()> {
let parent = path
.parent()
.ok_or_else(|| io::Error::other(format!("{} has no parent", path.display())))?;
let mut temporary = tempfile::Builder::new()
.prefix(&temporary_prefix(path))
.suffix(".tmp")
.tempfile_in(parent)?;
temporary.write_all(bytes)?;
temporary.as_file().sync_all()?;
temporary.persist(path).map_err(|error| error.error)?;
sync_directory(parent)
}
const MAX_NAMED: usize = 200;
pub fn temporary_prefix(path: &Path) -> OsString {
let mut prefix = OsString::from(".");
match path.file_name() {
Some(name) if name.len() <= MAX_NAMED => prefix.push(name),
_ => prefix.push("tmp"),
}
prefix.push(".");
prefix
}
pub fn sync_directory(directory: &Path) -> io::Result<()> {
#[cfg(unix)]
std::fs::File::open(directory)?.sync_all()?;
#[cfg(not(unix))]
let _ = directory;
Ok(())
}
#[cfg(test)]
mod tests;