diff --git a/cli/disk_cache.rs b/cli/disk_cache.rs index 233990903b..81b86c0ae7 100644 --- a/cli/disk_cache.rs +++ b/cli/disk_cache.rs @@ -139,7 +139,7 @@ impl DiskCache { Some(ref parent) => self.ensure_dir_exists(parent), None => Ok(()), }?; - fs_util::write_file(&path, data, crate::http_cache::CACHE_PERM) + fs_util::atomic_write_file(&path, data, crate::http_cache::CACHE_PERM) .map_err(|e| with_io_context(&e, format!("{:#?}", &path))) } } diff --git a/cli/fs_util.rs b/cli/fs_util.rs index 217476c012..f13558e36e 100644 --- a/cli/fs_util.rs +++ b/cli/fs_util.rs @@ -2,12 +2,28 @@ use deno_core::error::AnyError; pub use deno_core::normalize_path; +use deno_runtime::deno_crypto::rand; use std::env::current_dir; use std::fs::OpenOptions; use std::io::{Error, Write}; use std::path::{Path, PathBuf}; use walkdir::WalkDir; +pub fn atomic_write_file>( + filename: &Path, + data: T, + mode: u32, +) -> std::io::Result<()> { + let rand: String = (0..4) + .map(|_| format!("{:02x}", rand::random::())) + .collect(); + let extension = format!("{}.tmp", rand); + let tmp_file = filename.with_extension(extension); + write_file(&tmp_file, data, mode)?; + std::fs::rename(tmp_file, filename)?; + Ok(()) +} + pub fn write_file>( filename: &Path, data: T, diff --git a/cli/http_cache.rs b/cli/http_cache.rs index dd5f4dc3fd..4677b44c9f 100644 --- a/cli/http_cache.rs +++ b/cli/http_cache.rs @@ -87,7 +87,7 @@ impl Metadata { pub fn write(&self, cache_filename: &Path) -> Result<(), AnyError> { let metadata_filename = Self::filename(cache_filename); let json = serde_json::to_string_pretty(self)?; - fs_util::write_file(&metadata_filename, json, CACHE_PERM)?; + fs_util::atomic_write_file(&metadata_filename, json, CACHE_PERM)?; Ok(()) } @@ -161,7 +161,7 @@ impl HttpCache { .expect("Cache filename should have a parent dir"); self.ensure_dir_exists(parent_filename)?; // Cache content - fs_util::write_file(&cache_filename, content, CACHE_PERM)?; + fs_util::atomic_write_file(&cache_filename, content, CACHE_PERM)?; let metadata = Metadata { url: url.to_string(),