1use std::fs;
2use std::io;
3use std::path::Path;
4
5pub fn atomic_write(path: &Path, content: &[u8]) -> io::Result<()> {
9 if let Some(parent) = path.parent() {
11 fs::create_dir_all(parent)?;
12 }
13
14 let tmp_path = path.with_extension(format!("purple_tmp.{}", std::process::id()));
15
16 #[cfg(unix)]
17 {
18 use std::io::Write;
19 use std::os::unix::fs::OpenOptionsExt;
20 let _ = fs::remove_file(&tmp_path);
22 let mut file = fs::OpenOptions::new()
23 .write(true)
24 .create_new(true)
25 .mode(0o600)
26 .open(&tmp_path)
27 .map_err(|e| {
28 io::Error::new(
29 e.kind(),
30 format!("Failed to create temp file {}: {}", tmp_path.display(), e),
31 )
32 })?;
33 file.write_all(content)?;
34 }
35
36 #[cfg(not(unix))]
37 fs::write(&tmp_path, content)?;
38
39 let result = fs::rename(&tmp_path, path);
40 if result.is_err() {
41 let _ = fs::remove_file(&tmp_path);
42 }
43 result
44}