| 98a0fb9f Andy McCall ↶ |
1 |
|
| 2 |
|
| 3 |
|
| 4 |
use std::io::Write; |
| 5 |
use std::path::Path; |
| 6 |
|
| 7 |
fn write(path: &Path, bytes: &[u8], private: bool) -> std::io::Result<()> { |
| 8 |
let dir = path.parent().filter(|d| !d.as_os_str().is_empty()).unwrap_or(Path::new(".")); |
| 9 |
std::fs::create_dir_all(dir)?; |
| 10 |
let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("file"); |
| 11 |
let tmp = dir.join(format!(".{name}.{}.tmp", std::process::id())); |
| 12 |
let mut opts = std::fs::OpenOptions::new(); |
| 13 |
opts.write(true).create(true).truncate(true); |
| 14 |
#[cfg(unix)] |
| 15 |
{ |
| 16 |
use std::os::unix::fs::OpenOptionsExt; |
| 17 |
opts.mode(if private { 0o600 } else { 0o644 }); |
| 18 |
} |
| 19 |
#[cfg(not(unix))] |
| 20 |
let _ = private; |
| 21 |
let mut f = opts.open(&tmp)?; |
| 22 |
f.write_all(bytes)?; |
| 23 |
f.sync_all()?; |
| 24 |
drop(f); |
| 25 |
std::fs::rename(&tmp, path)?; |
| 26 |
if let Ok(d) = std::fs::File::open(dir) { |
| 27 |
let _ = d.sync_all(); |
| 28 |
} |
| 29 |
Ok(()) |
| 30 |
} |
| 31 |
|
| 32 |
pub fn write_atomic(path: &Path, bytes: &[u8]) -> std::io::Result<()> { |
| 33 |
write(path, bytes, false) |
| 34 |
} |
| 35 |
|
| 36 |
|
| 37 |
pub fn write_atomic_private(path: &Path, bytes: &[u8]) -> std::io::Result<()> { |
| 38 |
write(path, bytes, true) |
| 39 |
} |