feat: enhance safety and crash resilience in file operations; add fsync to critical writes and checks for path traversal
This commit is contained in:
+10
-3
@@ -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(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user