OXYGENHUB

Coverage / crates/spectra-core/src/durable.rs 100.0%

26 of 26 lines run, 10 of 10 functions · run #34 on main · run missed

1
//! Writing files so a crash leaves the old content or the new, never half:
2
//! a temporary file in the same directory, flushed, then renamed over.
3
4
use std::io::Write;
5
use std::path::Path;
6
7639×
fn write(path: &Path, bytes: &[u8], private: bool) -> std::io::Result<()> {
8639×
    let dir = path.parent().filter(|d| !d.as_os_str().is_empty()).unwrap_or(Path::new("."));
9639×
    std::fs::create_dir_all(dir)?;
10639×
    let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("file");
11639×
    let tmp = dir.join(format!(".{name}.{}.tmp", std::process::id()));
12639×
    let mut opts = std::fs::OpenOptions::new();
13639×
    opts.write(true).create(true).truncate(true);
14
    #[cfg(unix)]
15
    {
16
        use std::os::unix::fs::OpenOptionsExt;
17639×
        opts.mode(if private { 0o600 } else { 0o644 });
18
    }
19
    #[cfg(not(unix))]
20
    let _ = private;
21639×
    let mut f = opts.open(&tmp)?;
22639×
    f.write_all(bytes)?;
23639×
    f.sync_all()?;
24639×
    drop(f);
25639×
    std::fs::rename(&tmp, path)?;
26639×
    if let Ok(d) = std::fs::File::open(dir) {
27639×
        let _ = d.sync_all();
28639×
    }
29639×
    Ok(())
30639×
}
31
32439×
pub fn write_atomic(path: &Path, bytes: &[u8]) -> std::io::Result<()> {
33439×
    write(path, bytes, false)
34439×
}
35
36
/// As [`write_atomic`], readable by its owner only.
37200×
pub fn write_atomic_private(path: &Path, bytes: &[u8]) -> std::io::Result<()> {
38200×
    write(path, bytes, true)
39200×
}