OXYGENHUB

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

26 of 26 lines run, 10 of 10 functions · run #29 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
7563×
fn write(path: &Path, bytes: &[u8], private: bool) -> std::io::Result<()> {
8563×
    let dir = path.parent().filter(|d| !d.as_os_str().is_empty()).unwrap_or(Path::new("."));
9563×
    std::fs::create_dir_all(dir)?;
10563×
    let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("file");
11563×
    let tmp = dir.join(format!(".{name}.{}.tmp", std::process::id()));
12563×
    let mut opts = std::fs::OpenOptions::new();
13563×
    opts.write(true).create(true).truncate(true);
14
    #[cfg(unix)]
15
    {
16
        use std::os::unix::fs::OpenOptionsExt;
17563×
        opts.mode(if private { 0o600 } else { 0o644 });
18
    }
19
    #[cfg(not(unix))]
20
    let _ = private;
21563×
    let mut f = opts.open(&tmp)?;
22563×
    f.write_all(bytes)?;
23563×
    f.sync_all()?;
24563×
    drop(f);
25563×
    std::fs::rename(&tmp, path)?;
26563×
    if let Ok(d) = std::fs::File::open(dir) {
27563×
        let _ = d.sync_all();
28563×
    }
29563×
    Ok(())
30563×
}
31
32376×
pub fn write_atomic(path: &Path, bytes: &[u8]) -> std::io::Result<()> {
33376×
    write(path, bytes, false)
34376×
}
35
36
/// As [`write_atomic`], readable by its owner only.
37187×
pub fn write_atomic_private(path: &Path, bytes: &[u8]) -> std::io::Result<()> {
38187×
    write(path, bytes, true)
39187×
}