#pragma once /* * snapdiff.h — byte-level comparator for two checkpoint files * (bug-1389 triage: OPCode_snapshotTransfer chunk-content corruption). * * Compares a locally-generated source checkpoint (snap-*.capnp) against a * received one (snap-*.bin, ha_handle_snapshot_chunk) byte-for-byte, and * reports the first divergent offset plus whether it lands exactly on an * OPCode_snapshotTransfer chunk boundary (SNAPSHOT_CHUNK_SIZE, config_repl.c) * — the decisive signal separating "chunk transport corrupted this specific * chunk" from "the two files were never going to match" (different content * entirely, unrelated to chunking). * * Strictly read-only: opens both files O_RDONLY, mutates nothing. */ #include #include /* Mirrors config_repl.c's SNAPSHOT_CHUNK_SIZE (the OPCode_snapshotTransfer * wire chunk size) — kept in sync manually; both are compile-time constants * for the same wire protocol, not expected to change independently. */ #define SNAPDIFF_CHUNK_SIZE 65536 typedef struct { off_t size1; off_t size2; int size_mismatch; /* 1 if size1 != size2 (diff_offset unset in that case) */ int identical; /* 1 if same size and byte-for-byte identical */ off_t diff_offset; /* -1 if identical or size_mismatch; else first * differing byte offset */ int at_chunk_boundary; /* 1 if diff_offset is the first byte of a * SNAPDIFF_CHUNK_SIZE-aligned chunk, i.e. * diff_offset % SNAPDIFF_CHUNK_SIZE == 0 */ off_t chunk_index; /* diff_offset / SNAPDIFF_CHUNK_SIZE, valid only * when diff_offset >= 0 */ } snapdiff_report_t; /* Compare `path1` (source of truth) against `path2` (candidate, e.g. a * received copy). Prints a human-readable report to `out` (may be NULL) and * fills `*rep` (may be NULL). Returns 0 if identical, 1 if they differ (see * `*rep` for detail), or a negative errno on open/fstat failure. */ int snapdiff_paths(const char* path1, const char* path2, FILE* out, snapdiff_report_t* rep);