diff options
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/fileutil.rs | 23 |
2 files changed, 20 insertions, 4 deletions
@@ -22,6 +22,7 @@ serde_derive = { version = "1.0" } serde_json = { version = "1.0" } chrono = { version = "0.4.10", default-features = false, features = ["std"] } toml = { version = "0.5.6", optional = true } +rand = { version = "0.7.3", default-features = false, features = ["std"] } [features] default = [ "toml" ] diff --git a/src/fileutil.rs b/src/fileutil.rs index 190a7d0..941eb08 100644 --- a/src/fileutil.rs +++ b/src/fileutil.rs @@ -2,7 +2,6 @@ // // Copyright 2019 Hristo Venev -use std::ffi::OsString; #[cfg(unix)] use std::os::unix::fs::OpenOptionsExt; use std::path::{Path, PathBuf}; @@ -56,6 +55,24 @@ impl Writer { }) } + pub fn new_in(path: &Path) -> io::Result<Self> { + use rand::RngCore; + let mut rng = rand::thread_rng(); + loop { + let i: u64 = rng.next_u64(); + let mut p: PathBuf = path.into(); + p.push(format!(".tmp.{:16x}", i)); + match Self::new(p) { + Ok(v) => return Ok(v), + Err(e) => { + if e.kind() != io::ErrorKind::AlreadyExists { + return Err(e); + } + } + } + } + } + #[inline] pub fn file(&mut self) -> &mut fs::File { &mut self.file @@ -74,9 +91,7 @@ impl Writer { } pub fn update(path: &Path, data: &[u8]) -> io::Result<()> { - let mut tmp = OsString::from(path); - tmp.push(".tmp"); - let mut tmp = Writer::new(PathBuf::from(tmp))?; + let mut tmp = Writer::new_in(path.parent().unwrap())?; io::Write::write_all(tmp.file(), data)?; tmp.sync_done()?.rename_to(path) } |