OXYGENHUB

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

26 of 26 lines run, 10 of 10 functions · run #32 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
7632×
fn write(path: &Path, bytes: &[u8], private: bool) -> std::io::Result<()> {
8632×
    let dir = path.parent().filter(|d| !d.as_os_str().is_empty()).unwrap_or(Path::new("."));
9632×
    std::fs::create_dir_all(dir)?;
10632×
    let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("file");
11632×
    let tmp = dir.join(format!(".{name}.{}.tmp", std::process::id()));
12632×
    let mut opts = std::fs::OpenOptions::new();
13632×
    opts.write(true).create(true).truncate(true);
14
    #[cfg(unix)]
15
    {
16
        use std::os::unix::fs::OpenOptionsExt;
17632×
        opts.mode(if private { 0o600 } else { 0o644 });
18
    }
19
    #[cfg(not(unix))]
20
    let _ = private;
21632×
    let mut f = opts.open(&tmp)?;
22632×
    f.write_all(bytes)?;
23632×
    f.sync_all()?;
24632×
    drop(f);
25632×
    std::fs::rename(&tmp, path)?;
26632×
    if let Ok(d) = std::fs::File::open(dir) {
27632×
        let _ = d.sync_all();
28632×
    }
29632×
    Ok(())
30632×
}
31
32433×
pub fn write_atomic(path: &Path, bytes: &[u8]) -> std::io::Result<()> {
33433×
    write(path, bytes, false)
34433×
}
35
36
/// As [`write_atomic`], readable by its owner only.
37199×
pub fn write_atomic_private(path: &Path, bytes: &[u8]) -> std::io::Result<()> {
38199×
    write(path, bytes, true)
39199×
}