aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeonard Kugis <leonard@kug.is>2026-08-02 19:06:18 +0200
committerLeonard Kugis <leonard@kug.is>2026-08-02 19:06:18 +0200
commit910037ffaf252aae4e718f32a7812b22c8449995 (patch)
tree1194feaa1b8fb0d91edda2f721e628586f13c0df
parent3b34a2be2aab19ff4ed80cb58b956c6db5725e20 (diff)
downloadsquashr-910037ffaf252aae4e718f32a7812b22c8449995.tar.gz
Fixed snapshot mergefix_merge
-rw-r--r--[-rwxr-xr-x]src/main.rs38
1 files changed, 25 insertions, 13 deletions
diff --git a/src/main.rs b/src/main.rs
index 6f9239a..847e4a4 100755..100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -571,7 +571,7 @@ fn parse_hdr_chksum_octal(field: &[u8]) -> Option<u32> {
}
fn is_valid_tar_header(h: &[u8; 512]) -> bool {
- if is_zero_block(h) { return true; }
+ if is_zero_block(h) { return false; }
match parse_hdr_chksum_octal(&h[148..156]) {
Some(want) => tar_checksum(h) == want,
None => false,
@@ -1122,11 +1122,13 @@ fn cmd_backup(ctx:&mut Ctx)->Result<()>{
out
};
+ // Ensure tar.snapshot is always saved – also when tar did not run (no_changes).
+ // In the no_changes case we materialize the file from meta, which was already
+ // done by ensure_tar_snapshot_materialized() at the top, so it's up-to-date.
+
let staging = ctx.temp_path("meta.staging");
extract_all_meta_to(ctx, &staging)?;
- // neues Manifest hinein
save_manifest_to_dir(&staging, next_idx, &manifest_now)?;
- // aktualisierte tar.snapshot hinein (falls vorhanden)
if ctx.tar_snapshot.exists() {
let dst = staging.join("tar.snapshot");
if dst.exists() { let _ = fs::remove_file(&dst); }
@@ -1134,6 +1136,8 @@ fn cmd_backup(ctx:&mut Ctx)->Result<()>{
}
rebuild_meta_from_staging(ctx, &staging)?;
let _ = fs::remove_dir_all(&staging);
+ // Clean up tar.snapshot in work_dir after it was saved to meta
+ let _ = fs::remove_file(&ctx.tar_snapshot);
if tar_warn {
eprintln!("[warn] Snapshot {:04} created, but tar reported non-zero exit. Some files may be missing or changed during read.", next_idx);
@@ -1707,12 +1711,12 @@ fn merge_first_two(ctx:&mut Ctx)->Result<()>{
fs::create_dir_all(&upper)?;
fs::create_dir_all(&work)?;
fs::create_dir_all(&view)?;
- let loweropt = format!("{}:{}", abspath(&m1).display(), abspath(&m2).display());
+ let loweropt = format!("{}:{}", abspath(&m2).display(), abspath(&m1).display());
mount_overlay(&loweropt, &upper, &work, &view)?;
- let present = load_manifest(ctx, idx2).unwrap_or_default();
- let past = load_manifest(ctx, idx1).unwrap_or_default();
- let deletes: Vec<String> = past.difference(&present).cloned().collect();
+ let older = load_manifest(ctx, idx1).unwrap_or_default();
+ let newer = load_manifest(ctx, idx2).unwrap_or_default();
+ let deletes: Vec<String> = older.difference(&newer).cloned().collect();
if !deletes.is_empty() {
apply_whiteouts_via_unlink(&abspath(&view), &deletes)?;
}
@@ -1729,6 +1733,15 @@ fn merge_first_two(ctx:&mut Ctx)->Result<()>{
let _ = umount(&view);
let _ = umount(&m2);
let _ = umount(&m1);
+ // Close LUKS mappers for the merged snapshots
+ close_mount_mapper_best_effort(s1);
+ close_mount_mapper_best_effort(s2);
+ // Clean up merge temporary directories
+ let _ = fs::remove_dir_all(&upper);
+ let _ = fs::remove_dir_all(&work);
+ let _ = fs::remove_dir_all(&view);
+ let _ = fs::remove_dir_all(&m1);
+ let _ = fs::remove_dir_all(&m2);
let is_luks = s1.extension().and_then(|e| e.to_str()).unwrap_or("") == "luks";
let out_path = ctx.snapshot_path(idx1, is_luks);
@@ -1753,11 +1766,11 @@ fn merge_first_two(ctx:&mut Ctx)->Result<()>{
let staging = ctx.temp_path("meta.staging");
extract_all_meta_to(ctx, &staging)?;
- let m1p = staging.join(Ctx::manifest_name(1));
- let m2p = staging.join(Ctx::manifest_name(2));
- if m1p.exists(){ let _ = fs::remove_file(&m1p); }
- if m2p.exists(){ fs::rename(&m2p, &m1p).ok(); }
- let mut k = 3usize;
+ let m_older = staging.join(Ctx::manifest_name(idx1));
+ let m_newer = staging.join(Ctx::manifest_name(idx2));
+ if m_older.exists(){ let _ = fs::remove_file(&m_older); }
+ if m_newer.exists(){ fs::rename(&m_newer, &m_older).ok(); }
+ let mut k = idx2 + 1;
loop {
let from = staging.join(Ctx::manifest_name(k));
if !from.exists() { break; }
@@ -1772,4 +1785,3 @@ fn merge_first_two(ctx:&mut Ctx)->Result<()>{
println!("Merged snapshots {:04} + {:04} → {:04}.", idx1, idx2, idx1);
Ok(())
}
-