2 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: masterdump.c,v 1.89.128.5 2009/01/19 23:47:02 tbox Exp $ */
26 #include <isc/event.h>
28 #include <isc/magic.h>
30 #include <isc/print.h>
31 #include <isc/stdio.h>
32 #include <isc/string.h>
38 #include <dns/dbiterator.h>
39 #include <dns/events.h>
40 #include <dns/fixedname.h>
43 #include <dns/master.h>
44 #include <dns/masterdump.h>
45 #include <dns/rdata.h>
46 #include <dns/rdataclass.h>
47 #include <dns/rdataset.h>
48 #include <dns/rdatasetiter.h>
49 #include <dns/rdatatype.h>
50 #include <dns/result.h>
54 #define DNS_DCTX_MAGIC ISC_MAGIC('D', 'c', 't', 'x')
55 #define DNS_DCTX_VALID(d) ISC_MAGIC_VALID(d, DNS_DCTX_MAGIC)
57 #define RETERR(x) do { \
58 isc_result_t _r = (x); \
59 if (_r != ISC_R_SUCCESS) \
63 struct dns_master_style
{
64 unsigned int flags
; /* DNS_STYLEFLAG_* */
65 unsigned int ttl_column
;
66 unsigned int class_column
;
67 unsigned int type_column
;
68 unsigned int rdata_column
;
69 unsigned int line_length
;
70 unsigned int tab_width
;
74 * The maximum length of the newline+indentation that is output
75 * when inserting a line break in an RR. This effectively puts an
76 * upper limits on the value of "rdata_column", because if it is
77 * very large, the tabs and spaces needed to reach it will not fit.
79 #define DNS_TOTEXT_LINEBREAK_MAXLEN 100
82 * Context structure for a masterfile dump in progress.
84 typedef struct dns_totext_ctx
{
85 dns_master_style_t style
;
86 isc_boolean_t class_printed
;
88 char linebreak_buf
[DNS_TOTEXT_LINEBREAK_MAXLEN
];
90 dns_name_t
* neworigin
;
91 dns_fixedname_t origin_fixname
;
92 isc_uint32_t current_ttl
;
93 isc_boolean_t current_ttl_valid
;
96 LIBDNS_EXTERNAL_DATA
const dns_master_style_t
97 dns_master_style_default
= {
98 DNS_STYLEFLAG_OMIT_OWNER
|
99 DNS_STYLEFLAG_OMIT_CLASS
|
100 DNS_STYLEFLAG_REL_OWNER
|
101 DNS_STYLEFLAG_REL_DATA
|
102 DNS_STYLEFLAG_OMIT_TTL
|
104 DNS_STYLEFLAG_COMMENT
|
105 DNS_STYLEFLAG_MULTILINE
,
106 24, 24, 24, 32, 80, 8
109 LIBDNS_EXTERNAL_DATA
const dns_master_style_t
110 dns_master_style_full
= {
111 DNS_STYLEFLAG_COMMENT
,
112 46, 46, 46, 64, 120, 8
115 LIBDNS_EXTERNAL_DATA
const dns_master_style_t
116 dns_master_style_explicitttl
= {
117 DNS_STYLEFLAG_OMIT_OWNER
|
118 DNS_STYLEFLAG_OMIT_CLASS
|
119 DNS_STYLEFLAG_REL_OWNER
|
120 DNS_STYLEFLAG_REL_DATA
|
121 DNS_STYLEFLAG_COMMENT
|
122 DNS_STYLEFLAG_MULTILINE
,
123 24, 32, 32, 40, 80, 8
126 LIBDNS_EXTERNAL_DATA
const dns_master_style_t
127 dns_master_style_cache
= {
128 DNS_STYLEFLAG_OMIT_OWNER
|
129 DNS_STYLEFLAG_OMIT_CLASS
|
130 DNS_STYLEFLAG_MULTILINE
|
131 DNS_STYLEFLAG_TRUST
|
132 DNS_STYLEFLAG_NCACHE
,
133 24, 32, 32, 40, 80, 8
136 LIBDNS_EXTERNAL_DATA
const dns_master_style_t
137 dns_master_style_simple
= {
139 24, 32, 32, 40, 80, 8
143 * A style suitable for dns_rdataset_totext().
145 LIBDNS_EXTERNAL_DATA
const dns_master_style_t
146 dns_master_style_debug
= {
147 DNS_STYLEFLAG_REL_OWNER
,
148 24, 32, 40, 48, 80, 8
153 static char spaces
[N_SPACES
+1] = " ";
156 static char tabs
[N_TABS
+1] = "\t\t\t\t\t\t\t\t\t\t";
162 unsigned int references
;
163 isc_boolean_t canceled
;
165 isc_boolean_t do_date
;
169 dns_dbversion_t
*version
;
170 dns_dbiterator_t
*dbiter
;
171 dns_totext_ctx_t tctx
;
173 dns_dumpdonefunc_t done
;
176 /* dns_master_dumpinc() */
179 dns_masterformat_t format
;
180 isc_result_t (*dumpsets
)(isc_mem_t
*mctx
, dns_name_t
*name
,
181 dns_rdatasetiter_t
*rdsiter
,
182 dns_totext_ctx_t
*ctx
,
183 isc_buffer_t
*buffer
, FILE *f
);
186 #define NXDOMAIN(x) (((x)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
189 * Output tabs and spaces to go from column '*current' to
190 * column 'to', and update '*current' to reflect the new
194 indent(unsigned int *current
, unsigned int to
, int tabwidth
,
195 isc_buffer_t
*target
)
200 int ntabs
, nspaces
, t
;
207 ntabs
= to
/ tabwidth
- from
/ tabwidth
;
212 isc_buffer_availableregion(target
, &r
);
213 if (r
.length
< (unsigned) ntabs
)
214 return (ISC_R_NOSPACE
);
226 isc_buffer_add(target
, ntabs
);
227 from
= (to
/ tabwidth
) * tabwidth
;
231 INSIST(nspaces
>= 0);
233 isc_buffer_availableregion(target
, &r
);
234 if (r
.length
< (unsigned) nspaces
)
235 return (ISC_R_NOSPACE
);
243 memcpy(p
, spaces
, n
);
247 isc_buffer_add(target
, nspaces
);
250 return (ISC_R_SUCCESS
);
254 totext_ctx_init(const dns_master_style_t
*style
, dns_totext_ctx_t
*ctx
) {
257 REQUIRE(style
->tab_width
!= 0);
260 ctx
->class_printed
= ISC_FALSE
;
262 dns_fixedname_init(&ctx
->origin_fixname
);
265 * Set up the line break string if needed.
267 if ((ctx
->style
.flags
& DNS_STYLEFLAG_MULTILINE
) != 0) {
270 unsigned int col
= 0;
272 isc_buffer_init(&buf
, ctx
->linebreak_buf
,
273 sizeof(ctx
->linebreak_buf
));
275 isc_buffer_availableregion(&buf
, &r
);
277 return (DNS_R_TEXTTOOLONG
);
279 isc_buffer_add(&buf
, 1);
281 result
= indent(&col
, ctx
->style
.rdata_column
,
282 ctx
->style
.tab_width
, &buf
);
284 * Do not return ISC_R_NOSPACE if the line break string
285 * buffer is too small, because that would just make
286 * dump_rdataset() retry indefinitely with ever
287 * bigger target buffers. That's a different buffer,
288 * so it won't help. Use DNS_R_TEXTTOOLONG as a substitute.
290 if (result
== ISC_R_NOSPACE
)
291 return (DNS_R_TEXTTOOLONG
);
292 if (result
!= ISC_R_SUCCESS
)
295 isc_buffer_availableregion(&buf
, &r
);
297 return (DNS_R_TEXTTOOLONG
);
299 isc_buffer_add(&buf
, 1);
300 ctx
->linebreak
= ctx
->linebreak_buf
;
302 ctx
->linebreak
= NULL
;
306 ctx
->neworigin
= NULL
;
307 ctx
->current_ttl
= 0;
308 ctx
->current_ttl_valid
= ISC_FALSE
;
310 return (ISC_R_SUCCESS
);
313 #define INDENT_TO(col) \
315 if ((result = indent(&column, ctx->style.col, \
316 ctx->style.tab_width, target)) \
323 str_totext(const char *source
, isc_buffer_t
*target
) {
327 isc_buffer_availableregion(target
, ®ion
);
330 if (l
> region
.length
)
331 return (ISC_R_NOSPACE
);
333 memcpy(region
.base
, source
, l
);
334 isc_buffer_add(target
, l
);
335 return (ISC_R_SUCCESS
);
339 * Convert 'rdataset' to master file text format according to 'ctx',
340 * storing the result in 'target'. If 'owner_name' is NULL, it
341 * is omitted; otherwise 'owner_name' must be valid and have at least
346 rdataset_totext(dns_rdataset_t
*rdataset
,
347 dns_name_t
*owner_name
,
348 dns_totext_ctx_t
*ctx
,
349 isc_boolean_t omit_final_dot
,
350 isc_buffer_t
*target
)
354 isc_boolean_t first
= ISC_TRUE
;
355 isc_uint32_t current_ttl
;
356 isc_boolean_t current_ttl_valid
;
357 dns_rdatatype_t type
;
359 REQUIRE(DNS_RDATASET_VALID(rdataset
));
361 rdataset
->attributes
|= DNS_RDATASETATTR_LOADORDER
;
362 result
= dns_rdataset_first(rdataset
);
363 REQUIRE(result
== ISC_R_SUCCESS
);
365 current_ttl
= ctx
->current_ttl
;
366 current_ttl_valid
= ctx
->current_ttl_valid
;
374 if (owner_name
!= NULL
&&
375 ! ((ctx
->style
.flags
& DNS_STYLEFLAG_OMIT_OWNER
) != 0 &&
378 unsigned int name_start
= target
->used
;
379 RETERR(dns_name_totext(owner_name
,
382 column
+= target
->used
- name_start
;
388 if ((ctx
->style
.flags
& DNS_STYLEFLAG_NO_TTL
) == 0 &&
389 !((ctx
->style
.flags
& DNS_STYLEFLAG_OMIT_TTL
) != 0 &&
391 rdataset
->ttl
== current_ttl
))
397 INDENT_TO(ttl_column
);
398 length
= snprintf(ttlbuf
, sizeof(ttlbuf
), "%u",
400 INSIST(length
<= sizeof(ttlbuf
));
401 isc_buffer_availableregion(target
, &r
);
402 if (r
.length
< length
)
403 return (ISC_R_NOSPACE
);
404 memcpy(r
.base
, ttlbuf
, length
);
405 isc_buffer_add(target
, length
);
409 * If the $TTL directive is not in use, the TTL we
410 * just printed becomes the default for subsequent RRs.
412 if ((ctx
->style
.flags
& DNS_STYLEFLAG_TTL
) == 0) {
413 current_ttl
= rdataset
->ttl
;
414 current_ttl_valid
= ISC_TRUE
;
421 if ((ctx
->style
.flags
& DNS_STYLEFLAG_NO_CLASS
) == 0 &&
422 ((ctx
->style
.flags
& DNS_STYLEFLAG_OMIT_CLASS
) == 0 ||
423 ctx
->class_printed
== ISC_FALSE
))
425 unsigned int class_start
;
426 INDENT_TO(class_column
);
427 class_start
= target
->used
;
428 result
= dns_rdataclass_totext(rdataset
->rdclass
,
430 if (result
!= ISC_R_SUCCESS
)
432 column
+= (target
->used
- class_start
);
439 if (rdataset
->type
== 0) {
440 type
= rdataset
->covers
;
442 type
= rdataset
->type
;
446 unsigned int type_start
;
447 INDENT_TO(type_column
);
448 type_start
= target
->used
;
449 if (rdataset
->type
== 0)
450 RETERR(str_totext("\\-", target
));
451 result
= dns_rdatatype_totext(type
, target
);
452 if (result
!= ISC_R_SUCCESS
)
454 column
+= (target
->used
- type_start
);
460 INDENT_TO(rdata_column
);
461 if (rdataset
->type
== 0) {
462 if (NXDOMAIN(rdataset
))
463 RETERR(str_totext(";-$NXDOMAIN\n", target
));
465 RETERR(str_totext(";-$NXRRSET\n", target
));
467 dns_rdata_t rdata
= DNS_RDATA_INIT
;
470 dns_rdataset_current(rdataset
, &rdata
);
472 RETERR(dns_rdata_tofmttext(&rdata
,
475 ctx
->style
.line_length
-
476 ctx
->style
.rdata_column
,
480 isc_buffer_availableregion(target
, &r
);
482 return (ISC_R_NOSPACE
);
484 isc_buffer_add(target
, 1);
488 result
= dns_rdataset_next(rdataset
);
489 } while (result
== ISC_R_SUCCESS
);
491 if (result
!= ISC_R_NOMORE
)
495 * Update the ctx state to reflect what we just printed.
496 * This is done last, only when we are sure we will return
497 * success, because this function may be called multiple
498 * times with increasing buffer sizes until it succeeds,
499 * and failed attempts must not update the state prematurely.
501 ctx
->class_printed
= ISC_TRUE
;
502 ctx
->current_ttl
= current_ttl
;
503 ctx
->current_ttl_valid
= current_ttl_valid
;
505 return (ISC_R_SUCCESS
);
509 * Print the name, type, and class of an empty rdataset,
510 * such as those used to represent the question section
514 question_totext(dns_rdataset_t
*rdataset
,
515 dns_name_t
*owner_name
,
516 dns_totext_ctx_t
*ctx
,
517 isc_boolean_t omit_final_dot
,
518 isc_buffer_t
*target
)
524 REQUIRE(DNS_RDATASET_VALID(rdataset
));
525 result
= dns_rdataset_first(rdataset
);
526 REQUIRE(result
== ISC_R_NOMORE
);
532 unsigned int name_start
= target
->used
;
533 RETERR(dns_name_totext(owner_name
,
536 column
+= target
->used
- name_start
;
541 unsigned int class_start
;
542 INDENT_TO(class_column
);
543 class_start
= target
->used
;
544 result
= dns_rdataclass_totext(rdataset
->rdclass
, target
);
545 if (result
!= ISC_R_SUCCESS
)
547 column
+= (target
->used
- class_start
);
552 unsigned int type_start
;
553 INDENT_TO(type_column
);
554 type_start
= target
->used
;
555 result
= dns_rdatatype_totext(rdataset
->type
, target
);
556 if (result
!= ISC_R_SUCCESS
)
558 column
+= (target
->used
- type_start
);
561 isc_buffer_availableregion(target
, &r
);
563 return (ISC_R_NOSPACE
);
565 isc_buffer_add(target
, 1);
567 return (ISC_R_SUCCESS
);
571 dns_rdataset_totext(dns_rdataset_t
*rdataset
,
572 dns_name_t
*owner_name
,
573 isc_boolean_t omit_final_dot
,
574 isc_boolean_t question
,
575 isc_buffer_t
*target
)
577 dns_totext_ctx_t ctx
;
579 result
= totext_ctx_init(&dns_master_style_debug
, &ctx
);
580 if (result
!= ISC_R_SUCCESS
) {
581 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
582 "could not set master file style");
583 return (ISC_R_UNEXPECTED
);
587 * The caller might want to give us an empty owner
588 * name (e.g. if they are outputting into a master
589 * file and this rdataset has the same name as the
592 if (dns_name_countlabels(owner_name
) == 0)
596 return (question_totext(rdataset
, owner_name
, &ctx
,
597 omit_final_dot
, target
));
599 return (rdataset_totext(rdataset
, owner_name
, &ctx
,
600 omit_final_dot
, target
));
604 dns_master_rdatasettotext(dns_name_t
*owner_name
,
605 dns_rdataset_t
*rdataset
,
606 const dns_master_style_t
*style
,
607 isc_buffer_t
*target
)
609 dns_totext_ctx_t ctx
;
611 result
= totext_ctx_init(style
, &ctx
);
612 if (result
!= ISC_R_SUCCESS
) {
613 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
614 "could not set master file style");
615 return (ISC_R_UNEXPECTED
);
618 return (rdataset_totext(rdataset
, owner_name
, &ctx
,
623 dns_master_questiontotext(dns_name_t
*owner_name
,
624 dns_rdataset_t
*rdataset
,
625 const dns_master_style_t
*style
,
626 isc_buffer_t
*target
)
628 dns_totext_ctx_t ctx
;
630 result
= totext_ctx_init(style
, &ctx
);
631 if (result
!= ISC_R_SUCCESS
) {
632 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
633 "could not set master file style");
634 return (ISC_R_UNEXPECTED
);
637 return (question_totext(rdataset
, owner_name
, &ctx
,
642 * Print an rdataset. 'buffer' is a scratch buffer, which must have been
643 * dynamically allocated by the caller. It must be large enough to
644 * hold the result from dns_ttl_totext(). If more than that is needed,
645 * the buffer will be grown automatically.
649 dump_rdataset(isc_mem_t
*mctx
, dns_name_t
*name
, dns_rdataset_t
*rdataset
,
650 dns_totext_ctx_t
*ctx
,
651 isc_buffer_t
*buffer
, FILE *f
)
656 REQUIRE(buffer
->length
> 0);
659 * Output a $TTL directive if needed.
662 if ((ctx
->style
.flags
& DNS_STYLEFLAG_TTL
) != 0) {
663 if (ctx
->current_ttl_valid
== ISC_FALSE
||
664 ctx
->current_ttl
!= rdataset
->ttl
)
666 if ((ctx
->style
.flags
& DNS_STYLEFLAG_COMMENT
) != 0)
668 isc_buffer_clear(buffer
);
669 result
= dns_ttl_totext(rdataset
->ttl
,
671 INSIST(result
== ISC_R_SUCCESS
);
672 isc_buffer_usedregion(buffer
, &r
);
673 fprintf(f
, "$TTL %u\t; %.*s\n", rdataset
->ttl
,
674 (int) r
.length
, (char *) r
.base
);
676 fprintf(f
, "$TTL %u\n", rdataset
->ttl
);
678 ctx
->current_ttl
= rdataset
->ttl
;
679 ctx
->current_ttl_valid
= ISC_TRUE
;
683 isc_buffer_clear(buffer
);
686 * Generate the text representation of the rdataset into
687 * the buffer. If the buffer is too small, grow it.
692 result
= rdataset_totext(rdataset
, name
, ctx
,
694 if (result
!= ISC_R_NOSPACE
)
697 newlength
= buffer
->length
* 2;
698 newmem
= isc_mem_get(mctx
, newlength
);
700 return (ISC_R_NOMEMORY
);
701 isc_mem_put(mctx
, buffer
->base
, buffer
->length
);
702 isc_buffer_init(buffer
, newmem
, newlength
);
704 if (result
!= ISC_R_SUCCESS
)
708 * Write the buffer contents to the master file.
710 isc_buffer_usedregion(buffer
, &r
);
711 result
= isc_stdio_write(r
.base
, 1, (size_t)r
.length
, f
, NULL
);
713 if (result
!= ISC_R_SUCCESS
) {
714 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
715 "master file write failed: %s",
716 isc_result_totext(result
));
720 return (ISC_R_SUCCESS
);
724 * Define the order in which rdatasets should be printed in zone
725 * files. We will print SOA and NS records before others, SIGs
726 * immediately following the things they sign, and order everything
727 * else by RR number. This is all just for aesthetics and
728 * compatibility with buggy software that expects the SOA to be first;
729 * the DNS specifications allow any order.
733 dump_order(const dns_rdataset_t
*rds
) {
736 if (rds
->type
== dns_rdatatype_rrsig
) {
744 case dns_rdatatype_soa
:
747 case dns_rdatatype_ns
:
754 return (t
<< 1) + sig
;
758 dump_order_compare(const void *a
, const void *b
) {
759 return (dump_order(*((const dns_rdataset_t
* const *) a
)) -
760 dump_order(*((const dns_rdataset_t
* const *) b
)));
764 * Dump all the rdatasets of a domain name to a master file. We make
765 * a "best effort" attempt to sort the RRsets in a nice order, but if
766 * there are more than MAXSORT RRsets, we punt and only sort them in
767 * groups of MAXSORT. This is not expected to ever happen in practice
768 * since much less than 64 RR types have been registered with the
769 * IANA, so far, and the output will be correct (though not
770 * aesthetically pleasing) even if it does happen.
775 static const char *trustnames
[] = {
784 "local" /* aka ultimate */
788 dump_rdatasets_text(isc_mem_t
*mctx
, dns_name_t
*name
,
789 dns_rdatasetiter_t
*rdsiter
, dns_totext_ctx_t
*ctx
,
790 isc_buffer_t
*buffer
, FILE *f
)
792 isc_result_t itresult
, dumpresult
;
794 dns_rdataset_t rdatasets
[MAXSORT
];
795 dns_rdataset_t
*sorted
[MAXSORT
];
798 itresult
= dns_rdatasetiter_first(rdsiter
);
799 dumpresult
= ISC_R_SUCCESS
;
801 if (itresult
== ISC_R_SUCCESS
&& ctx
->neworigin
!= NULL
) {
802 isc_buffer_clear(buffer
);
803 itresult
= dns_name_totext(ctx
->neworigin
, ISC_FALSE
, buffer
);
804 RUNTIME_CHECK(itresult
== ISC_R_SUCCESS
);
805 isc_buffer_usedregion(buffer
, &r
);
806 fprintf(f
, "$ORIGIN %.*s\n", (int) r
.length
, (char *) r
.base
);
807 ctx
->neworigin
= NULL
;
812 itresult
== ISC_R_SUCCESS
&& i
< MAXSORT
;
813 itresult
= dns_rdatasetiter_next(rdsiter
), i
++) {
814 dns_rdataset_init(&rdatasets
[i
]);
815 dns_rdatasetiter_current(rdsiter
, &rdatasets
[i
]);
816 sorted
[i
] = &rdatasets
[i
];
819 INSIST(n
<= MAXSORT
);
821 qsort(sorted
, n
, sizeof(sorted
[0]), dump_order_compare
);
823 for (i
= 0; i
< n
; i
++) {
824 dns_rdataset_t
*rds
= sorted
[i
];
825 if (ctx
->style
.flags
& DNS_STYLEFLAG_TRUST
) {
826 unsigned int trust
= rds
->trust
;
827 INSIST(trust
< (sizeof(trustnames
) /
828 sizeof(trustnames
[0])));
829 fprintf(f
, "; %s\n", trustnames
[trust
]);
831 if (rds
->type
== 0 &&
832 (ctx
->style
.flags
& DNS_STYLEFLAG_NCACHE
) == 0) {
833 /* Omit negative cache entries */
835 isc_result_t result
=
836 dump_rdataset(mctx
, name
, rds
, ctx
,
838 if (result
!= ISC_R_SUCCESS
)
840 if ((ctx
->style
.flags
& DNS_STYLEFLAG_OMIT_OWNER
) != 0)
843 dns_rdataset_disassociate(rds
);
846 if (dumpresult
!= ISC_R_SUCCESS
)
850 * If we got more data than could be sorted at once,
851 * go handle the rest.
853 if (itresult
== ISC_R_SUCCESS
)
856 if (itresult
== ISC_R_NOMORE
)
857 itresult
= ISC_R_SUCCESS
;
863 * Dump given RRsets in the "raw" format.
866 dump_rdataset_raw(isc_mem_t
*mctx
, dns_name_t
*name
, dns_rdataset_t
*rdataset
,
867 isc_buffer_t
*buffer
, FILE *f
)
870 isc_uint32_t totallen
;
872 isc_region_t r
, r_hdr
;
874 REQUIRE(buffer
->length
> 0);
875 REQUIRE(DNS_RDATASET_VALID(rdataset
));
879 result
= dns_rdataset_first(rdataset
);
880 REQUIRE(result
== ISC_R_SUCCESS
);
882 isc_buffer_clear(buffer
);
885 * Common header and owner name (length followed by name)
886 * These fields should be in a moderate length, so we assume we
887 * can store all of them in the initial buffer.
889 isc_buffer_availableregion(buffer
, &r_hdr
);
890 INSIST(r_hdr
.length
>= sizeof(dns_masterrawrdataset_t
));
891 isc_buffer_putuint32(buffer
, totallen
); /* XXX: leave space */
892 isc_buffer_putuint16(buffer
, rdataset
->rdclass
); /* 16-bit class */
893 isc_buffer_putuint16(buffer
, rdataset
->type
); /* 16-bit type */
894 isc_buffer_putuint16(buffer
, rdataset
->covers
); /* same as type */
895 isc_buffer_putuint32(buffer
, rdataset
->ttl
); /* 32-bit TTL */
896 isc_buffer_putuint32(buffer
, dns_rdataset_count(rdataset
));
897 totallen
= isc_buffer_usedlength(buffer
);
898 INSIST(totallen
<= sizeof(dns_masterrawrdataset_t
));
900 dns_name_toregion(name
, &r
);
901 INSIST(isc_buffer_availablelength(buffer
) >=
902 (sizeof(dlen
) + r
.length
));
903 dlen
= (isc_uint16_t
)r
.length
;
904 isc_buffer_putuint16(buffer
, dlen
);
905 isc_buffer_copyregion(buffer
, &r
);
906 totallen
+= sizeof(dlen
) + r
.length
;
909 dns_rdata_t rdata
= DNS_RDATA_INIT
;
912 dns_rdataset_current(rdataset
, &rdata
);
913 dns_rdata_toregion(&rdata
, &r
);
914 INSIST(r
.length
<= 0xffffU
);
915 dlen
= (isc_uint16_t
)r
.length
;
918 * Copy the rdata into the buffer. If the buffer is too small,
919 * grow it. This should be rare, so we'll simply restart the
920 * entire procedure (or should we copy the old data and
923 if (isc_buffer_availablelength(buffer
) <
924 sizeof(dlen
) + r
.length
) {
928 newlength
= buffer
->length
* 2;
929 newmem
= isc_mem_get(mctx
, newlength
);
931 return (ISC_R_NOMEMORY
);
932 isc_mem_put(mctx
, buffer
->base
, buffer
->length
);
933 isc_buffer_init(buffer
, newmem
, newlength
);
936 isc_buffer_putuint16(buffer
, dlen
);
937 isc_buffer_copyregion(buffer
, &r
);
938 totallen
+= sizeof(dlen
) + r
.length
;
940 result
= dns_rdataset_next(rdataset
);
941 } while (result
== ISC_R_SUCCESS
);
943 if (result
!= ISC_R_NOMORE
)
947 * Fill in the total length field.
948 * XXX: this is a bit tricky. Since we have already "used" the space
949 * for the total length in the buffer, we first remember the entire
950 * buffer length in the region, "rewind", and then write the value.
952 isc_buffer_usedregion(buffer
, &r
);
953 isc_buffer_clear(buffer
);
954 isc_buffer_putuint32(buffer
, totallen
);
955 INSIST(isc_buffer_usedlength(buffer
) < totallen
);
958 * Write the buffer contents to the raw master file.
960 result
= isc_stdio_write(r
.base
, 1, (size_t)r
.length
, f
, NULL
);
962 if (result
!= ISC_R_SUCCESS
) {
963 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
964 "raw master file write failed: %s",
965 isc_result_totext(result
));
973 dump_rdatasets_raw(isc_mem_t
*mctx
, dns_name_t
*name
,
974 dns_rdatasetiter_t
*rdsiter
, dns_totext_ctx_t
*ctx
,
975 isc_buffer_t
*buffer
, FILE *f
)
978 dns_rdataset_t rdataset
;
980 for (result
= dns_rdatasetiter_first(rdsiter
);
981 result
== ISC_R_SUCCESS
;
982 result
= dns_rdatasetiter_next(rdsiter
)) {
984 dns_rdataset_init(&rdataset
);
985 dns_rdatasetiter_current(rdsiter
, &rdataset
);
987 if (rdataset
.type
== 0 &&
988 (ctx
->style
.flags
& DNS_STYLEFLAG_NCACHE
) == 0) {
989 /* Omit negative cache entries */
991 result
= dump_rdataset_raw(mctx
, name
, &rdataset
,
994 dns_rdataset_disassociate(&rdataset
);
997 if (result
== ISC_R_NOMORE
)
998 result
= ISC_R_SUCCESS
;
1004 * Initial size of text conversion buffer. The buffer is used
1005 * for several purposes: converting origin names, rdatasets,
1006 * $DATE timestamps, and comment strings for $TTL directives.
1008 * When converting rdatasets, it is dynamically resized, but
1009 * when converting origins, timestamps, etc it is not. Therefore,
1010 * the initial size must large enough to hold the longest possible
1011 * text representation of any domain name (for $ORIGIN).
1013 static const int initial_buffer_length
= 1200;
1016 dumptostreaminc(dns_dumpctx_t
*dctx
);
1019 dumpctx_destroy(dns_dumpctx_t
*dctx
) {
1022 DESTROYLOCK(&dctx
->lock
);
1023 dns_dbiterator_destroy(&dctx
->dbiter
);
1024 if (dctx
->version
!= NULL
)
1025 dns_db_closeversion(dctx
->db
, &dctx
->version
, ISC_FALSE
);
1026 dns_db_detach(&dctx
->db
);
1027 if (dctx
->task
!= NULL
)
1028 isc_task_detach(&dctx
->task
);
1029 if (dctx
->file
!= NULL
)
1030 isc_mem_free(dctx
->mctx
, dctx
->file
);
1031 if (dctx
->tmpfile
!= NULL
)
1032 isc_mem_free(dctx
->mctx
, dctx
->tmpfile
);
1033 isc_mem_putanddetach(&dctx
->mctx
, dctx
, sizeof(*dctx
));
1037 dns_dumpctx_attach(dns_dumpctx_t
*source
, dns_dumpctx_t
**target
) {
1039 REQUIRE(DNS_DCTX_VALID(source
));
1040 REQUIRE(target
!= NULL
&& *target
== NULL
);
1042 LOCK(&source
->lock
);
1043 INSIST(source
->references
> 0);
1044 source
->references
++;
1045 INSIST(source
->references
!= 0); /* Overflow? */
1046 UNLOCK(&source
->lock
);
1052 dns_dumpctx_detach(dns_dumpctx_t
**dctxp
) {
1053 dns_dumpctx_t
*dctx
;
1054 isc_boolean_t need_destroy
= ISC_FALSE
;
1056 REQUIRE(dctxp
!= NULL
);
1058 REQUIRE(DNS_DCTX_VALID(dctx
));
1063 INSIST(dctx
->references
!= 0);
1065 if (dctx
->references
== 0)
1066 need_destroy
= ISC_TRUE
;
1067 UNLOCK(&dctx
->lock
);
1069 dumpctx_destroy(dctx
);
1073 dns_dumpctx_version(dns_dumpctx_t
*dctx
) {
1074 REQUIRE(DNS_DCTX_VALID(dctx
));
1075 return (dctx
->version
);
1079 dns_dumpctx_db(dns_dumpctx_t
*dctx
) {
1080 REQUIRE(DNS_DCTX_VALID(dctx
));
1085 dns_dumpctx_cancel(dns_dumpctx_t
*dctx
) {
1086 REQUIRE(DNS_DCTX_VALID(dctx
));
1089 dctx
->canceled
= ISC_TRUE
;
1090 UNLOCK(&dctx
->lock
);
1094 closeandrename(FILE *f
, isc_result_t result
, const char *temp
, const char *file
)
1096 isc_result_t tresult
;
1097 isc_boolean_t logit
= ISC_TF(result
== ISC_R_SUCCESS
);
1099 if (result
== ISC_R_SUCCESS
)
1100 result
= isc_stdio_sync(f
);
1101 if (result
!= ISC_R_SUCCESS
&& logit
) {
1102 isc_log_write(dns_lctx
, ISC_LOGCATEGORY_GENERAL
,
1103 DNS_LOGMODULE_MASTERDUMP
, ISC_LOG_ERROR
,
1104 "dumping master file: %s: fsync: %s",
1105 temp
, isc_result_totext(result
));
1108 tresult
= isc_stdio_close(f
);
1109 if (result
== ISC_R_SUCCESS
)
1111 if (result
!= ISC_R_SUCCESS
&& logit
) {
1112 isc_log_write(dns_lctx
, ISC_LOGCATEGORY_GENERAL
,
1113 DNS_LOGMODULE_MASTERDUMP
, ISC_LOG_ERROR
,
1114 "dumping master file: %s: fclose: %s",
1115 temp
, isc_result_totext(result
));
1118 if (result
== ISC_R_SUCCESS
)
1119 result
= isc_file_rename(temp
, file
);
1121 (void)isc_file_remove(temp
);
1122 if (result
!= ISC_R_SUCCESS
&& logit
) {
1123 isc_log_write(dns_lctx
, ISC_LOGCATEGORY_GENERAL
,
1124 DNS_LOGMODULE_MASTERDUMP
, ISC_LOG_ERROR
,
1125 "dumping master file: rename: %s: %s",
1126 file
, isc_result_totext(result
));
1132 dump_quantum(isc_task_t
*task
, isc_event_t
*event
) {
1133 isc_result_t result
;
1134 isc_result_t tresult
;
1135 dns_dumpctx_t
*dctx
;
1137 REQUIRE(event
!= NULL
);
1138 dctx
= event
->ev_arg
;
1139 REQUIRE(DNS_DCTX_VALID(dctx
));
1141 result
= ISC_R_CANCELED
;
1143 result
= dumptostreaminc(dctx
);
1144 if (result
== DNS_R_CONTINUE
) {
1145 event
->ev_arg
= dctx
;
1146 isc_task_send(task
, &event
);
1150 if (dctx
->file
!= NULL
) {
1151 tresult
= closeandrename(dctx
->f
, result
,
1152 dctx
->tmpfile
, dctx
->file
);
1153 if (tresult
!= ISC_R_SUCCESS
&& result
== ISC_R_SUCCESS
)
1156 (dctx
->done
)(dctx
->done_arg
, result
);
1157 isc_event_free(&event
);
1158 dns_dumpctx_detach(&dctx
);
1162 task_send(dns_dumpctx_t
*dctx
) {
1165 event
= isc_event_allocate(dctx
->mctx
, NULL
, DNS_EVENT_DUMPQUANTUM
,
1166 dump_quantum
, dctx
, sizeof(*event
));
1168 return (ISC_R_NOMEMORY
);
1169 isc_task_send(dctx
->task
, &event
);
1170 return (ISC_R_SUCCESS
);
1174 dumpctx_create(isc_mem_t
*mctx
, dns_db_t
*db
, dns_dbversion_t
*version
,
1175 const dns_master_style_t
*style
, FILE *f
, dns_dumpctx_t
**dctxp
,
1176 dns_masterformat_t format
)
1178 dns_dumpctx_t
*dctx
;
1179 isc_result_t result
;
1180 isc_boolean_t relative
;
1182 dctx
= isc_mem_get(mctx
, sizeof(*dctx
));
1184 return (ISC_R_NOMEMORY
);
1188 dctx
->dbiter
= NULL
;
1190 dctx
->version
= NULL
;
1192 dctx
->done_arg
= NULL
;
1195 dctx
->first
= ISC_TRUE
;
1196 dctx
->canceled
= ISC_FALSE
;
1198 dctx
->tmpfile
= NULL
;
1199 dctx
->format
= format
;
1202 case dns_masterformat_text
:
1203 dctx
->dumpsets
= dump_rdatasets_text
;
1205 case dns_masterformat_raw
:
1206 dctx
->dumpsets
= dump_rdatasets_raw
;
1213 result
= totext_ctx_init(style
, &dctx
->tctx
);
1214 if (result
!= ISC_R_SUCCESS
) {
1215 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1216 "could not set master file style");
1220 isc_stdtime_get(&dctx
->now
);
1221 dns_db_attach(db
, &dctx
->db
);
1223 dctx
->do_date
= dns_db_iscache(dctx
->db
);
1225 if (dctx
->format
== dns_masterformat_text
&&
1226 (dctx
->tctx
.style
.flags
& DNS_STYLEFLAG_REL_OWNER
) != 0) {
1227 relative
= ISC_TRUE
;
1229 relative
= ISC_FALSE
;
1230 result
= dns_db_createiterator(dctx
->db
, relative
, &dctx
->dbiter
);
1231 if (result
!= ISC_R_SUCCESS
)
1234 result
= isc_mutex_init(&dctx
->lock
);
1235 if (result
!= ISC_R_SUCCESS
)
1237 if (version
!= NULL
)
1238 dns_db_attachversion(dctx
->db
, version
, &dctx
->version
);
1239 else if (!dns_db_iscache(db
))
1240 dns_db_currentversion(dctx
->db
, &dctx
->version
);
1241 isc_mem_attach(mctx
, &dctx
->mctx
);
1242 dctx
->references
= 1;
1243 dctx
->magic
= DNS_DCTX_MAGIC
;
1245 return (ISC_R_SUCCESS
);
1248 if (dctx
->dbiter
!= NULL
)
1249 dns_dbiterator_destroy(&dctx
->dbiter
);
1250 if (dctx
->db
!= NULL
)
1251 dns_db_detach(&dctx
->db
);
1253 isc_mem_put(mctx
, dctx
, sizeof(*dctx
));
1258 dumptostreaminc(dns_dumpctx_t
*dctx
) {
1259 isc_result_t result
;
1260 isc_buffer_t buffer
;
1264 dns_fixedname_t fixname
;
1266 dns_masterrawheader_t rawheader
;
1270 bufmem
= isc_mem_get(dctx
->mctx
, initial_buffer_length
);
1272 return (ISC_R_NOMEMORY
);
1274 isc_buffer_init(&buffer
, bufmem
, initial_buffer_length
);
1276 dns_fixedname_init(&fixname
);
1277 name
= dns_fixedname_name(&fixname
);
1280 switch (dctx
->format
) {
1281 case dns_masterformat_text
:
1283 * If the database has cache semantics, output an
1284 * RFC2540 $DATE directive so that the TTLs can be
1285 * adjusted when it is reloaded. For zones it is not
1286 * really needed, and it would make the file
1287 * incompatible with pre-RFC2540 software, so we omit
1288 * it in the zone case.
1290 if (dctx
->do_date
) {
1291 result
= dns_time32_totext(dctx
->now
, &buffer
);
1292 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1293 isc_buffer_usedregion(&buffer
, &r
);
1294 fprintf(dctx
->f
, "$DATE %.*s\n",
1295 (int) r
.length
, (char *) r
.base
);
1298 case dns_masterformat_raw
:
1299 r
.base
= (unsigned char *)&rawheader
;
1300 r
.length
= sizeof(rawheader
);
1301 isc_buffer_region(&buffer
, &r
);
1302 isc_buffer_putuint32(&buffer
, dns_masterformat_raw
);
1303 isc_buffer_putuint32(&buffer
, DNS_RAWFORMAT_VERSION
);
1304 if (sizeof(now32
) != sizeof(dctx
->now
)) {
1306 * We assume isc_stdtime_t is a 32-bit integer,
1307 * which should be the case on most cases.
1308 * If it turns out to be uncommon, we'll need
1309 * to bump the version number and revise the
1312 isc_log_write(dns_lctx
,
1313 ISC_LOGCATEGORY_GENERAL
,
1314 DNS_LOGMODULE_MASTERDUMP
,
1316 "dumping master file in raw "
1317 "format: stdtime is not 32bits");
1321 isc_buffer_putuint32(&buffer
, now32
);
1322 INSIST(isc_buffer_usedlength(&buffer
) <=
1324 result
= isc_stdio_write(buffer
.base
, 1,
1325 isc_buffer_usedlength(&buffer
),
1327 if (result
!= ISC_R_SUCCESS
)
1329 isc_buffer_clear(&buffer
);
1335 result
= dns_dbiterator_first(dctx
->dbiter
);
1336 dctx
->first
= ISC_FALSE
;
1338 result
= ISC_R_SUCCESS
;
1340 nodes
= dctx
->nodes
;
1341 isc_time_now(&start
);
1342 while (result
== ISC_R_SUCCESS
&& (dctx
->nodes
== 0 || nodes
--)) {
1343 dns_rdatasetiter_t
*rdsiter
= NULL
;
1344 dns_dbnode_t
*node
= NULL
;
1346 result
= dns_dbiterator_current(dctx
->dbiter
, &node
, name
);
1347 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_NEWORIGIN
)
1349 if (result
== DNS_R_NEWORIGIN
) {
1350 dns_name_t
*origin
=
1351 dns_fixedname_name(&dctx
->tctx
.origin_fixname
);
1352 result
= dns_dbiterator_origin(dctx
->dbiter
, origin
);
1353 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1354 if ((dctx
->tctx
.style
.flags
& DNS_STYLEFLAG_REL_DATA
) != 0)
1355 dctx
->tctx
.origin
= origin
;
1356 dctx
->tctx
.neworigin
= origin
;
1358 result
= dns_db_allrdatasets(dctx
->db
, node
, dctx
->version
,
1359 dctx
->now
, &rdsiter
);
1360 if (result
!= ISC_R_SUCCESS
) {
1361 dns_db_detachnode(dctx
->db
, &node
);
1364 result
= (dctx
->dumpsets
)(dctx
->mctx
, name
, rdsiter
,
1365 &dctx
->tctx
, &buffer
, dctx
->f
);
1366 dns_rdatasetiter_destroy(&rdsiter
);
1367 if (result
!= ISC_R_SUCCESS
) {
1368 dns_db_detachnode(dctx
->db
, &node
);
1371 dns_db_detachnode(dctx
->db
, &node
);
1372 result
= dns_dbiterator_next(dctx
->dbiter
);
1376 * Work out how many nodes can be written in the time between
1377 * two requests to the nameserver. Smooth the resulting number and
1378 * use it as a estimate for the number of nodes to be written in the
1381 if (dctx
->nodes
!= 0 && result
== ISC_R_SUCCESS
) {
1382 unsigned int pps
= dns_pps
; /* packets per second */
1383 unsigned int interval
;
1390 interval
= 1000000 / pps
; /* interval in usecs */
1393 usecs
= isc_time_microdiff(&end
, &start
);
1395 dctx
->nodes
= dctx
->nodes
* 2;
1396 if (dctx
->nodes
> 1000)
1399 nodes
= dctx
->nodes
* interval
;
1400 nodes
/= (unsigned int)usecs
;
1403 else if (nodes
> 1000)
1406 /* Smooth and assign. */
1407 dctx
->nodes
= (nodes
+ dctx
->nodes
* 7) / 8;
1409 isc_log_write(dns_lctx
, ISC_LOGCATEGORY_GENERAL
,
1410 DNS_LOGMODULE_MASTERDUMP
,
1412 "dumptostreaminc(%p) new nodes -> %d\n",
1415 result
= DNS_R_CONTINUE
;
1416 } else if (result
== ISC_R_NOMORE
)
1417 result
= ISC_R_SUCCESS
;
1419 RUNTIME_CHECK(dns_dbiterator_pause(dctx
->dbiter
) == ISC_R_SUCCESS
);
1420 isc_mem_put(dctx
->mctx
, buffer
.base
, buffer
.length
);
1425 dns_master_dumptostreaminc(isc_mem_t
*mctx
, dns_db_t
*db
,
1426 dns_dbversion_t
*version
,
1427 const dns_master_style_t
*style
,
1428 FILE *f
, isc_task_t
*task
,
1429 dns_dumpdonefunc_t done
, void *done_arg
,
1430 dns_dumpctx_t
**dctxp
)
1432 dns_dumpctx_t
*dctx
= NULL
;
1433 isc_result_t result
;
1435 REQUIRE(task
!= NULL
);
1437 REQUIRE(done
!= NULL
);
1439 result
= dumpctx_create(mctx
, db
, version
, style
, f
, &dctx
,
1440 dns_masterformat_text
);
1441 if (result
!= ISC_R_SUCCESS
)
1443 isc_task_attach(task
, &dctx
->task
);
1445 dctx
->done_arg
= done_arg
;
1448 result
= task_send(dctx
);
1449 if (result
== ISC_R_SUCCESS
) {
1450 dns_dumpctx_attach(dctx
, dctxp
);
1451 return (DNS_R_CONTINUE
);
1454 dns_dumpctx_detach(&dctx
);
1459 * Dump an entire database into a master file.
1462 dns_master_dumptostream(isc_mem_t
*mctx
, dns_db_t
*db
,
1463 dns_dbversion_t
*version
,
1464 const dns_master_style_t
*style
,
1467 return (dns_master_dumptostream2(mctx
, db
, version
, style
,
1468 dns_masterformat_text
, f
));
1472 dns_master_dumptostream2(isc_mem_t
*mctx
, dns_db_t
*db
,
1473 dns_dbversion_t
*version
,
1474 const dns_master_style_t
*style
,
1475 dns_masterformat_t format
, FILE *f
)
1477 dns_dumpctx_t
*dctx
= NULL
;
1478 isc_result_t result
;
1480 result
= dumpctx_create(mctx
, db
, version
, style
, f
, &dctx
, format
);
1481 if (result
!= ISC_R_SUCCESS
)
1484 result
= dumptostreaminc(dctx
);
1485 INSIST(result
!= DNS_R_CONTINUE
);
1486 dns_dumpctx_detach(&dctx
);
1491 opentmp(isc_mem_t
*mctx
, const char *file
, char **tempp
, FILE **fp
) {
1493 isc_result_t result
;
1494 char *tempname
= NULL
;
1497 tempnamelen
= strlen(file
) + 20;
1498 tempname
= isc_mem_allocate(mctx
, tempnamelen
);
1499 if (tempname
== NULL
)
1500 return (ISC_R_NOMEMORY
);
1502 result
= isc_file_mktemplate(file
, tempname
, tempnamelen
);
1503 if (result
!= ISC_R_SUCCESS
)
1506 result
= isc_file_openunique(tempname
, &f
);
1507 if (result
!= ISC_R_SUCCESS
) {
1508 isc_log_write(dns_lctx
, ISC_LOGCATEGORY_GENERAL
,
1509 DNS_LOGMODULE_MASTERDUMP
, ISC_LOG_ERROR
,
1510 "dumping master file: %s: open: %s",
1511 tempname
, isc_result_totext(result
));
1516 return (ISC_R_SUCCESS
);
1519 isc_mem_free(mctx
, tempname
);
1524 dns_master_dumpinc(isc_mem_t
*mctx
, dns_db_t
*db
, dns_dbversion_t
*version
,
1525 const dns_master_style_t
*style
, const char *filename
,
1526 isc_task_t
*task
, dns_dumpdonefunc_t done
, void *done_arg
,
1527 dns_dumpctx_t
**dctxp
)
1529 return (dns_master_dumpinc2(mctx
, db
, version
, style
, filename
, task
,
1530 done
, done_arg
, dctxp
,
1531 dns_masterformat_text
));
1535 dns_master_dumpinc2(isc_mem_t
*mctx
, dns_db_t
*db
, dns_dbversion_t
*version
,
1536 const dns_master_style_t
*style
, const char *filename
,
1537 isc_task_t
*task
, dns_dumpdonefunc_t done
, void *done_arg
,
1538 dns_dumpctx_t
**dctxp
, dns_masterformat_t format
)
1541 isc_result_t result
;
1542 char *tempname
= NULL
;
1544 dns_dumpctx_t
*dctx
= NULL
;
1546 file
= isc_mem_strdup(mctx
, filename
);
1548 return (ISC_R_NOMEMORY
);
1550 result
= opentmp(mctx
, filename
, &tempname
, &f
);
1551 if (result
!= ISC_R_SUCCESS
)
1554 result
= dumpctx_create(mctx
, db
, version
, style
, f
, &dctx
, format
);
1555 if (result
!= ISC_R_SUCCESS
) {
1556 (void)isc_stdio_close(f
);
1557 (void)isc_file_remove(tempname
);
1561 isc_task_attach(task
, &dctx
->task
);
1563 dctx
->done_arg
= done_arg
;
1567 dctx
->tmpfile
= tempname
;
1570 result
= task_send(dctx
);
1571 if (result
== ISC_R_SUCCESS
) {
1572 dns_dumpctx_attach(dctx
, dctxp
);
1573 return (DNS_R_CONTINUE
);
1578 dns_dumpctx_detach(&dctx
);
1580 isc_mem_free(mctx
, file
);
1581 if (tempname
!= NULL
)
1582 isc_mem_free(mctx
, tempname
);
1587 dns_master_dump(isc_mem_t
*mctx
, dns_db_t
*db
, dns_dbversion_t
*version
,
1588 const dns_master_style_t
*style
, const char *filename
)
1590 return (dns_master_dump2(mctx
, db
, version
, style
, filename
,
1591 dns_masterformat_text
));
1595 dns_master_dump2(isc_mem_t
*mctx
, dns_db_t
*db
, dns_dbversion_t
*version
,
1596 const dns_master_style_t
*style
, const char *filename
,
1597 dns_masterformat_t format
)
1600 isc_result_t result
;
1602 dns_dumpctx_t
*dctx
= NULL
;
1604 result
= opentmp(mctx
, filename
, &tempname
, &f
);
1605 if (result
!= ISC_R_SUCCESS
)
1608 result
= dumpctx_create(mctx
, db
, version
, style
, f
, &dctx
, format
);
1609 if (result
!= ISC_R_SUCCESS
)
1612 result
= dumptostreaminc(dctx
);
1613 INSIST(result
!= DNS_R_CONTINUE
);
1614 dns_dumpctx_detach(&dctx
);
1616 result
= closeandrename(f
, result
, tempname
, filename
);
1619 isc_mem_free(mctx
, tempname
);
1624 * Dump a database node into a master file.
1625 * XXX: this function assumes the text format.
1628 dns_master_dumpnodetostream(isc_mem_t
*mctx
, dns_db_t
*db
,
1629 dns_dbversion_t
*version
,
1630 dns_dbnode_t
*node
, dns_name_t
*name
,
1631 const dns_master_style_t
*style
,
1634 isc_result_t result
;
1635 isc_buffer_t buffer
;
1638 dns_totext_ctx_t ctx
;
1639 dns_rdatasetiter_t
*rdsiter
= NULL
;
1641 result
= totext_ctx_init(style
, &ctx
);
1642 if (result
!= ISC_R_SUCCESS
) {
1643 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
1644 "could not set master file style");
1645 return (ISC_R_UNEXPECTED
);
1648 isc_stdtime_get(&now
);
1650 bufmem
= isc_mem_get(mctx
, initial_buffer_length
);
1652 return (ISC_R_NOMEMORY
);
1654 isc_buffer_init(&buffer
, bufmem
, initial_buffer_length
);
1656 result
= dns_db_allrdatasets(db
, node
, version
, now
, &rdsiter
);
1657 if (result
!= ISC_R_SUCCESS
)
1659 result
= dump_rdatasets_text(mctx
, name
, rdsiter
, &ctx
, &buffer
, f
);
1660 if (result
!= ISC_R_SUCCESS
)
1662 dns_rdatasetiter_destroy(&rdsiter
);
1664 result
= ISC_R_SUCCESS
;
1667 isc_mem_put(mctx
, buffer
.base
, buffer
.length
);
1672 dns_master_dumpnode(isc_mem_t
*mctx
, dns_db_t
*db
, dns_dbversion_t
*version
,
1673 dns_dbnode_t
*node
, dns_name_t
*name
,
1674 const dns_master_style_t
*style
, const char *filename
)
1677 isc_result_t result
;
1679 result
= isc_stdio_open(filename
, "w", &f
);
1680 if (result
!= ISC_R_SUCCESS
) {
1681 isc_log_write(dns_lctx
, ISC_LOGCATEGORY_GENERAL
,
1682 DNS_LOGMODULE_MASTERDUMP
, ISC_LOG_ERROR
,
1683 "dumping node to file: %s: open: %s", filename
,
1684 isc_result_totext(result
));
1685 return (ISC_R_UNEXPECTED
);
1688 result
= dns_master_dumpnodetostream(mctx
, db
, version
, node
, name
,
1691 result
= isc_stdio_close(f
);
1692 if (result
!= ISC_R_SUCCESS
) {
1693 isc_log_write(dns_lctx
, ISC_LOGCATEGORY_GENERAL
,
1694 DNS_LOGMODULE_MASTERDUMP
, ISC_LOG_ERROR
,
1695 "dumping master file: %s: close: %s", filename
,
1696 isc_result_totext(result
));
1697 return (ISC_R_UNEXPECTED
);
1704 dns_master_stylecreate(dns_master_style_t
**stylep
, unsigned int flags
,
1705 unsigned int ttl_column
, unsigned int class_column
,
1706 unsigned int type_column
, unsigned int rdata_column
,
1707 unsigned int line_length
, unsigned int tab_width
,
1710 dns_master_style_t
*style
;
1712 REQUIRE(stylep
!= NULL
&& *stylep
== NULL
);
1713 style
= isc_mem_get(mctx
, sizeof(*style
));
1715 return (ISC_R_NOMEMORY
);
1717 style
->flags
= flags
;
1718 style
->ttl_column
= ttl_column
;
1719 style
->class_column
= class_column
;
1720 style
->type_column
= type_column
;
1721 style
->rdata_column
= rdata_column
;
1722 style
->line_length
= line_length
;
1723 style
->tab_width
= tab_width
;
1726 return (ISC_R_SUCCESS
);
1730 dns_master_styledestroy(dns_master_style_t
**stylep
, isc_mem_t
*mctx
) {
1731 dns_master_style_t
*style
;
1733 REQUIRE(stylep
!= NULL
&& *stylep
!= NULL
);
1736 isc_mem_put(mctx
, style
, sizeof(*style
));