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 ~~~~~~~