aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml1
-rw-r--r--src/fileutil.rs23
2 files changed, 20 insertions, 4 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 4d76d31..8c91e39 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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)
}