From ba112d49ffe01f4452645b0083aab1f8dd8fdeb1 Mon Sep 17 00:00:00 2001 From: Hristo Venev Date: Sun, 9 Feb 2020 00:36:43 +0000 Subject: Generate random temporary file names. --- Cargo.toml | 1 + src/fileutil.rs | 23 +++++++++++++++++++---- 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 { + 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) } -- cgit