From fb2d0e2897e10e71627bf895aeb6b8664ee54ad2 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 3 Mar 2021 17:07:15 +1100 Subject: [PATCH] extend named-journalprint to be able to force the journal version named-journalprint can now upgrade or downgrade a journal file in place; the '-u' option upgrades and the '-d' option downgrades. --- bin/tools/named-journalprint.c | 26 +++++++++++++--- bin/tools/named-journalprint.rst | 19 +++++++++--- doc/man/named-journalprint.1in | 19 +++++++++--- lib/dns/include/dns/journal.h | 1 + lib/dns/journal.c | 52 ++++++++++++++++++++++---------- 5 files changed, 86 insertions(+), 31 deletions(-) diff --git a/bin/tools/named-journalprint.c b/bin/tools/named-journalprint.c index 0fcfa2d0de..37cc0ff205 100644 --- a/bin/tools/named-journalprint.c +++ b/bin/tools/named-journalprint.c @@ -28,7 +28,7 @@ const char *progname = NULL; static void usage(void) { - fprintf(stderr, "Usage: %s [-x] journal\n", progname); + fprintf(stderr, "Usage: %s [-dux] journal\n", progname); exit(1); } @@ -68,10 +68,18 @@ main(int argc, char **argv) { isc_log_t *lctx = NULL; uint32_t flags = 0U; char ch; + bool downgrade = false; + bool upgrade = false; progname = argv[0]; - while ((ch = isc_commandline_parse(argc, argv, "x")) != -1) { + while ((ch = isc_commandline_parse(argc, argv, "dux")) != -1) { switch (ch) { + case 'd': + downgrade = true; + break; + case 'u': + upgrade = true; + break; case 'x': flags |= DNS_JOURNAL_PRINTXHDR; break; @@ -91,9 +99,17 @@ main(int argc, char **argv) { isc_mem_create(&mctx); RUNTIME_CHECK(setup_logging(mctx, stderr, &lctx) == ISC_R_SUCCESS); - result = dns_journal_print(mctx, flags, file, stdout); - if (result == DNS_R_NOJOURNAL) { - fprintf(stderr, "%s\n", dns_result_totext(result)); + if (upgrade) { + flags = DNS_JOURNAL_COMPACTALL; + result = dns_journal_compact(mctx, file, 0, flags, 0); + } else if (downgrade) { + flags = DNS_JOURNAL_COMPACTALL | DNS_JOURNAL_VERSION1; + result = dns_journal_compact(mctx, file, 0, flags, 0); + } else { + result = dns_journal_print(mctx, flags, file, stdout); + if (result == DNS_R_NOJOURNAL) { + fprintf(stderr, "%s\n", dns_result_totext(result)); + } } isc_log_destroy(&lctx); isc_mem_detach(&mctx); diff --git a/bin/tools/named-journalprint.rst b/bin/tools/named-journalprint.rst index 2ce6a05bb4..633bcb628b 100644 --- a/bin/tools/named-journalprint.rst +++ b/bin/tools/named-journalprint.rst @@ -29,13 +29,14 @@ named-journalprint - print zone journal in human-readable form Synopsis ~~~~~~~~ -:program:`named-journalprint` [**-x**] {journal} +:program:`named-journalprint` [**-dux**] {journal} Description ~~~~~~~~~~~ -``named-journalprint`` prints the contents of a zone journal file in a -human-readable form. +``named-journalprint`` scans the contents of a zone journal file, +printing it in a human-readable form, or, optionally, converting it +to a different journal file format. Journal files are automatically created by ``named`` when changes are made to dynamic zones (e.g., by ``nsupdate``). They record each addition @@ -50,8 +51,16 @@ into a human-readable text format. Each line begins with ``add`` or ``del``, to indicate whether the record was added or deleted, and continues with the resource record in master-file format. -The ``-x`` option causes additional information about the transaction -header to be printed before each group of changes. +The ``-x`` option causes additional data about the journal file to be +printed at the beginning of the output and before each group of changes. + +The ``-u`` (upgrade) and ``-d`` (downgrade) options recreate the journal +file with a modified format version. The existing journal file is +replaced. ``-d`` writes out the journal in the format used by +versions of BIND up to 9.16.11; ``-u`` writes it out in the format used +by versions since 9.16.13. (9.16.12 is omitted due to a journal-formatting +bug in that release.) Note that these options *must not* be used while +``named`` is running. See Also ~~~~~~~~ diff --git a/doc/man/named-journalprint.1in b/doc/man/named-journalprint.1in index 84684cb8d6..b18f896547 100644 --- a/doc/man/named-journalprint.1in +++ b/doc/man/named-journalprint.1in @@ -32,11 +32,12 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .. .SH SYNOPSIS .sp -\fBnamed\-journalprint\fP [\fB\-x\fP] {journal} +\fBnamed\-journalprint\fP [\fB\-dux\fP] {journal} .SH DESCRIPTION .sp -\fBnamed\-journalprint\fP prints the contents of a zone journal file in a -human\-readable form. +\fBnamed\-journalprint\fP scans the contents of a zone journal file, +printing it in a human\-readable form, or, optionally, converting it +to a different journal file format. .sp Journal files are automatically created by \fBnamed\fP when changes are made to dynamic zones (e.g., by \fBnsupdate\fP). They record each addition @@ -51,8 +52,16 @@ into a human\-readable text format. Each line begins with \fBadd\fP or \fBdel\fP to indicate whether the record was added or deleted, and continues with the resource record in master\-file format. .sp -The \fB\-x\fP option causes additional information about the transaction -header to be printed before each group of changes. +The \fB\-x\fP option causes additional data about the journal file to be +printed at the beginning of the output and before each group of changes. +.sp +The \fB\-u\fP (upgrade) and \fB\-d\fP (downgrade) options recreate the journal +file with a modified format version. The existing journal file is +replaced. \fB\-d\fP writes out the journal in the format used by +versions of BIND up to 9.16.11; \fB\-u\fP writes it out in the format used +by versions since 9.16.13. (9.16.12 is omitted due to a journal\-formatting +bug in that release.) Note that these options \fImust not\fP be used while +\fBnamed\fP is running. .SH SEE ALSO .sp \fBnamed(8)\fP, \fBnsupdate(1)\fP, BIND 9 Administrator Reference Manual. diff --git a/lib/dns/include/dns/journal.h b/lib/dns/include/dns/journal.h index 4d3b73efb5..e115bbc226 100644 --- a/lib/dns/include/dns/journal.h +++ b/lib/dns/include/dns/journal.h @@ -53,6 +53,7 @@ /*% Rewrite whole journal file instead of compacting */ #define DNS_JOURNAL_COMPACTALL 0x0001 +#define DNS_JOURNAL_VERSION1 0x0002 /*** *** Types diff --git a/lib/dns/journal.c b/lib/dns/journal.c index 5007f0c9ef..32756735f1 100644 --- a/lib/dns/journal.c +++ b/lib/dns/journal.c @@ -520,13 +520,20 @@ journal_read_xhdr(dns_journal_t *j, journal_xhdr_t *xhdr) { static isc_result_t journal_write_xhdr(dns_journal_t *j, uint32_t size, uint32_t count, uint32_t serial0, uint32_t serial1) { - journal_rawxhdr_t raw; - - encode_uint32(size, raw.size); - encode_uint32(count, raw.count); - encode_uint32(serial0, raw.serial0); - encode_uint32(serial1, raw.serial1); - return (journal_write(j, &raw, sizeof(raw))); + if (j->header_ver1) { + journal_rawxhdr_ver1_t raw; + encode_uint32(size, raw.size); + encode_uint32(serial0, raw.serial0); + encode_uint32(serial1, raw.serial1); + return (journal_write(j, &raw, sizeof(raw))); + } else { + journal_rawxhdr_t raw; + encode_uint32(size, raw.size); + encode_uint32(count, raw.count); + encode_uint32(serial0, raw.serial0); + encode_uint32(serial1, raw.serial1); + return (journal_write(j, &raw, sizeof(raw))); + } } /* @@ -547,7 +554,7 @@ journal_read_rrhdr(dns_journal_t *j, journal_rrhdr_t *rrhdr) { } static isc_result_t -journal_file_create(isc_mem_t *mctx, const char *filename) { +journal_file_create(isc_mem_t *mctx, bool downgrade, const char *filename) { FILE *fp = NULL; isc_result_t result; journal_header_t header; @@ -566,7 +573,11 @@ journal_file_create(isc_mem_t *mctx, const char *filename) { return (ISC_R_UNEXPECTED); } - header = initial_journal_header; + if (downgrade) { + header = journal_header_ver1; + } else { + header = initial_journal_header; + } header.index_size = index_size; journal_header_encode(&header, &rawheader); @@ -603,7 +614,7 @@ journal_file_create(isc_mem_t *mctx, const char *filename) { static isc_result_t journal_open(isc_mem_t *mctx, const char *filename, bool writable, bool create, - dns_journal_t **journalp) { + bool downgrade, dns_journal_t **journalp) { FILE *fp = NULL; isc_result_t result; journal_rawheader_t rawheader; @@ -624,7 +635,7 @@ journal_open(isc_mem_t *mctx, const char *filename, bool writable, bool create, "journal file %s does not exist, " "creating it", j->filename); - CHECK(journal_file_create(mctx, filename)); + CHECK(journal_file_create(mctx, downgrade, filename)); /* * Retry. */ @@ -758,7 +769,8 @@ dns_journal_open(isc_mem_t *mctx, const char *filename, unsigned int mode, create = ((mode & DNS_JOURNAL_CREATE) != 0); writable = ((mode & (DNS_JOURNAL_WRITE | DNS_JOURNAL_CREATE)) != 0); - result = journal_open(mctx, filename, writable, create, journalp); + result = journal_open(mctx, filename, writable, create, false, + journalp); if (result == ISC_R_NOTFOUND) { namelen = strlen(filename); if (namelen > 4U && strcmp(filename + namelen - 4, ".jnl") == 0) @@ -771,7 +783,7 @@ dns_journal_open(isc_mem_t *mctx, const char *filename, unsigned int mode, if (result >= sizeof(backup)) { return (ISC_R_NOSPACE); } - result = journal_open(mctx, backup, writable, writable, + result = journal_open(mctx, backup, writable, writable, false, journalp); } return (result); @@ -1620,6 +1632,10 @@ dns_journal_print(isc_mem_t *mctx, uint32_t flags, const char *filename, return (result); } + if (printxhdr) { + fprintf(file, "Journal format = %sHeader version = %d\n", + j->header.format + 1, j->header_ver1 ? 1 : 2); + } if (j->header.serialset) { fprintf(file, "Source serial = %u\n", j->header.sourceserial); } @@ -2385,6 +2401,7 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, uint32_t serial, char backup[PATH_MAX]; bool is_backup = false; bool rewrite = false; + bool downgrade = false; REQUIRE(filename != NULL); @@ -2401,10 +2418,10 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, uint32_t serial, filename); RUNTIME_CHECK(result < sizeof(backup)); - result = journal_open(mctx, filename, false, false, &j1); + result = journal_open(mctx, filename, false, false, false, &j1); if (result == ISC_R_NOTFOUND) { is_backup = true; - result = journal_open(mctx, backup, false, false, &j1); + result = journal_open(mctx, backup, false, false, false, &j1); } if (result != ISC_R_SUCCESS) { return (result); @@ -2415,6 +2432,9 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, uint32_t serial, * file (for example, to upversion it). */ if ((flags & DNS_JOURNAL_COMPACTALL) != 0) { + if ((flags & DNS_JOURNAL_VERSION1) != 0) { + downgrade = true; + } rewrite = true; serial = dns_journal_first_serial(j1); } else if (JOURNAL_EMPTY(&j1->header)) { @@ -2449,7 +2469,7 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, uint32_t serial, return (ISC_R_SUCCESS); } - CHECK(journal_open(mctx, newname, true, true, &j2)); + CHECK(journal_open(mctx, newname, true, true, downgrade, &j2)); CHECK(journal_seek(j2, indexend)); /*