From 21d666465fda16e0c9cc54bbbd8b6f8121c3bac1 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Thu, 22 Oct 2026 20:34:42 +0200 Subject: [PATCH] Remove all leftover temp files at server startup Fixes #1129 Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- apps/figcraft-server/src/store.rs | 13 ++++++++++++- apps/figcraft-server/src/store_tests.rs | 26 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/apps/figcraft-server/src/store.rs b/apps/figcraft-server/src/store.rs index ea9bc626..8c6226a5 100644 --- a/apps/figcraft-server/src/store.rs +++ b/apps/figcraft-server/src/store.rs @@ -344,6 +344,9 @@ impl Store { /// [`open`](Self::open), or `None` when someone else holds the directory. pub fn try_open(root: &Path, cfg: StoreConfig) -> Result, String> { let Some(lock) = lock(root)? else { return Ok(None) }; + for name in [KEY, BLOCKED, REPORTS] { + let _ = fs::remove_file(disk::temp_of(&root.join(name))); + } let key = load_key(root)?; let dir = root.join(FILES); fs::create_dir_all(&dir).map_err(|e| format!("can't create {}: {e}", dir.display()))?; @@ -425,12 +428,20 @@ impl Store { /// A file folder's description and links, after checking its snapshot and log. Leftover /// temporary files (writes cut short) are removed. fn check(&self, path: &Path) -> Result { - for name in [SNAPSHOT, LOG, META, LINKS] { + for name in [SNAPSHOT, LOG, META, LINKS, USAGE] { let tmp = disk::temp_of(&path.join(name)); if tmp.exists() { let _ = fs::remove_file(&tmp); } } + if let Ok(entries) = fs::read_dir(path) { + for e in entries.flatten() { + let name = e.file_name().to_string_lossy().into_owned(); + if name.starts_with("library-") && name.ends_with(".bin.tmp") { + let _ = fs::remove_file(e.path()); + } + } + } let meta: Meta = serde_json::from_slice(&disk::read_capped(&path.join(META), 1 << 20)?).map_err(|e| format!("{META} is damaged ({e})"))?; let links: Vec = serde_json::from_slice(&disk::read_capped(&path.join(LINKS), 16 << 20)?).map_err(|e| format!("{LINKS} is damaged ({e})"))?; diff --git a/apps/figcraft-server/src/store_tests.rs b/apps/figcraft-server/src/store_tests.rs index f380568c..6625a0dd 100644 --- a/apps/figcraft-server/src/store_tests.rs +++ b/apps/figcraft-server/src/store_tests.rs @@ -313,3 +313,29 @@ fn edits_confirmed_after_a_compaction_cut_short_survive_a_restart() { let name = page_name(&restored); assert!(at(&name) >= at(&confirmed), "restored {name:?}, confirmed {confirmed:?}"); } + +#[test] +fn every_leftover_temporary_file_is_removed_at_startup() { + let dir = TempDir::new("leftovers"); + let id = { + let mut store = Store::open(dir.path(), cfg(dir.path())).unwrap(); + let id = publish(&mut store, "A").0; + store.flush(); + id + }; + let folder = dir.path().join(FILES).join(&id); + let leftovers = [ + dir.path().join("blocked.json.tmp"), + dir.path().join("reports.json.tmp"), + dir.path().join("server.key.tmp"), + folder.join("usage.json.tmp"), + folder.join("library-1.bin.tmp"), + ]; + for path in &leftovers { + fs::write(path, b"half").unwrap(); + } + let _store = Store::open(dir.path(), cfg(dir.path())).unwrap(); + for path in &leftovers { + assert!(!path.exists(), "leftover not cleaned at startup: {}", path.display()); + } +}