From 365e4de077168de6b14e732dcb4809731dc53265 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Wed, 5 Feb 2025 23:08:27 -0800 Subject: [PATCH] load the journal file if it already exists apply the existing journal file, if any, to the old version of the database before diffing it against the new version. then, append the diff to the end of the journal. this allows easy creation of a journal file with multiple deltas, by running named-makejournal successively. --- bin/tools/named-makejournal.c | 69 ++++++++++++++++++++++++++++++--- bin/tools/named-makejournal.rst | 10 +++-- 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/bin/tools/named-makejournal.c b/bin/tools/named-makejournal.c index d67c970be9..2c974dc078 100644 --- a/bin/tools/named-makejournal.c +++ b/bin/tools/named-makejournal.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,48 @@ loadzone(dns_db_t **db, const char *origin, const char *filename) { return result; } +static isc_result_t +loadjournal(dns_db_t *db, const char *file) { + dns_journal_t *jnl = NULL; + isc_result_t result; + + result = dns_journal_open(mctx, file, DNS_JOURNAL_READ, &jnl); + if (result == ISC_R_NOTFOUND) { + return ISC_R_SUCCESS; + } else if (result != ISC_R_SUCCESS) { + fprintf(stderr, "Error: unable to open journal %s: %s\n", file, + isc_result_totext(result)); + return result; + } + + if (dns_journal_empty(jnl)) { + dns_journal_destroy(&jnl); + return ISC_R_SUCCESS; + } + + result = dns_journal_rollforward(jnl, db, 0); + switch (result) { + case ISC_R_SUCCESS: + break; + case DNS_R_UPTODATE: + result = ISC_R_SUCCESS; + break; + + case ISC_R_NOTFOUND: + case ISC_R_RANGE: + fprintf(stderr, "Error: journal %s out of sync with zone", + file); + break; + + default: + fprintf(stderr, "Error: journal %s: %s\n", file, + isc_result_totext(result)); + } + + dns_journal_destroy(&jnl); + return result; +} + int main(int argc, char **argv) { isc_result_t result; @@ -75,6 +118,7 @@ main(int argc, char **argv) { const char *journal = NULL; dns_db_t *olddb = NULL, *newdb = NULL; isc_logconfig_t *logconfig = NULL; + uint32_t s1, s2, s3; int ch; isc_commandline_init(argc, argv); @@ -130,22 +174,35 @@ main(int argc, char **argv) { goto cleanup; } - uint32_t s1, s2; result = dns_db_getsoaserial(olddb, NULL, &s1); if (result != ISC_R_SUCCESS) { - fprintf(stderr, "Error: no SOA found in %s\n", file1); + fprintf(stderr, "Error: %s: SOA lookup failed\n", file1); goto cleanup; } - result = dns_db_getsoaserial(newdb, NULL, &s2); + + result = loadjournal(olddb, journal); if (result != ISC_R_SUCCESS) { - fprintf(stderr, "Error: no SOA found in %s\n", file2); goto cleanup; } - if (s1 == s2) { + + result = dns_db_getsoaserial(olddb, NULL, &s2); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + result = dns_db_getsoaserial(newdb, NULL, &s3); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "Error: %s: SOA lookup failed\n", file2); + goto cleanup; + } + + if (isc_serial_eq(s1, s3)) { fprintf(stderr, "Error: SOA serial (%u) unchanged between files\n", s1); result = ISC_R_FAILURE; goto cleanup; + } else if (isc_serial_eq(s2, s3)) { + fprintf(stderr, "Journal %s already has serial %u\n", journal, + s3); + goto cleanup; } result = dns_db_diff(mctx, newdb, NULL, olddb, NULL, journal); @@ -166,5 +223,5 @@ cleanup: isc_mem_detach(&mctx); } - return result != ISC_R_SUCCESS ? 1 : 0; + return (result != ISC_R_SUCCESS) ? 1 : 0; } diff --git a/bin/tools/named-makejournal.rst b/bin/tools/named-makejournal.rst index 1a39a4d8f2..1724d0bfb4 100644 --- a/bin/tools/named-makejournal.rst +++ b/bin/tools/named-makejournal.rst @@ -40,10 +40,12 @@ If the optional argument ``journal`` is not specified, then the journal file name will be formed by appending the extension ``.jnl`` to the zone file name specified as ``oldfile``. -If the journal file already exists, a new transaction will be appended -onto the end of it. (Note, however, that the most recent serial number in -the existing journal file must match the serial number in ``oldfile``. -This will be corrected later.) +If the journal file already exists, then it will be applied to ``oldfile`` +immediately after loading. The difference between the resulting zone and +the one in ``newfile`` will then be appended onto the end of the journal. +This allows creation of journal files with multiple transactions, by +running ``named-makejournal`` multiple times, updating ``newfile`` each +time. Options ~~~~~~~