OXYGENHUB

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

26 of 26 lines run, 10 of 10 functions · run #33 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
7666×
fn write(path: &Path, bytes: &[u8], private: bool) -> std::io::Result<()> {
8666×
    let dir = path.parent().filter(|d| !d.as_os_str().is_empty()).unwrap_or(Path::new("."));
9666×
    std::fs::create_dir_all(dir)?;
10666×
    let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("file");
11666×
    let tmp = dir.join(format!(".{name}.{}.tmp", std::process::id()));
12666×
    let mut opts = std::fs::OpenOptions::new();
13666×
    opts.write(true).create(true).truncate(true);
14
    #[cfg(unix)]
15
    {
16
        use std::os::unix::fs::OpenOptionsExt;
17666×
        opts.mode(if private { 0o600 } else { 0o644 });
18
    }
19
    #[cfg(not(unix))]
20
    let _ = private;
21666×
    let mut f = opts.open(&tmp)?;
22666×
    f.write_all(bytes)?;
23666×
    f.sync_all()?;
24666×
    drop(f);
25666×
    std::fs::rename(&tmp, path)?;
26666×
    if let Ok(d) = std::fs::File::open(dir) {
27666×
        let _ = d.sync_all();
28666×
    }
29666×
    Ok(())
30666×
}
31
32458×
pub fn write_atomic(path: &Path, bytes: &[u8]) -> std::io::Result<()> {
33458×
    write(path, bytes, false)
34458×
}
35
36
/// As [`write_atomic`], readable by its owner only.
37208×
pub fn write_atomic_private(path: &Path, bytes: &[u8]) -> std::io::Result<()> {
38208×
    write(path, bytes, true)
39208×
}