fedimint_portalloc/
util.rs

1use std::fs;
2use std::io::{self, Write};
3use std::path::Path;
4
5use serde::Serialize;
6use tracing::debug;
7
8pub fn open_lock_file(root_path: &Path) -> anyhow::Result<fs::File> {
9    let path = root_path.join("lock");
10    debug!(path = %path.display(), "Opening lock file...");
11    let file = fs::OpenOptions::new()
12        .create(true)
13        .append(true)
14        .read(true)
15        .open(path.clone())?;
16    debug!(path = %path.display(), "Opened lock file");
17    Ok(file)
18}
19
20pub fn store_json_pretty_to_file<T>(path: &Path, val: &T) -> anyhow::Result<()>
21where
22    T: Serialize,
23{
24    Ok(store_to_file_with(path, |f| {
25        serde_json::to_writer_pretty(f, val).map_err(Into::into)
26    })
27    .and_then(|res| res)?)
28}
29
30fn store_to_file_with<E, F>(path: &Path, f: F) -> io::Result<Result<(), E>>
31where
32    F: Fn(&mut dyn io::Write) -> Result<(), E>,
33{
34    std::fs::create_dir_all(path.parent().expect("Not a root path"))?;
35    let tmp_path = path.with_extension("tmp");
36    let mut file = std::fs::OpenOptions::new()
37        .create(true)
38        .truncate(true)
39        .write(true)
40        .open(&tmp_path)?;
41    if let Err(e) = f(&mut file) {
42        return Ok(Err(e));
43    }
44    file.flush()?;
45    file.sync_data()?;
46    drop(file);
47    std::fs::rename(tmp_path, path)?;
48    Ok(Ok(()))
49}