feat: enhance safety and crash resilience in file operations; add fsync to critical writes and checks for path traversal

This commit is contained in:
asepharyana
2026-07-12 11:49:33 +07:00
parent 8767beef39
commit 87d0aac596
9 changed files with 79 additions and 26 deletions
+10 -3
View File
@@ -78,17 +78,24 @@ impl Settings {
.unwrap_or_default()
}
/// Serialize and write settings to `<store_base_dir>/settings.json`.
/// Serialize and write settings to `<store_base_dir>/settings.json`,
/// using write-then-rename with fsync for crash safety.
///
/// Flow: ensure base dir exists → pretty-print JSON → write to disk.
/// Flow: ensure base dir exists → pretty-print JSON → write to a temp
/// file → sync to disk → rename over the real path → sync the directory.
///
/// Return: `Err` if the directory can't be created or the write fails.
pub fn save(&self) -> std::io::Result<()> {
let store = super::store::Store::new();
std::fs::create_dir_all(&store.base_dir)?;
let path = store.base_dir.join("settings.json");
let tmp = store.base_dir.join("settings.json.tmp");
let s = serde_json::to_string_pretty(self)?;
std::fs::write(path, s)?;
std::fs::write(&tmp, s)?;
let f = std::fs::File::open(&tmp)?;
f.sync_all()?;
std::fs::rename(&tmp, path)?;
let _ = std::fs::File::open(&store.base_dir).and_then(|d| d.sync_all());
Ok(())
}
}