xref: /minix3/external/bsd/bind/dist/lib/dns/masterdump.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: masterdump.c,v 1.11 2015/07/08 17:28:58 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004-2009, 2011-2015  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2003  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek /*! \file */
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <config.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #include <stdlib.h>
27*00b67f09SDavid van Moolenbroek 
28*00b67f09SDavid van Moolenbroek #include <isc/event.h>
29*00b67f09SDavid van Moolenbroek #include <isc/file.h>
30*00b67f09SDavid van Moolenbroek #include <isc/magic.h>
31*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
32*00b67f09SDavid van Moolenbroek #include <isc/print.h>
33*00b67f09SDavid van Moolenbroek #include <isc/stdio.h>
34*00b67f09SDavid van Moolenbroek #include <isc/string.h>
35*00b67f09SDavid van Moolenbroek #include <isc/task.h>
36*00b67f09SDavid van Moolenbroek #include <isc/time.h>
37*00b67f09SDavid van Moolenbroek #include <isc/util.h>
38*00b67f09SDavid van Moolenbroek 
39*00b67f09SDavid van Moolenbroek #include <dns/db.h>
40*00b67f09SDavid van Moolenbroek #include <dns/dbiterator.h>
41*00b67f09SDavid van Moolenbroek #include <dns/events.h>
42*00b67f09SDavid van Moolenbroek #include <dns/fixedname.h>
43*00b67f09SDavid van Moolenbroek #include <dns/lib.h>
44*00b67f09SDavid van Moolenbroek #include <dns/log.h>
45*00b67f09SDavid van Moolenbroek #include <dns/master.h>
46*00b67f09SDavid van Moolenbroek #include <dns/masterdump.h>
47*00b67f09SDavid van Moolenbroek #include <dns/ncache.h>
48*00b67f09SDavid van Moolenbroek #include <dns/rdata.h>
49*00b67f09SDavid van Moolenbroek #include <dns/rdataclass.h>
50*00b67f09SDavid van Moolenbroek #include <dns/rdataset.h>
51*00b67f09SDavid van Moolenbroek #include <dns/rdatasetiter.h>
52*00b67f09SDavid van Moolenbroek #include <dns/rdatatype.h>
53*00b67f09SDavid van Moolenbroek #include <dns/result.h>
54*00b67f09SDavid van Moolenbroek #include <dns/time.h>
55*00b67f09SDavid van Moolenbroek #include <dns/ttl.h>
56*00b67f09SDavid van Moolenbroek 
57*00b67f09SDavid van Moolenbroek #define DNS_DCTX_MAGIC		ISC_MAGIC('D', 'c', 't', 'x')
58*00b67f09SDavid van Moolenbroek #define DNS_DCTX_VALID(d)	ISC_MAGIC_VALID(d, DNS_DCTX_MAGIC)
59*00b67f09SDavid van Moolenbroek 
60*00b67f09SDavid van Moolenbroek #define RETERR(x) do { \
61*00b67f09SDavid van Moolenbroek 	isc_result_t _r = (x); \
62*00b67f09SDavid van Moolenbroek 	if (_r != ISC_R_SUCCESS) \
63*00b67f09SDavid van Moolenbroek 		return (_r); \
64*00b67f09SDavid van Moolenbroek 	} while (/*CONSTCOND*/0)
65*00b67f09SDavid van Moolenbroek 
66*00b67f09SDavid van Moolenbroek #define CHECK(x) do { \
67*00b67f09SDavid van Moolenbroek 	if ((x) != ISC_R_SUCCESS) \
68*00b67f09SDavid van Moolenbroek 		goto cleanup; \
69*00b67f09SDavid van Moolenbroek 	} while (/*CONSTCOND*/0)
70*00b67f09SDavid van Moolenbroek 
71*00b67f09SDavid van Moolenbroek struct dns_master_style {
72*00b67f09SDavid van Moolenbroek 	unsigned int flags;		/* DNS_STYLEFLAG_* */
73*00b67f09SDavid van Moolenbroek 	unsigned int ttl_column;
74*00b67f09SDavid van Moolenbroek 	unsigned int class_column;
75*00b67f09SDavid van Moolenbroek 	unsigned int type_column;
76*00b67f09SDavid van Moolenbroek 	unsigned int rdata_column;
77*00b67f09SDavid van Moolenbroek 	unsigned int line_length;
78*00b67f09SDavid van Moolenbroek 	unsigned int tab_width;
79*00b67f09SDavid van Moolenbroek 	unsigned int split_width;
80*00b67f09SDavid van Moolenbroek };
81*00b67f09SDavid van Moolenbroek 
82*00b67f09SDavid van Moolenbroek /*%
83*00b67f09SDavid van Moolenbroek  * The maximum length of the newline+indentation that is output
84*00b67f09SDavid van Moolenbroek  * when inserting a line break in an RR.  This effectively puts an
85*00b67f09SDavid van Moolenbroek  * upper limits on the value of "rdata_column", because if it is
86*00b67f09SDavid van Moolenbroek  * very large, the tabs and spaces needed to reach it will not fit.
87*00b67f09SDavid van Moolenbroek  */
88*00b67f09SDavid van Moolenbroek #define DNS_TOTEXT_LINEBREAK_MAXLEN 100
89*00b67f09SDavid van Moolenbroek 
90*00b67f09SDavid van Moolenbroek /*%
91*00b67f09SDavid van Moolenbroek  * Context structure for a masterfile dump in progress.
92*00b67f09SDavid van Moolenbroek  */
93*00b67f09SDavid van Moolenbroek typedef struct dns_totext_ctx {
94*00b67f09SDavid van Moolenbroek 	dns_master_style_t	style;
95*00b67f09SDavid van Moolenbroek 	isc_boolean_t 		class_printed;
96*00b67f09SDavid van Moolenbroek 	char *			linebreak;
97*00b67f09SDavid van Moolenbroek 	char 			linebreak_buf[DNS_TOTEXT_LINEBREAK_MAXLEN];
98*00b67f09SDavid van Moolenbroek 	dns_name_t *		origin;
99*00b67f09SDavid van Moolenbroek 	dns_name_t *		neworigin;
100*00b67f09SDavid van Moolenbroek 	dns_fixedname_t		origin_fixname;
101*00b67f09SDavid van Moolenbroek 	isc_uint32_t 		current_ttl;
102*00b67f09SDavid van Moolenbroek 	isc_boolean_t 		current_ttl_valid;
103*00b67f09SDavid van Moolenbroek } dns_totext_ctx_t;
104*00b67f09SDavid van Moolenbroek 
105*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
106*00b67f09SDavid van Moolenbroek dns_master_style_keyzone = {
107*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_OMIT_OWNER |
108*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_OMIT_CLASS |
109*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_REL_OWNER |
110*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_REL_DATA |
111*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_OMIT_TTL |
112*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_TTL |
113*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_COMMENT |
114*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_RRCOMMENT |
115*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_MULTILINE |
116*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_KEYDATA,
117*00b67f09SDavid van Moolenbroek 	24, 24, 24, 32, 80, 8, UINT_MAX
118*00b67f09SDavid van Moolenbroek };
119*00b67f09SDavid van Moolenbroek 
120*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
121*00b67f09SDavid van Moolenbroek dns_master_style_default = {
122*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_OMIT_OWNER |
123*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_OMIT_CLASS |
124*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_REL_OWNER |
125*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_REL_DATA |
126*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_OMIT_TTL |
127*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_TTL |
128*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_COMMENT |
129*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_RRCOMMENT |
130*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_MULTILINE,
131*00b67f09SDavid van Moolenbroek 	24, 24, 24, 32, 80, 8, UINT_MAX
132*00b67f09SDavid van Moolenbroek };
133*00b67f09SDavid van Moolenbroek 
134*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
135*00b67f09SDavid van Moolenbroek dns_master_style_full = {
136*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_COMMENT |
137*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_RESIGN,
138*00b67f09SDavid van Moolenbroek 	46, 46, 46, 64, 120, 8, UINT_MAX
139*00b67f09SDavid van Moolenbroek };
140*00b67f09SDavid van Moolenbroek 
141*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
142*00b67f09SDavid van Moolenbroek dns_master_style_explicitttl = {
143*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_OMIT_OWNER |
144*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_OMIT_CLASS |
145*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_REL_OWNER |
146*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_REL_DATA |
147*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_COMMENT |
148*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_RRCOMMENT |
149*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_MULTILINE,
150*00b67f09SDavid van Moolenbroek 	24, 32, 32, 40, 80, 8, UINT_MAX
151*00b67f09SDavid van Moolenbroek };
152*00b67f09SDavid van Moolenbroek 
153*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
154*00b67f09SDavid van Moolenbroek dns_master_style_cache = {
155*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_OMIT_OWNER |
156*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_OMIT_CLASS |
157*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_MULTILINE |
158*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_RRCOMMENT |
159*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_TRUST |
160*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_NCACHE,
161*00b67f09SDavid van Moolenbroek 	24, 32, 32, 40, 80, 8, UINT_MAX
162*00b67f09SDavid van Moolenbroek };
163*00b67f09SDavid van Moolenbroek 
164*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
165*00b67f09SDavid van Moolenbroek dns_master_style_simple = {
166*00b67f09SDavid van Moolenbroek 	0,
167*00b67f09SDavid van Moolenbroek 	24, 32, 32, 40, 80, 8, UINT_MAX
168*00b67f09SDavid van Moolenbroek };
169*00b67f09SDavid van Moolenbroek 
170*00b67f09SDavid van Moolenbroek /*%
171*00b67f09SDavid van Moolenbroek  * A style suitable for dns_rdataset_totext().
172*00b67f09SDavid van Moolenbroek  */
173*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
174*00b67f09SDavid van Moolenbroek dns_master_style_debug = {
175*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_REL_OWNER,
176*00b67f09SDavid van Moolenbroek 	24, 32, 40, 48, 80, 8, UINT_MAX
177*00b67f09SDavid van Moolenbroek };
178*00b67f09SDavid van Moolenbroek 
179*00b67f09SDavid van Moolenbroek /*%
180*00b67f09SDavid van Moolenbroek  * Similar, but with each line commented out.
181*00b67f09SDavid van Moolenbroek  */
182*00b67f09SDavid van Moolenbroek LIBDNS_EXTERNAL_DATA const dns_master_style_t
183*00b67f09SDavid van Moolenbroek dns_master_style_comment = {
184*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_REL_OWNER |
185*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_MULTILINE |
186*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_RRCOMMENT |
187*00b67f09SDavid van Moolenbroek 	DNS_STYLEFLAG_COMMENTDATA,
188*00b67f09SDavid van Moolenbroek 	24, 32, 40, 48, 80, 8, UINT_MAX
189*00b67f09SDavid van Moolenbroek };
190*00b67f09SDavid van Moolenbroek 
191*00b67f09SDavid van Moolenbroek 
192*00b67f09SDavid van Moolenbroek #define N_SPACES 10
193*00b67f09SDavid van Moolenbroek static char spaces[N_SPACES+1] = "          ";
194*00b67f09SDavid van Moolenbroek 
195*00b67f09SDavid van Moolenbroek #define N_TABS 10
196*00b67f09SDavid van Moolenbroek static char tabs[N_TABS+1] = "\t\t\t\t\t\t\t\t\t\t";
197*00b67f09SDavid van Moolenbroek 
198*00b67f09SDavid van Moolenbroek struct dns_dumpctx {
199*00b67f09SDavid van Moolenbroek 	unsigned int		magic;
200*00b67f09SDavid van Moolenbroek 	isc_mem_t		*mctx;
201*00b67f09SDavid van Moolenbroek 	isc_mutex_t		lock;
202*00b67f09SDavid van Moolenbroek 	unsigned int		references;
203*00b67f09SDavid van Moolenbroek 	isc_boolean_t		canceled;
204*00b67f09SDavid van Moolenbroek 	isc_boolean_t		first;
205*00b67f09SDavid van Moolenbroek 	isc_boolean_t		do_date;
206*00b67f09SDavid van Moolenbroek 	isc_stdtime_t		now;
207*00b67f09SDavid van Moolenbroek 	FILE			*f;
208*00b67f09SDavid van Moolenbroek 	dns_db_t		*db;
209*00b67f09SDavid van Moolenbroek 	dns_dbversion_t		*version;
210*00b67f09SDavid van Moolenbroek 	dns_dbiterator_t	*dbiter;
211*00b67f09SDavid van Moolenbroek 	dns_totext_ctx_t	tctx;
212*00b67f09SDavid van Moolenbroek 	isc_task_t		*task;
213*00b67f09SDavid van Moolenbroek 	dns_dumpdonefunc_t	done;
214*00b67f09SDavid van Moolenbroek 	void			*done_arg;
215*00b67f09SDavid van Moolenbroek 	unsigned int		nodes;
216*00b67f09SDavid van Moolenbroek 	/* dns_master_dumpinc() */
217*00b67f09SDavid van Moolenbroek 	char			*file;
218*00b67f09SDavid van Moolenbroek 	char 			*tmpfile;
219*00b67f09SDavid van Moolenbroek 	dns_masterformat_t	format;
220*00b67f09SDavid van Moolenbroek 	dns_masterrawheader_t	header;
221*00b67f09SDavid van Moolenbroek 	isc_result_t		(*dumpsets)(isc_mem_t *mctx, dns_name_t *name,
222*00b67f09SDavid van Moolenbroek 					    dns_rdatasetiter_t *rdsiter,
223*00b67f09SDavid van Moolenbroek 					    dns_totext_ctx_t *ctx,
224*00b67f09SDavid van Moolenbroek 					    isc_buffer_t *buffer, FILE *f);
225*00b67f09SDavid van Moolenbroek };
226*00b67f09SDavid van Moolenbroek 
227*00b67f09SDavid van Moolenbroek #define NXDOMAIN(x) (((x)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
228*00b67f09SDavid van Moolenbroek 
229*00b67f09SDavid van Moolenbroek /*%
230*00b67f09SDavid van Moolenbroek  * Output tabs and spaces to go from column '*current' to
231*00b67f09SDavid van Moolenbroek  * column 'to', and update '*current' to reflect the new
232*00b67f09SDavid van Moolenbroek  * current column.
233*00b67f09SDavid van Moolenbroek  */
234*00b67f09SDavid van Moolenbroek static isc_result_t
indent(unsigned int * current,unsigned int to,int tabwidth,isc_buffer_t * target)235*00b67f09SDavid van Moolenbroek indent(unsigned int *current, unsigned int to, int tabwidth,
236*00b67f09SDavid van Moolenbroek        isc_buffer_t *target)
237*00b67f09SDavid van Moolenbroek {
238*00b67f09SDavid van Moolenbroek 	isc_region_t r;
239*00b67f09SDavid van Moolenbroek 	unsigned char *p;
240*00b67f09SDavid van Moolenbroek 	unsigned int from;
241*00b67f09SDavid van Moolenbroek 	int ntabs, nspaces, t;
242*00b67f09SDavid van Moolenbroek 
243*00b67f09SDavid van Moolenbroek 	from = *current;
244*00b67f09SDavid van Moolenbroek 
245*00b67f09SDavid van Moolenbroek 	if (to < from + 1)
246*00b67f09SDavid van Moolenbroek 		to = from + 1;
247*00b67f09SDavid van Moolenbroek 
248*00b67f09SDavid van Moolenbroek 	ntabs = to / tabwidth - from / tabwidth;
249*00b67f09SDavid van Moolenbroek 	if (ntabs < 0)
250*00b67f09SDavid van Moolenbroek 		ntabs = 0;
251*00b67f09SDavid van Moolenbroek 
252*00b67f09SDavid van Moolenbroek 	if (ntabs > 0) {
253*00b67f09SDavid van Moolenbroek 		isc_buffer_availableregion(target, &r);
254*00b67f09SDavid van Moolenbroek 		if (r.length < (unsigned) ntabs)
255*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOSPACE);
256*00b67f09SDavid van Moolenbroek 		p = r.base;
257*00b67f09SDavid van Moolenbroek 
258*00b67f09SDavid van Moolenbroek 		t = ntabs;
259*00b67f09SDavid van Moolenbroek 		while (t) {
260*00b67f09SDavid van Moolenbroek 			int n = t;
261*00b67f09SDavid van Moolenbroek 			if (n > N_TABS)
262*00b67f09SDavid van Moolenbroek 				n = N_TABS;
263*00b67f09SDavid van Moolenbroek 			memmove(p, tabs, n);
264*00b67f09SDavid van Moolenbroek 			p += n;
265*00b67f09SDavid van Moolenbroek 			t -= n;
266*00b67f09SDavid van Moolenbroek 		}
267*00b67f09SDavid van Moolenbroek 		isc_buffer_add(target, ntabs);
268*00b67f09SDavid van Moolenbroek 		from = (to / tabwidth) * tabwidth;
269*00b67f09SDavid van Moolenbroek 	}
270*00b67f09SDavid van Moolenbroek 
271*00b67f09SDavid van Moolenbroek 	nspaces = to - from;
272*00b67f09SDavid van Moolenbroek 	INSIST(nspaces >= 0);
273*00b67f09SDavid van Moolenbroek 
274*00b67f09SDavid van Moolenbroek 	isc_buffer_availableregion(target, &r);
275*00b67f09SDavid van Moolenbroek 	if (r.length < (unsigned) nspaces)
276*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
277*00b67f09SDavid van Moolenbroek 	p = r.base;
278*00b67f09SDavid van Moolenbroek 
279*00b67f09SDavid van Moolenbroek 	t = nspaces;
280*00b67f09SDavid van Moolenbroek 	while (t) {
281*00b67f09SDavid van Moolenbroek 		int n = t;
282*00b67f09SDavid van Moolenbroek 		if (n > N_SPACES)
283*00b67f09SDavid van Moolenbroek 			n = N_SPACES;
284*00b67f09SDavid van Moolenbroek 		memmove(p, spaces, n);
285*00b67f09SDavid van Moolenbroek 		p += n;
286*00b67f09SDavid van Moolenbroek 		t -= n;
287*00b67f09SDavid van Moolenbroek 	}
288*00b67f09SDavid van Moolenbroek 	isc_buffer_add(target, nspaces);
289*00b67f09SDavid van Moolenbroek 
290*00b67f09SDavid van Moolenbroek 	*current = to;
291*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
292*00b67f09SDavid van Moolenbroek }
293*00b67f09SDavid van Moolenbroek 
294*00b67f09SDavid van Moolenbroek static isc_result_t
totext_ctx_init(const dns_master_style_t * style,dns_totext_ctx_t * ctx)295*00b67f09SDavid van Moolenbroek totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) {
296*00b67f09SDavid van Moolenbroek 	isc_result_t result;
297*00b67f09SDavid van Moolenbroek 
298*00b67f09SDavid van Moolenbroek 	REQUIRE(style->tab_width != 0);
299*00b67f09SDavid van Moolenbroek 
300*00b67f09SDavid van Moolenbroek 	ctx->style = *style;
301*00b67f09SDavid van Moolenbroek 	ctx->class_printed = ISC_FALSE;
302*00b67f09SDavid van Moolenbroek 
303*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&ctx->origin_fixname);
304*00b67f09SDavid van Moolenbroek 
305*00b67f09SDavid van Moolenbroek 	/*
306*00b67f09SDavid van Moolenbroek 	 * Set up the line break string if needed.
307*00b67f09SDavid van Moolenbroek 	 */
308*00b67f09SDavid van Moolenbroek 	if ((ctx->style.flags & DNS_STYLEFLAG_MULTILINE) != 0) {
309*00b67f09SDavid van Moolenbroek 		isc_buffer_t buf;
310*00b67f09SDavid van Moolenbroek 		isc_region_t r;
311*00b67f09SDavid van Moolenbroek 		unsigned int col = 0;
312*00b67f09SDavid van Moolenbroek 
313*00b67f09SDavid van Moolenbroek 		isc_buffer_init(&buf, ctx->linebreak_buf,
314*00b67f09SDavid van Moolenbroek 				sizeof(ctx->linebreak_buf));
315*00b67f09SDavid van Moolenbroek 
316*00b67f09SDavid van Moolenbroek 		isc_buffer_availableregion(&buf, &r);
317*00b67f09SDavid van Moolenbroek 		if (r.length < 1)
318*00b67f09SDavid van Moolenbroek 			return (DNS_R_TEXTTOOLONG);
319*00b67f09SDavid van Moolenbroek 		r.base[0] = '\n';
320*00b67f09SDavid van Moolenbroek 		isc_buffer_add(&buf, 1);
321*00b67f09SDavid van Moolenbroek 
322*00b67f09SDavid van Moolenbroek 		if ((ctx->style.flags & DNS_STYLEFLAG_COMMENTDATA) != 0) {
323*00b67f09SDavid van Moolenbroek 			isc_buffer_availableregion(&buf, &r);
324*00b67f09SDavid van Moolenbroek 			if (r.length < 1)
325*00b67f09SDavid van Moolenbroek 				return (DNS_R_TEXTTOOLONG);
326*00b67f09SDavid van Moolenbroek 			r.base[0] = ';';
327*00b67f09SDavid van Moolenbroek 			isc_buffer_add(&buf, 1);
328*00b67f09SDavid van Moolenbroek 		}
329*00b67f09SDavid van Moolenbroek 
330*00b67f09SDavid van Moolenbroek 		result = indent(&col, ctx->style.rdata_column,
331*00b67f09SDavid van Moolenbroek 				ctx->style.tab_width, &buf);
332*00b67f09SDavid van Moolenbroek 		/*
333*00b67f09SDavid van Moolenbroek 		 * Do not return ISC_R_NOSPACE if the line break string
334*00b67f09SDavid van Moolenbroek 		 * buffer is too small, because that would just make
335*00b67f09SDavid van Moolenbroek 		 * dump_rdataset() retry indefinitely with ever
336*00b67f09SDavid van Moolenbroek 		 * bigger target buffers.  That's a different buffer,
337*00b67f09SDavid van Moolenbroek 		 * so it won't help.  Use DNS_R_TEXTTOOLONG as a substitute.
338*00b67f09SDavid van Moolenbroek 		 */
339*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_NOSPACE)
340*00b67f09SDavid van Moolenbroek 			return (DNS_R_TEXTTOOLONG);
341*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
342*00b67f09SDavid van Moolenbroek 			return (result);
343*00b67f09SDavid van Moolenbroek 
344*00b67f09SDavid van Moolenbroek 		isc_buffer_availableregion(&buf, &r);
345*00b67f09SDavid van Moolenbroek 		if (r.length < 1)
346*00b67f09SDavid van Moolenbroek 			return (DNS_R_TEXTTOOLONG);
347*00b67f09SDavid van Moolenbroek 		r.base[0] = '\0';
348*00b67f09SDavid van Moolenbroek 		isc_buffer_add(&buf, 1);
349*00b67f09SDavid van Moolenbroek 		ctx->linebreak = ctx->linebreak_buf;
350*00b67f09SDavid van Moolenbroek 	} else {
351*00b67f09SDavid van Moolenbroek 		ctx->linebreak = NULL;
352*00b67f09SDavid van Moolenbroek 	}
353*00b67f09SDavid van Moolenbroek 
354*00b67f09SDavid van Moolenbroek 	ctx->origin = NULL;
355*00b67f09SDavid van Moolenbroek 	ctx->neworigin = NULL;
356*00b67f09SDavid van Moolenbroek 	ctx->current_ttl = 0;
357*00b67f09SDavid van Moolenbroek 	ctx->current_ttl_valid = ISC_FALSE;
358*00b67f09SDavid van Moolenbroek 
359*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
360*00b67f09SDavid van Moolenbroek }
361*00b67f09SDavid van Moolenbroek 
362*00b67f09SDavid van Moolenbroek #define INDENT_TO(col) \
363*00b67f09SDavid van Moolenbroek 	do { \
364*00b67f09SDavid van Moolenbroek 		 if ((result = indent(&column, ctx->style.col, \
365*00b67f09SDavid van Moolenbroek 				      ctx->style.tab_width, target)) \
366*00b67f09SDavid van Moolenbroek 		     != ISC_R_SUCCESS) \
367*00b67f09SDavid van Moolenbroek 			    return (result); \
368*00b67f09SDavid van Moolenbroek 	} while (/*CONSTCOND*/0)
369*00b67f09SDavid van Moolenbroek 
370*00b67f09SDavid van Moolenbroek 
371*00b67f09SDavid van Moolenbroek static isc_result_t
str_totext(const char * source,isc_buffer_t * target)372*00b67f09SDavid van Moolenbroek str_totext(const char *source, isc_buffer_t *target) {
373*00b67f09SDavid van Moolenbroek 	unsigned int l;
374*00b67f09SDavid van Moolenbroek 	isc_region_t region;
375*00b67f09SDavid van Moolenbroek 
376*00b67f09SDavid van Moolenbroek 	isc_buffer_availableregion(target, &region);
377*00b67f09SDavid van Moolenbroek 	l = strlen(source);
378*00b67f09SDavid van Moolenbroek 
379*00b67f09SDavid van Moolenbroek 	if (l > region.length)
380*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
381*00b67f09SDavid van Moolenbroek 
382*00b67f09SDavid van Moolenbroek 	memmove(region.base, source, l);
383*00b67f09SDavid van Moolenbroek 	isc_buffer_add(target, l);
384*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
385*00b67f09SDavid van Moolenbroek }
386*00b67f09SDavid van Moolenbroek 
387*00b67f09SDavid van Moolenbroek static isc_result_t
ncache_summary(dns_rdataset_t * rdataset,isc_boolean_t omit_final_dot,isc_buffer_t * target)388*00b67f09SDavid van Moolenbroek ncache_summary(dns_rdataset_t *rdataset, isc_boolean_t omit_final_dot,
389*00b67f09SDavid van Moolenbroek 	       isc_buffer_t *target)
390*00b67f09SDavid van Moolenbroek {
391*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
392*00b67f09SDavid van Moolenbroek 	dns_rdataset_t rds;
393*00b67f09SDavid van Moolenbroek 	dns_name_t name;
394*00b67f09SDavid van Moolenbroek 
395*00b67f09SDavid van Moolenbroek 	dns_rdataset_init(&rds);
396*00b67f09SDavid van Moolenbroek 	dns_name_init(&name, NULL);
397*00b67f09SDavid van Moolenbroek 
398*00b67f09SDavid van Moolenbroek 	do {
399*00b67f09SDavid van Moolenbroek 		dns_ncache_current(rdataset, &name, &rds);
400*00b67f09SDavid van Moolenbroek 		for (result = dns_rdataset_first(&rds);
401*00b67f09SDavid van Moolenbroek 		     result == ISC_R_SUCCESS;
402*00b67f09SDavid van Moolenbroek 		     result = dns_rdataset_next(&rds)) {
403*00b67f09SDavid van Moolenbroek 			CHECK(str_totext("; ", target));
404*00b67f09SDavid van Moolenbroek 			CHECK(dns_name_totext(&name, omit_final_dot, target));
405*00b67f09SDavid van Moolenbroek 			CHECK(str_totext(" ", target));
406*00b67f09SDavid van Moolenbroek 			CHECK(dns_rdatatype_totext(rds.type, target));
407*00b67f09SDavid van Moolenbroek 			if (rds.type == dns_rdatatype_rrsig) {
408*00b67f09SDavid van Moolenbroek 				CHECK(str_totext(" ", target));
409*00b67f09SDavid van Moolenbroek 				CHECK(dns_rdatatype_totext(rds.covers, target));
410*00b67f09SDavid van Moolenbroek 				CHECK(str_totext(" ...\n", target));
411*00b67f09SDavid van Moolenbroek 			} else {
412*00b67f09SDavid van Moolenbroek 				dns_rdata_t rdata = DNS_RDATA_INIT;
413*00b67f09SDavid van Moolenbroek 				dns_rdataset_current(&rds, &rdata);
414*00b67f09SDavid van Moolenbroek 				CHECK(str_totext(" ", target));
415*00b67f09SDavid van Moolenbroek 				CHECK(dns_rdata_tofmttext(&rdata, dns_rootname,
416*00b67f09SDavid van Moolenbroek 							  0, 0, 0, " ", target));
417*00b67f09SDavid van Moolenbroek 				CHECK(str_totext("\n", target));
418*00b67f09SDavid van Moolenbroek 			}
419*00b67f09SDavid van Moolenbroek 		}
420*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&rds);
421*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_next(rdataset);
422*00b67f09SDavid van Moolenbroek 	} while (result == ISC_R_SUCCESS);
423*00b67f09SDavid van Moolenbroek 
424*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_NOMORE)
425*00b67f09SDavid van Moolenbroek 		result = ISC_R_SUCCESS;
426*00b67f09SDavid van Moolenbroek  cleanup:
427*00b67f09SDavid van Moolenbroek 	if (dns_rdataset_isassociated(&rds))
428*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&rds);
429*00b67f09SDavid van Moolenbroek 
430*00b67f09SDavid van Moolenbroek 	return (result);
431*00b67f09SDavid van Moolenbroek }
432*00b67f09SDavid van Moolenbroek 
433*00b67f09SDavid van Moolenbroek /*
434*00b67f09SDavid van Moolenbroek  * Convert 'rdataset' to master file text format according to 'ctx',
435*00b67f09SDavid van Moolenbroek  * storing the result in 'target'.  If 'owner_name' is NULL, it
436*00b67f09SDavid van Moolenbroek  * is omitted; otherwise 'owner_name' must be valid and have at least
437*00b67f09SDavid van Moolenbroek  * one label.
438*00b67f09SDavid van Moolenbroek  */
439*00b67f09SDavid van Moolenbroek 
440*00b67f09SDavid van Moolenbroek static isc_result_t
rdataset_totext(dns_rdataset_t * rdataset,dns_name_t * owner_name,dns_totext_ctx_t * ctx,isc_boolean_t omit_final_dot,isc_buffer_t * target)441*00b67f09SDavid van Moolenbroek rdataset_totext(dns_rdataset_t *rdataset,
442*00b67f09SDavid van Moolenbroek 		dns_name_t *owner_name,
443*00b67f09SDavid van Moolenbroek 		dns_totext_ctx_t *ctx,
444*00b67f09SDavid van Moolenbroek 		isc_boolean_t omit_final_dot,
445*00b67f09SDavid van Moolenbroek 		isc_buffer_t *target)
446*00b67f09SDavid van Moolenbroek {
447*00b67f09SDavid van Moolenbroek 	isc_result_t result;
448*00b67f09SDavid van Moolenbroek 	unsigned int column;
449*00b67f09SDavid van Moolenbroek 	isc_boolean_t first = ISC_TRUE;
450*00b67f09SDavid van Moolenbroek 	isc_uint32_t current_ttl;
451*00b67f09SDavid van Moolenbroek 	isc_boolean_t current_ttl_valid;
452*00b67f09SDavid van Moolenbroek 	dns_rdatatype_t type;
453*00b67f09SDavid van Moolenbroek 	unsigned int type_start;
454*00b67f09SDavid van Moolenbroek 
455*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_RDATASET_VALID(rdataset));
456*00b67f09SDavid van Moolenbroek 
457*00b67f09SDavid van Moolenbroek 	rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
458*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(rdataset);
459*00b67f09SDavid van Moolenbroek 
460*00b67f09SDavid van Moolenbroek 	current_ttl = ctx->current_ttl;
461*00b67f09SDavid van Moolenbroek 	current_ttl_valid = ctx->current_ttl_valid;
462*00b67f09SDavid van Moolenbroek 
463*00b67f09SDavid van Moolenbroek 	while (result == ISC_R_SUCCESS) {
464*00b67f09SDavid van Moolenbroek 		column = 0;
465*00b67f09SDavid van Moolenbroek 
466*00b67f09SDavid van Moolenbroek 		/*
467*00b67f09SDavid van Moolenbroek 		 * Comment?
468*00b67f09SDavid van Moolenbroek 		 */
469*00b67f09SDavid van Moolenbroek 		if ((ctx->style.flags & DNS_STYLEFLAG_COMMENTDATA) != 0)
470*00b67f09SDavid van Moolenbroek 			RETERR(str_totext(";", target));
471*00b67f09SDavid van Moolenbroek 
472*00b67f09SDavid van Moolenbroek 		/*
473*00b67f09SDavid van Moolenbroek 		 * Owner name.
474*00b67f09SDavid van Moolenbroek 		 */
475*00b67f09SDavid van Moolenbroek 		if (owner_name != NULL &&
476*00b67f09SDavid van Moolenbroek 		    ! ((ctx->style.flags & DNS_STYLEFLAG_OMIT_OWNER) != 0 &&
477*00b67f09SDavid van Moolenbroek 		       !first))
478*00b67f09SDavid van Moolenbroek 		{
479*00b67f09SDavid van Moolenbroek 			unsigned int name_start = target->used;
480*00b67f09SDavid van Moolenbroek 			RETERR(dns_name_totext(owner_name,
481*00b67f09SDavid van Moolenbroek 					       omit_final_dot,
482*00b67f09SDavid van Moolenbroek 					       target));
483*00b67f09SDavid van Moolenbroek 			column += target->used - name_start;
484*00b67f09SDavid van Moolenbroek 		}
485*00b67f09SDavid van Moolenbroek 
486*00b67f09SDavid van Moolenbroek 		/*
487*00b67f09SDavid van Moolenbroek 		 * TTL.
488*00b67f09SDavid van Moolenbroek 		 */
489*00b67f09SDavid van Moolenbroek 		if ((ctx->style.flags & DNS_STYLEFLAG_NO_TTL) == 0 &&
490*00b67f09SDavid van Moolenbroek 		    !((ctx->style.flags & DNS_STYLEFLAG_OMIT_TTL) != 0 &&
491*00b67f09SDavid van Moolenbroek 		      current_ttl_valid &&
492*00b67f09SDavid van Moolenbroek 		      rdataset->ttl == current_ttl))
493*00b67f09SDavid van Moolenbroek 		{
494*00b67f09SDavid van Moolenbroek 			char ttlbuf[64];
495*00b67f09SDavid van Moolenbroek 			isc_region_t r;
496*00b67f09SDavid van Moolenbroek 			unsigned int length;
497*00b67f09SDavid van Moolenbroek 
498*00b67f09SDavid van Moolenbroek 			INDENT_TO(ttl_column);
499*00b67f09SDavid van Moolenbroek 			length = snprintf(ttlbuf, sizeof(ttlbuf), "%u",
500*00b67f09SDavid van Moolenbroek 					  rdataset->ttl);
501*00b67f09SDavid van Moolenbroek 			INSIST(length <= sizeof(ttlbuf));
502*00b67f09SDavid van Moolenbroek 			isc_buffer_availableregion(target, &r);
503*00b67f09SDavid van Moolenbroek 			if (r.length < length)
504*00b67f09SDavid van Moolenbroek 				return (ISC_R_NOSPACE);
505*00b67f09SDavid van Moolenbroek 			memmove(r.base, ttlbuf, length);
506*00b67f09SDavid van Moolenbroek 			isc_buffer_add(target, length);
507*00b67f09SDavid van Moolenbroek 			column += length;
508*00b67f09SDavid van Moolenbroek 
509*00b67f09SDavid van Moolenbroek 			/*
510*00b67f09SDavid van Moolenbroek 			 * If the $TTL directive is not in use, the TTL we
511*00b67f09SDavid van Moolenbroek 			 * just printed becomes the default for subsequent RRs.
512*00b67f09SDavid van Moolenbroek 			 */
513*00b67f09SDavid van Moolenbroek 			if ((ctx->style.flags & DNS_STYLEFLAG_TTL) == 0) {
514*00b67f09SDavid van Moolenbroek 				current_ttl = rdataset->ttl;
515*00b67f09SDavid van Moolenbroek 				current_ttl_valid = ISC_TRUE;
516*00b67f09SDavid van Moolenbroek 			}
517*00b67f09SDavid van Moolenbroek 		}
518*00b67f09SDavid van Moolenbroek 
519*00b67f09SDavid van Moolenbroek 		/*
520*00b67f09SDavid van Moolenbroek 		 * Class.
521*00b67f09SDavid van Moolenbroek 		 */
522*00b67f09SDavid van Moolenbroek 		if ((ctx->style.flags & DNS_STYLEFLAG_NO_CLASS) == 0 &&
523*00b67f09SDavid van Moolenbroek 		    ((ctx->style.flags & DNS_STYLEFLAG_OMIT_CLASS) == 0 ||
524*00b67f09SDavid van Moolenbroek 		     ctx->class_printed == ISC_FALSE))
525*00b67f09SDavid van Moolenbroek 		{
526*00b67f09SDavid van Moolenbroek 			unsigned int class_start;
527*00b67f09SDavid van Moolenbroek 			INDENT_TO(class_column);
528*00b67f09SDavid van Moolenbroek 			class_start = target->used;
529*00b67f09SDavid van Moolenbroek 			result = dns_rdataclass_totext(rdataset->rdclass,
530*00b67f09SDavid van Moolenbroek 						       target);
531*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
532*00b67f09SDavid van Moolenbroek 				return (result);
533*00b67f09SDavid van Moolenbroek 			column += (target->used - class_start);
534*00b67f09SDavid van Moolenbroek 		}
535*00b67f09SDavid van Moolenbroek 
536*00b67f09SDavid van Moolenbroek 		/*
537*00b67f09SDavid van Moolenbroek 		 * Type.
538*00b67f09SDavid van Moolenbroek 		 */
539*00b67f09SDavid van Moolenbroek 
540*00b67f09SDavid van Moolenbroek 		if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
541*00b67f09SDavid van Moolenbroek 			type = rdataset->covers;
542*00b67f09SDavid van Moolenbroek 		} else {
543*00b67f09SDavid van Moolenbroek 			type = rdataset->type;
544*00b67f09SDavid van Moolenbroek 		}
545*00b67f09SDavid van Moolenbroek 
546*00b67f09SDavid van Moolenbroek 		INDENT_TO(type_column);
547*00b67f09SDavid van Moolenbroek 		type_start = target->used;
548*00b67f09SDavid van Moolenbroek 		if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
549*00b67f09SDavid van Moolenbroek 			RETERR(str_totext("\\-", target));
550*00b67f09SDavid van Moolenbroek 		switch (type) {
551*00b67f09SDavid van Moolenbroek 		case dns_rdatatype_keydata:
552*00b67f09SDavid van Moolenbroek #define KEYDATA "KEYDATA"
553*00b67f09SDavid van Moolenbroek 			if ((ctx->style.flags & DNS_STYLEFLAG_KEYDATA) != 0) {
554*00b67f09SDavid van Moolenbroek 				if (isc_buffer_availablelength(target) <
555*00b67f09SDavid van Moolenbroek 				    (sizeof(KEYDATA) - 1))
556*00b67f09SDavid van Moolenbroek 					return (ISC_R_NOSPACE);
557*00b67f09SDavid van Moolenbroek 				isc_buffer_putstr(target, KEYDATA);
558*00b67f09SDavid van Moolenbroek 				break;
559*00b67f09SDavid van Moolenbroek 			}
560*00b67f09SDavid van Moolenbroek 			/* FALLTHROUGH */
561*00b67f09SDavid van Moolenbroek 		default:
562*00b67f09SDavid van Moolenbroek 			result = dns_rdatatype_totext(type, target);
563*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
564*00b67f09SDavid van Moolenbroek 				return (result);
565*00b67f09SDavid van Moolenbroek 		}
566*00b67f09SDavid van Moolenbroek 		column += (target->used - type_start);
567*00b67f09SDavid van Moolenbroek 
568*00b67f09SDavid van Moolenbroek 		/*
569*00b67f09SDavid van Moolenbroek 		 * Rdata.
570*00b67f09SDavid van Moolenbroek 		 */
571*00b67f09SDavid van Moolenbroek 		INDENT_TO(rdata_column);
572*00b67f09SDavid van Moolenbroek 		if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
573*00b67f09SDavid van Moolenbroek 			if (NXDOMAIN(rdataset))
574*00b67f09SDavid van Moolenbroek 				RETERR(str_totext(";-$NXDOMAIN\n", target));
575*00b67f09SDavid van Moolenbroek 			else
576*00b67f09SDavid van Moolenbroek 				RETERR(str_totext(";-$NXRRSET\n", target));
577*00b67f09SDavid van Moolenbroek 			/*
578*00b67f09SDavid van Moolenbroek 			 * Print a summary of the cached records which make
579*00b67f09SDavid van Moolenbroek 			 * up the negative response.
580*00b67f09SDavid van Moolenbroek 			 */
581*00b67f09SDavid van Moolenbroek 			RETERR(ncache_summary(rdataset, omit_final_dot,
582*00b67f09SDavid van Moolenbroek 					      target));
583*00b67f09SDavid van Moolenbroek 			break;
584*00b67f09SDavid van Moolenbroek 		} else {
585*00b67f09SDavid van Moolenbroek 			dns_rdata_t rdata = DNS_RDATA_INIT;
586*00b67f09SDavid van Moolenbroek 			isc_region_t r;
587*00b67f09SDavid van Moolenbroek 
588*00b67f09SDavid van Moolenbroek 			dns_rdataset_current(rdataset, &rdata);
589*00b67f09SDavid van Moolenbroek 
590*00b67f09SDavid van Moolenbroek 			RETERR(dns_rdata_tofmttext(&rdata,
591*00b67f09SDavid van Moolenbroek 						   ctx->origin,
592*00b67f09SDavid van Moolenbroek 						   ctx->style.flags,
593*00b67f09SDavid van Moolenbroek 						   ctx->style.line_length -
594*00b67f09SDavid van Moolenbroek 						       ctx->style.rdata_column,
595*00b67f09SDavid van Moolenbroek 						   ctx->style.split_width,
596*00b67f09SDavid van Moolenbroek 						   ctx->linebreak,
597*00b67f09SDavid van Moolenbroek 						   target));
598*00b67f09SDavid van Moolenbroek 
599*00b67f09SDavid van Moolenbroek 			isc_buffer_availableregion(target, &r);
600*00b67f09SDavid van Moolenbroek 			if (r.length < 1)
601*00b67f09SDavid van Moolenbroek 				return (ISC_R_NOSPACE);
602*00b67f09SDavid van Moolenbroek 			r.base[0] = '\n';
603*00b67f09SDavid van Moolenbroek 			isc_buffer_add(target, 1);
604*00b67f09SDavid van Moolenbroek 		}
605*00b67f09SDavid van Moolenbroek 
606*00b67f09SDavid van Moolenbroek 		first = ISC_FALSE;
607*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_next(rdataset);
608*00b67f09SDavid van Moolenbroek 	}
609*00b67f09SDavid van Moolenbroek 
610*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_NOMORE)
611*00b67f09SDavid van Moolenbroek 		return (result);
612*00b67f09SDavid van Moolenbroek 
613*00b67f09SDavid van Moolenbroek 	/*
614*00b67f09SDavid van Moolenbroek 	 * Update the ctx state to reflect what we just printed.
615*00b67f09SDavid van Moolenbroek 	 * This is done last, only when we are sure we will return
616*00b67f09SDavid van Moolenbroek 	 * success, because this function may be called multiple
617*00b67f09SDavid van Moolenbroek 	 * times with increasing buffer sizes until it succeeds,
618*00b67f09SDavid van Moolenbroek 	 * and failed attempts must not update the state prematurely.
619*00b67f09SDavid van Moolenbroek 	 */
620*00b67f09SDavid van Moolenbroek 	ctx->class_printed = ISC_TRUE;
621*00b67f09SDavid van Moolenbroek 	ctx->current_ttl= current_ttl;
622*00b67f09SDavid van Moolenbroek 	ctx->current_ttl_valid = current_ttl_valid;
623*00b67f09SDavid van Moolenbroek 
624*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
625*00b67f09SDavid van Moolenbroek }
626*00b67f09SDavid van Moolenbroek 
627*00b67f09SDavid van Moolenbroek /*
628*00b67f09SDavid van Moolenbroek  * Print the name, type, and class of an empty rdataset,
629*00b67f09SDavid van Moolenbroek  * such as those used to represent the question section
630*00b67f09SDavid van Moolenbroek  * of a DNS message.
631*00b67f09SDavid van Moolenbroek  */
632*00b67f09SDavid van Moolenbroek static isc_result_t
question_totext(dns_rdataset_t * rdataset,dns_name_t * owner_name,dns_totext_ctx_t * ctx,isc_boolean_t omit_final_dot,isc_buffer_t * target)633*00b67f09SDavid van Moolenbroek question_totext(dns_rdataset_t *rdataset,
634*00b67f09SDavid van Moolenbroek 		dns_name_t *owner_name,
635*00b67f09SDavid van Moolenbroek 		dns_totext_ctx_t *ctx,
636*00b67f09SDavid van Moolenbroek 		isc_boolean_t omit_final_dot,
637*00b67f09SDavid van Moolenbroek 		isc_buffer_t *target)
638*00b67f09SDavid van Moolenbroek {
639*00b67f09SDavid van Moolenbroek 	unsigned int column;
640*00b67f09SDavid van Moolenbroek 	isc_result_t result;
641*00b67f09SDavid van Moolenbroek 	isc_region_t r;
642*00b67f09SDavid van Moolenbroek 
643*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_RDATASET_VALID(rdataset));
644*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(rdataset);
645*00b67f09SDavid van Moolenbroek 	REQUIRE(result == ISC_R_NOMORE);
646*00b67f09SDavid van Moolenbroek 
647*00b67f09SDavid van Moolenbroek 	column = 0;
648*00b67f09SDavid van Moolenbroek 
649*00b67f09SDavid van Moolenbroek 	/* Owner name */
650*00b67f09SDavid van Moolenbroek 	{
651*00b67f09SDavid van Moolenbroek 		unsigned int name_start = target->used;
652*00b67f09SDavid van Moolenbroek 		RETERR(dns_name_totext(owner_name,
653*00b67f09SDavid van Moolenbroek 				       omit_final_dot,
654*00b67f09SDavid van Moolenbroek 				       target));
655*00b67f09SDavid van Moolenbroek 		column += target->used - name_start;
656*00b67f09SDavid van Moolenbroek 	}
657*00b67f09SDavid van Moolenbroek 
658*00b67f09SDavid van Moolenbroek 	/* Class */
659*00b67f09SDavid van Moolenbroek 	{
660*00b67f09SDavid van Moolenbroek 		unsigned int class_start;
661*00b67f09SDavid van Moolenbroek 		INDENT_TO(class_column);
662*00b67f09SDavid van Moolenbroek 		class_start = target->used;
663*00b67f09SDavid van Moolenbroek 		result = dns_rdataclass_totext(rdataset->rdclass, target);
664*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
665*00b67f09SDavid van Moolenbroek 			return (result);
666*00b67f09SDavid van Moolenbroek 		column += (target->used - class_start);
667*00b67f09SDavid van Moolenbroek 	}
668*00b67f09SDavid van Moolenbroek 
669*00b67f09SDavid van Moolenbroek 	/* Type */
670*00b67f09SDavid van Moolenbroek 	{
671*00b67f09SDavid van Moolenbroek 		unsigned int type_start;
672*00b67f09SDavid van Moolenbroek 		INDENT_TO(type_column);
673*00b67f09SDavid van Moolenbroek 		type_start = target->used;
674*00b67f09SDavid van Moolenbroek 		result = dns_rdatatype_totext(rdataset->type, target);
675*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
676*00b67f09SDavid van Moolenbroek 			return (result);
677*00b67f09SDavid van Moolenbroek 		column += (target->used - type_start);
678*00b67f09SDavid van Moolenbroek 	}
679*00b67f09SDavid van Moolenbroek 
680*00b67f09SDavid van Moolenbroek 	isc_buffer_availableregion(target, &r);
681*00b67f09SDavid van Moolenbroek 	if (r.length < 1)
682*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
683*00b67f09SDavid van Moolenbroek 	r.base[0] = '\n';
684*00b67f09SDavid van Moolenbroek 	isc_buffer_add(target, 1);
685*00b67f09SDavid van Moolenbroek 
686*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
687*00b67f09SDavid van Moolenbroek }
688*00b67f09SDavid van Moolenbroek 
689*00b67f09SDavid van Moolenbroek isc_result_t
dns_rdataset_totext(dns_rdataset_t * rdataset,dns_name_t * owner_name,isc_boolean_t omit_final_dot,isc_boolean_t question,isc_buffer_t * target)690*00b67f09SDavid van Moolenbroek dns_rdataset_totext(dns_rdataset_t *rdataset,
691*00b67f09SDavid van Moolenbroek 		    dns_name_t *owner_name,
692*00b67f09SDavid van Moolenbroek 		    isc_boolean_t omit_final_dot,
693*00b67f09SDavid van Moolenbroek 		    isc_boolean_t question,
694*00b67f09SDavid van Moolenbroek 		    isc_buffer_t *target)
695*00b67f09SDavid van Moolenbroek {
696*00b67f09SDavid van Moolenbroek 	dns_totext_ctx_t ctx;
697*00b67f09SDavid van Moolenbroek 	isc_result_t result;
698*00b67f09SDavid van Moolenbroek 	result = totext_ctx_init(&dns_master_style_debug, &ctx);
699*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
700*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
701*00b67f09SDavid van Moolenbroek 				 "could not set master file style");
702*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
703*00b67f09SDavid van Moolenbroek 	}
704*00b67f09SDavid van Moolenbroek 
705*00b67f09SDavid van Moolenbroek 	/*
706*00b67f09SDavid van Moolenbroek 	 * The caller might want to give us an empty owner
707*00b67f09SDavid van Moolenbroek 	 * name (e.g. if they are outputting into a master
708*00b67f09SDavid van Moolenbroek 	 * file and this rdataset has the same name as the
709*00b67f09SDavid van Moolenbroek 	 * previous one.)
710*00b67f09SDavid van Moolenbroek 	 */
711*00b67f09SDavid van Moolenbroek 	if (dns_name_countlabels(owner_name) == 0)
712*00b67f09SDavid van Moolenbroek 		owner_name = NULL;
713*00b67f09SDavid van Moolenbroek 
714*00b67f09SDavid van Moolenbroek 	if (question)
715*00b67f09SDavid van Moolenbroek 		return (question_totext(rdataset, owner_name, &ctx,
716*00b67f09SDavid van Moolenbroek 					omit_final_dot, target));
717*00b67f09SDavid van Moolenbroek 	else
718*00b67f09SDavid van Moolenbroek 		return (rdataset_totext(rdataset, owner_name, &ctx,
719*00b67f09SDavid van Moolenbroek 					omit_final_dot, target));
720*00b67f09SDavid van Moolenbroek }
721*00b67f09SDavid van Moolenbroek 
722*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_rdatasettotext(dns_name_t * owner_name,dns_rdataset_t * rdataset,const dns_master_style_t * style,isc_buffer_t * target)723*00b67f09SDavid van Moolenbroek dns_master_rdatasettotext(dns_name_t *owner_name,
724*00b67f09SDavid van Moolenbroek 			  dns_rdataset_t *rdataset,
725*00b67f09SDavid van Moolenbroek 			  const dns_master_style_t *style,
726*00b67f09SDavid van Moolenbroek 			  isc_buffer_t *target)
727*00b67f09SDavid van Moolenbroek {
728*00b67f09SDavid van Moolenbroek 	dns_totext_ctx_t ctx;
729*00b67f09SDavid van Moolenbroek 	isc_result_t result;
730*00b67f09SDavid van Moolenbroek 	result = totext_ctx_init(style, &ctx);
731*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
732*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
733*00b67f09SDavid van Moolenbroek 				 "could not set master file style");
734*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
735*00b67f09SDavid van Moolenbroek 	}
736*00b67f09SDavid van Moolenbroek 
737*00b67f09SDavid van Moolenbroek 	return (rdataset_totext(rdataset, owner_name, &ctx,
738*00b67f09SDavid van Moolenbroek 				ISC_FALSE, target));
739*00b67f09SDavid van Moolenbroek }
740*00b67f09SDavid van Moolenbroek 
741*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_questiontotext(dns_name_t * owner_name,dns_rdataset_t * rdataset,const dns_master_style_t * style,isc_buffer_t * target)742*00b67f09SDavid van Moolenbroek dns_master_questiontotext(dns_name_t *owner_name,
743*00b67f09SDavid van Moolenbroek 			  dns_rdataset_t *rdataset,
744*00b67f09SDavid van Moolenbroek 			  const dns_master_style_t *style,
745*00b67f09SDavid van Moolenbroek 			  isc_buffer_t *target)
746*00b67f09SDavid van Moolenbroek {
747*00b67f09SDavid van Moolenbroek 	dns_totext_ctx_t ctx;
748*00b67f09SDavid van Moolenbroek 	isc_result_t result;
749*00b67f09SDavid van Moolenbroek 	result = totext_ctx_init(style, &ctx);
750*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
751*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
752*00b67f09SDavid van Moolenbroek 				 "could not set master file style");
753*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
754*00b67f09SDavid van Moolenbroek 	}
755*00b67f09SDavid van Moolenbroek 
756*00b67f09SDavid van Moolenbroek 	return (question_totext(rdataset, owner_name, &ctx,
757*00b67f09SDavid van Moolenbroek 				ISC_FALSE, target));
758*00b67f09SDavid van Moolenbroek }
759*00b67f09SDavid van Moolenbroek 
760*00b67f09SDavid van Moolenbroek /*
761*00b67f09SDavid van Moolenbroek  * Print an rdataset.  'buffer' is a scratch buffer, which must have been
762*00b67f09SDavid van Moolenbroek  * dynamically allocated by the caller.  It must be large enough to
763*00b67f09SDavid van Moolenbroek  * hold the result from dns_ttl_totext().  If more than that is needed,
764*00b67f09SDavid van Moolenbroek  * the buffer will be grown automatically.
765*00b67f09SDavid van Moolenbroek  */
766*00b67f09SDavid van Moolenbroek 
767*00b67f09SDavid van Moolenbroek static isc_result_t
dump_rdataset(isc_mem_t * mctx,dns_name_t * name,dns_rdataset_t * rdataset,dns_totext_ctx_t * ctx,isc_buffer_t * buffer,FILE * f)768*00b67f09SDavid van Moolenbroek dump_rdataset(isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *rdataset,
769*00b67f09SDavid van Moolenbroek 	      dns_totext_ctx_t *ctx,
770*00b67f09SDavid van Moolenbroek 	      isc_buffer_t *buffer, FILE *f)
771*00b67f09SDavid van Moolenbroek {
772*00b67f09SDavid van Moolenbroek 	isc_region_t r;
773*00b67f09SDavid van Moolenbroek 	isc_result_t result;
774*00b67f09SDavid van Moolenbroek 
775*00b67f09SDavid van Moolenbroek 	REQUIRE(buffer->length > 0);
776*00b67f09SDavid van Moolenbroek 
777*00b67f09SDavid van Moolenbroek 	/*
778*00b67f09SDavid van Moolenbroek 	 * Output a $TTL directive if needed.
779*00b67f09SDavid van Moolenbroek 	 */
780*00b67f09SDavid van Moolenbroek 
781*00b67f09SDavid van Moolenbroek 	if ((ctx->style.flags & DNS_STYLEFLAG_TTL) != 0) {
782*00b67f09SDavid van Moolenbroek 		if (ctx->current_ttl_valid == ISC_FALSE ||
783*00b67f09SDavid van Moolenbroek 		    ctx->current_ttl != rdataset->ttl)
784*00b67f09SDavid van Moolenbroek 		{
785*00b67f09SDavid van Moolenbroek 			if ((ctx->style.flags & DNS_STYLEFLAG_COMMENT) != 0)
786*00b67f09SDavid van Moolenbroek 			{
787*00b67f09SDavid van Moolenbroek 				isc_buffer_clear(buffer);
788*00b67f09SDavid van Moolenbroek 				result = dns_ttl_totext(rdataset->ttl,
789*00b67f09SDavid van Moolenbroek 							ISC_TRUE, buffer);
790*00b67f09SDavid van Moolenbroek 				INSIST(result == ISC_R_SUCCESS);
791*00b67f09SDavid van Moolenbroek 				isc_buffer_usedregion(buffer, &r);
792*00b67f09SDavid van Moolenbroek 				fprintf(f, "$TTL %u\t; %.*s\n", rdataset->ttl,
793*00b67f09SDavid van Moolenbroek 					(int) r.length, (char *) r.base);
794*00b67f09SDavid van Moolenbroek 			} else {
795*00b67f09SDavid van Moolenbroek 				fprintf(f, "$TTL %u\n", rdataset->ttl);
796*00b67f09SDavid van Moolenbroek 			}
797*00b67f09SDavid van Moolenbroek 			ctx->current_ttl = rdataset->ttl;
798*00b67f09SDavid van Moolenbroek 			ctx->current_ttl_valid = ISC_TRUE;
799*00b67f09SDavid van Moolenbroek 		}
800*00b67f09SDavid van Moolenbroek 	}
801*00b67f09SDavid van Moolenbroek 
802*00b67f09SDavid van Moolenbroek 	isc_buffer_clear(buffer);
803*00b67f09SDavid van Moolenbroek 
804*00b67f09SDavid van Moolenbroek 	/*
805*00b67f09SDavid van Moolenbroek 	 * Generate the text representation of the rdataset into
806*00b67f09SDavid van Moolenbroek 	 * the buffer.  If the buffer is too small, grow it.
807*00b67f09SDavid van Moolenbroek 	 */
808*00b67f09SDavid van Moolenbroek 	for (;;) {
809*00b67f09SDavid van Moolenbroek 		int newlength;
810*00b67f09SDavid van Moolenbroek 		void *newmem;
811*00b67f09SDavid van Moolenbroek 		result = rdataset_totext(rdataset, name, ctx,
812*00b67f09SDavid van Moolenbroek 					 ISC_FALSE, buffer);
813*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_NOSPACE)
814*00b67f09SDavid van Moolenbroek 			break;
815*00b67f09SDavid van Moolenbroek 
816*00b67f09SDavid van Moolenbroek 		newlength = buffer->length * 2;
817*00b67f09SDavid van Moolenbroek 		newmem = isc_mem_get(mctx, newlength);
818*00b67f09SDavid van Moolenbroek 		if (newmem == NULL)
819*00b67f09SDavid van Moolenbroek 			return (ISC_R_NOMEMORY);
820*00b67f09SDavid van Moolenbroek 		isc_mem_put(mctx, buffer->base, buffer->length);
821*00b67f09SDavid van Moolenbroek 		isc_buffer_init(buffer, newmem, newlength);
822*00b67f09SDavid van Moolenbroek 	}
823*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
824*00b67f09SDavid van Moolenbroek 		return (result);
825*00b67f09SDavid van Moolenbroek 
826*00b67f09SDavid van Moolenbroek 	/*
827*00b67f09SDavid van Moolenbroek 	 * Write the buffer contents to the master file.
828*00b67f09SDavid van Moolenbroek 	 */
829*00b67f09SDavid van Moolenbroek 	isc_buffer_usedregion(buffer, &r);
830*00b67f09SDavid van Moolenbroek 	result = isc_stdio_write(r.base, 1, (size_t)r.length, f, NULL);
831*00b67f09SDavid van Moolenbroek 
832*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
833*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
834*00b67f09SDavid van Moolenbroek 				 "master file write failed: %s",
835*00b67f09SDavid van Moolenbroek 				 isc_result_totext(result));
836*00b67f09SDavid van Moolenbroek 		return (result);
837*00b67f09SDavid van Moolenbroek 	}
838*00b67f09SDavid van Moolenbroek 
839*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
840*00b67f09SDavid van Moolenbroek }
841*00b67f09SDavid van Moolenbroek 
842*00b67f09SDavid van Moolenbroek /*
843*00b67f09SDavid van Moolenbroek  * Define the order in which rdatasets should be printed in zone
844*00b67f09SDavid van Moolenbroek  * files.  We will print SOA and NS records before others, SIGs
845*00b67f09SDavid van Moolenbroek  * immediately following the things they sign, and order everything
846*00b67f09SDavid van Moolenbroek  * else by RR number.  This is all just for aesthetics and
847*00b67f09SDavid van Moolenbroek  * compatibility with buggy software that expects the SOA to be first;
848*00b67f09SDavid van Moolenbroek  * the DNS specifications allow any order.
849*00b67f09SDavid van Moolenbroek  */
850*00b67f09SDavid van Moolenbroek 
851*00b67f09SDavid van Moolenbroek static int
dump_order(const dns_rdataset_t * rds)852*00b67f09SDavid van Moolenbroek dump_order(const dns_rdataset_t *rds) {
853*00b67f09SDavid van Moolenbroek 	int t;
854*00b67f09SDavid van Moolenbroek 	int sig;
855*00b67f09SDavid van Moolenbroek 	if (rds->type == dns_rdatatype_rrsig) {
856*00b67f09SDavid van Moolenbroek 		t = rds->covers;
857*00b67f09SDavid van Moolenbroek 		sig = 1;
858*00b67f09SDavid van Moolenbroek 	} else {
859*00b67f09SDavid van Moolenbroek 		t = rds->type;
860*00b67f09SDavid van Moolenbroek 		sig = 0;
861*00b67f09SDavid van Moolenbroek 	}
862*00b67f09SDavid van Moolenbroek 	switch (t) {
863*00b67f09SDavid van Moolenbroek 	case dns_rdatatype_soa:
864*00b67f09SDavid van Moolenbroek 		t = 0;
865*00b67f09SDavid van Moolenbroek 		break;
866*00b67f09SDavid van Moolenbroek 	case dns_rdatatype_ns:
867*00b67f09SDavid van Moolenbroek 		t = 1;
868*00b67f09SDavid van Moolenbroek 		break;
869*00b67f09SDavid van Moolenbroek 	default:
870*00b67f09SDavid van Moolenbroek 		t += 2;
871*00b67f09SDavid van Moolenbroek 		break;
872*00b67f09SDavid van Moolenbroek 	}
873*00b67f09SDavid van Moolenbroek 	return (t << 1) + sig;
874*00b67f09SDavid van Moolenbroek }
875*00b67f09SDavid van Moolenbroek 
876*00b67f09SDavid van Moolenbroek static int
dump_order_compare(const void * a,const void * b)877*00b67f09SDavid van Moolenbroek dump_order_compare(const void *a, const void *b) {
878*00b67f09SDavid van Moolenbroek 	return (dump_order(*((const dns_rdataset_t * const *) a)) -
879*00b67f09SDavid van Moolenbroek 		dump_order(*((const dns_rdataset_t * const *) b)));
880*00b67f09SDavid van Moolenbroek }
881*00b67f09SDavid van Moolenbroek 
882*00b67f09SDavid van Moolenbroek /*
883*00b67f09SDavid van Moolenbroek  * Dump all the rdatasets of a domain name to a master file.  We make
884*00b67f09SDavid van Moolenbroek  * a "best effort" attempt to sort the RRsets in a nice order, but if
885*00b67f09SDavid van Moolenbroek  * there are more than MAXSORT RRsets, we punt and only sort them in
886*00b67f09SDavid van Moolenbroek  * groups of MAXSORT.  This is not expected to ever happen in practice
887*00b67f09SDavid van Moolenbroek  * since much less than 64 RR types have been registered with the
888*00b67f09SDavid van Moolenbroek  * IANA, so far, and the output will be correct (though not
889*00b67f09SDavid van Moolenbroek  * aesthetically pleasing) even if it does happen.
890*00b67f09SDavid van Moolenbroek  */
891*00b67f09SDavid van Moolenbroek 
892*00b67f09SDavid van Moolenbroek #define MAXSORT 64
893*00b67f09SDavid van Moolenbroek 
894*00b67f09SDavid van Moolenbroek static isc_result_t
dump_rdatasets_text(isc_mem_t * mctx,dns_name_t * name,dns_rdatasetiter_t * rdsiter,dns_totext_ctx_t * ctx,isc_buffer_t * buffer,FILE * f)895*00b67f09SDavid van Moolenbroek dump_rdatasets_text(isc_mem_t *mctx, dns_name_t *name,
896*00b67f09SDavid van Moolenbroek 		    dns_rdatasetiter_t *rdsiter, dns_totext_ctx_t *ctx,
897*00b67f09SDavid van Moolenbroek 		    isc_buffer_t *buffer, FILE *f)
898*00b67f09SDavid van Moolenbroek {
899*00b67f09SDavid van Moolenbroek 	isc_result_t itresult, dumpresult;
900*00b67f09SDavid van Moolenbroek 	isc_region_t r;
901*00b67f09SDavid van Moolenbroek 	dns_rdataset_t rdatasets[MAXSORT];
902*00b67f09SDavid van Moolenbroek 	dns_rdataset_t *sorted[MAXSORT];
903*00b67f09SDavid van Moolenbroek 	int i, n;
904*00b67f09SDavid van Moolenbroek 
905*00b67f09SDavid van Moolenbroek 	itresult = dns_rdatasetiter_first(rdsiter);
906*00b67f09SDavid van Moolenbroek 	dumpresult = ISC_R_SUCCESS;
907*00b67f09SDavid van Moolenbroek 
908*00b67f09SDavid van Moolenbroek 	if (itresult == ISC_R_SUCCESS && ctx->neworigin != NULL) {
909*00b67f09SDavid van Moolenbroek 		isc_buffer_clear(buffer);
910*00b67f09SDavid van Moolenbroek 		itresult = dns_name_totext(ctx->neworigin, ISC_FALSE, buffer);
911*00b67f09SDavid van Moolenbroek 		RUNTIME_CHECK(itresult == ISC_R_SUCCESS);
912*00b67f09SDavid van Moolenbroek 		isc_buffer_usedregion(buffer, &r);
913*00b67f09SDavid van Moolenbroek 		fprintf(f, "$ORIGIN %.*s\n", (int) r.length, (char *) r.base);
914*00b67f09SDavid van Moolenbroek 		ctx->neworigin = NULL;
915*00b67f09SDavid van Moolenbroek 	}
916*00b67f09SDavid van Moolenbroek 
917*00b67f09SDavid van Moolenbroek  again:
918*00b67f09SDavid van Moolenbroek 	for (i = 0;
919*00b67f09SDavid van Moolenbroek 	     itresult == ISC_R_SUCCESS && i < MAXSORT;
920*00b67f09SDavid van Moolenbroek 	     itresult = dns_rdatasetiter_next(rdsiter), i++) {
921*00b67f09SDavid van Moolenbroek 		dns_rdataset_init(&rdatasets[i]);
922*00b67f09SDavid van Moolenbroek 		dns_rdatasetiter_current(rdsiter, &rdatasets[i]);
923*00b67f09SDavid van Moolenbroek 		sorted[i] = &rdatasets[i];
924*00b67f09SDavid van Moolenbroek 	}
925*00b67f09SDavid van Moolenbroek 	n = i;
926*00b67f09SDavid van Moolenbroek 	INSIST(n <= MAXSORT);
927*00b67f09SDavid van Moolenbroek 
928*00b67f09SDavid van Moolenbroek 	qsort(sorted, n, sizeof(sorted[0]), dump_order_compare);
929*00b67f09SDavid van Moolenbroek 
930*00b67f09SDavid van Moolenbroek 	for (i = 0; i < n; i++) {
931*00b67f09SDavid van Moolenbroek 		dns_rdataset_t *rds = sorted[i];
932*00b67f09SDavid van Moolenbroek 		if (ctx->style.flags & DNS_STYLEFLAG_TRUST)
933*00b67f09SDavid van Moolenbroek 			fprintf(f, "; %s\n", dns_trust_totext(rds->trust));
934*00b67f09SDavid van Moolenbroek 		if (((rds->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) &&
935*00b67f09SDavid van Moolenbroek 		    (ctx->style.flags & DNS_STYLEFLAG_NCACHE) == 0) {
936*00b67f09SDavid van Moolenbroek 			/* Omit negative cache entries */
937*00b67f09SDavid van Moolenbroek 		} else {
938*00b67f09SDavid van Moolenbroek 			isc_result_t result =
939*00b67f09SDavid van Moolenbroek 				dump_rdataset(mctx, name, rds, ctx,
940*00b67f09SDavid van Moolenbroek 					       buffer, f);
941*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
942*00b67f09SDavid van Moolenbroek 				dumpresult = result;
943*00b67f09SDavid van Moolenbroek 			if ((ctx->style.flags & DNS_STYLEFLAG_OMIT_OWNER) != 0)
944*00b67f09SDavid van Moolenbroek 				name = NULL;
945*00b67f09SDavid van Moolenbroek 		}
946*00b67f09SDavid van Moolenbroek 		if (ctx->style.flags & DNS_STYLEFLAG_RESIGN &&
947*00b67f09SDavid van Moolenbroek 		    rds->attributes & DNS_RDATASETATTR_RESIGN) {
948*00b67f09SDavid van Moolenbroek 			isc_buffer_t b;
949*00b67f09SDavid van Moolenbroek 			char buf[sizeof("YYYYMMDDHHMMSS")];
950*00b67f09SDavid van Moolenbroek 			memset(buf, 0, sizeof(buf));
951*00b67f09SDavid van Moolenbroek 			isc_buffer_init(&b, buf, sizeof(buf) - 1);
952*00b67f09SDavid van Moolenbroek 			dns_time64_totext((isc_uint64_t)rds->resign, &b);
953*00b67f09SDavid van Moolenbroek 			fprintf(f, "; resign=%s\n", buf);
954*00b67f09SDavid van Moolenbroek 		}
955*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(rds);
956*00b67f09SDavid van Moolenbroek 	}
957*00b67f09SDavid van Moolenbroek 
958*00b67f09SDavid van Moolenbroek 	if (dumpresult != ISC_R_SUCCESS)
959*00b67f09SDavid van Moolenbroek 		return (dumpresult);
960*00b67f09SDavid van Moolenbroek 
961*00b67f09SDavid van Moolenbroek 	/*
962*00b67f09SDavid van Moolenbroek 	 * If we got more data than could be sorted at once,
963*00b67f09SDavid van Moolenbroek 	 * go handle the rest.
964*00b67f09SDavid van Moolenbroek 	 */
965*00b67f09SDavid van Moolenbroek 	if (itresult == ISC_R_SUCCESS)
966*00b67f09SDavid van Moolenbroek 		goto again;
967*00b67f09SDavid van Moolenbroek 
968*00b67f09SDavid van Moolenbroek 	if (itresult == ISC_R_NOMORE)
969*00b67f09SDavid van Moolenbroek 		itresult = ISC_R_SUCCESS;
970*00b67f09SDavid van Moolenbroek 
971*00b67f09SDavid van Moolenbroek 	return (itresult);
972*00b67f09SDavid van Moolenbroek }
973*00b67f09SDavid van Moolenbroek 
974*00b67f09SDavid van Moolenbroek /*
975*00b67f09SDavid van Moolenbroek  * Dump given RRsets in the "raw" format.
976*00b67f09SDavid van Moolenbroek  */
977*00b67f09SDavid van Moolenbroek static isc_result_t
dump_rdataset_raw(isc_mem_t * mctx,dns_name_t * name,dns_rdataset_t * rdataset,isc_buffer_t * buffer,FILE * f)978*00b67f09SDavid van Moolenbroek dump_rdataset_raw(isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *rdataset,
979*00b67f09SDavid van Moolenbroek 		  isc_buffer_t *buffer, FILE *f)
980*00b67f09SDavid van Moolenbroek {
981*00b67f09SDavid van Moolenbroek 	isc_result_t result;
982*00b67f09SDavid van Moolenbroek 	isc_uint32_t totallen;
983*00b67f09SDavid van Moolenbroek 	isc_uint16_t dlen;
984*00b67f09SDavid van Moolenbroek 	isc_region_t r, r_hdr;
985*00b67f09SDavid van Moolenbroek 
986*00b67f09SDavid van Moolenbroek 	REQUIRE(buffer->length > 0);
987*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_RDATASET_VALID(rdataset));
988*00b67f09SDavid van Moolenbroek 
989*00b67f09SDavid van Moolenbroek 	rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
990*00b67f09SDavid van Moolenbroek  restart:
991*00b67f09SDavid van Moolenbroek 	totallen = 0;
992*00b67f09SDavid van Moolenbroek 	result = dns_rdataset_first(rdataset);
993*00b67f09SDavid van Moolenbroek 	REQUIRE(result == ISC_R_SUCCESS);
994*00b67f09SDavid van Moolenbroek 
995*00b67f09SDavid van Moolenbroek 	isc_buffer_clear(buffer);
996*00b67f09SDavid van Moolenbroek 
997*00b67f09SDavid van Moolenbroek 	/*
998*00b67f09SDavid van Moolenbroek 	 * Common header and owner name (length followed by name)
999*00b67f09SDavid van Moolenbroek 	 * These fields should be in a moderate length, so we assume we
1000*00b67f09SDavid van Moolenbroek 	 * can store all of them in the initial buffer.
1001*00b67f09SDavid van Moolenbroek 	 */
1002*00b67f09SDavid van Moolenbroek 	isc_buffer_availableregion(buffer, &r_hdr);
1003*00b67f09SDavid van Moolenbroek 	INSIST(r_hdr.length >= sizeof(dns_masterrawrdataset_t));
1004*00b67f09SDavid van Moolenbroek 	isc_buffer_putuint32(buffer, totallen);	/* XXX: leave space */
1005*00b67f09SDavid van Moolenbroek 	isc_buffer_putuint16(buffer, rdataset->rdclass); /* 16-bit class */
1006*00b67f09SDavid van Moolenbroek 	isc_buffer_putuint16(buffer, rdataset->type); /* 16-bit type */
1007*00b67f09SDavid van Moolenbroek 	isc_buffer_putuint16(buffer, rdataset->covers);	/* same as type */
1008*00b67f09SDavid van Moolenbroek 	isc_buffer_putuint32(buffer, rdataset->ttl); /* 32-bit TTL */
1009*00b67f09SDavid van Moolenbroek 	isc_buffer_putuint32(buffer, dns_rdataset_count(rdataset));
1010*00b67f09SDavid van Moolenbroek 	totallen = isc_buffer_usedlength(buffer);
1011*00b67f09SDavid van Moolenbroek 	INSIST(totallen <= sizeof(dns_masterrawrdataset_t));
1012*00b67f09SDavid van Moolenbroek 
1013*00b67f09SDavid van Moolenbroek 	dns_name_toregion(name, &r);
1014*00b67f09SDavid van Moolenbroek 	INSIST(isc_buffer_availablelength(buffer) >=
1015*00b67f09SDavid van Moolenbroek 	       (sizeof(dlen) + r.length));
1016*00b67f09SDavid van Moolenbroek 	dlen = (isc_uint16_t)r.length;
1017*00b67f09SDavid van Moolenbroek 	isc_buffer_putuint16(buffer, dlen);
1018*00b67f09SDavid van Moolenbroek 	isc_buffer_copyregion(buffer, &r);
1019*00b67f09SDavid van Moolenbroek 	totallen += sizeof(dlen) + r.length;
1020*00b67f09SDavid van Moolenbroek 
1021*00b67f09SDavid van Moolenbroek 	do {
1022*00b67f09SDavid van Moolenbroek 		dns_rdata_t rdata = DNS_RDATA_INIT;
1023*00b67f09SDavid van Moolenbroek 
1024*00b67f09SDavid van Moolenbroek 		dns_rdataset_current(rdataset, &rdata);
1025*00b67f09SDavid van Moolenbroek 		dns_rdata_toregion(&rdata, &r);
1026*00b67f09SDavid van Moolenbroek 		INSIST(r.length <= 0xffffU);
1027*00b67f09SDavid van Moolenbroek 		dlen = (isc_uint16_t)r.length;
1028*00b67f09SDavid van Moolenbroek 
1029*00b67f09SDavid van Moolenbroek 		/*
1030*00b67f09SDavid van Moolenbroek 		 * Copy the rdata into the buffer.  If the buffer is too small,
1031*00b67f09SDavid van Moolenbroek 		 * grow it.  This should be rare, so we'll simply restart the
1032*00b67f09SDavid van Moolenbroek 		 * entire procedure (or should we copy the old data and
1033*00b67f09SDavid van Moolenbroek 		 * continue?).
1034*00b67f09SDavid van Moolenbroek 		 */
1035*00b67f09SDavid van Moolenbroek 		if (isc_buffer_availablelength(buffer) <
1036*00b67f09SDavid van Moolenbroek 						 sizeof(dlen) + r.length) {
1037*00b67f09SDavid van Moolenbroek 			int newlength;
1038*00b67f09SDavid van Moolenbroek 			void *newmem;
1039*00b67f09SDavid van Moolenbroek 
1040*00b67f09SDavid van Moolenbroek 			newlength = buffer->length * 2;
1041*00b67f09SDavid van Moolenbroek 			newmem = isc_mem_get(mctx, newlength);
1042*00b67f09SDavid van Moolenbroek 			if (newmem == NULL)
1043*00b67f09SDavid van Moolenbroek 				return (ISC_R_NOMEMORY);
1044*00b67f09SDavid van Moolenbroek 			isc_mem_put(mctx, buffer->base, buffer->length);
1045*00b67f09SDavid van Moolenbroek 			isc_buffer_init(buffer, newmem, newlength);
1046*00b67f09SDavid van Moolenbroek 			goto restart;
1047*00b67f09SDavid van Moolenbroek 		}
1048*00b67f09SDavid van Moolenbroek 		isc_buffer_putuint16(buffer, dlen);
1049*00b67f09SDavid van Moolenbroek 		isc_buffer_copyregion(buffer, &r);
1050*00b67f09SDavid van Moolenbroek 		totallen += sizeof(dlen) + r.length;
1051*00b67f09SDavid van Moolenbroek 
1052*00b67f09SDavid van Moolenbroek 		result = dns_rdataset_next(rdataset);
1053*00b67f09SDavid van Moolenbroek 	} while (result == ISC_R_SUCCESS);
1054*00b67f09SDavid van Moolenbroek 
1055*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_NOMORE)
1056*00b67f09SDavid van Moolenbroek 		return (result);
1057*00b67f09SDavid van Moolenbroek 
1058*00b67f09SDavid van Moolenbroek 	/*
1059*00b67f09SDavid van Moolenbroek 	 * Fill in the total length field.
1060*00b67f09SDavid van Moolenbroek 	 * XXX: this is a bit tricky.  Since we have already "used" the space
1061*00b67f09SDavid van Moolenbroek 	 * for the total length in the buffer, we first remember the entire
1062*00b67f09SDavid van Moolenbroek 	 * buffer length in the region, "rewind", and then write the value.
1063*00b67f09SDavid van Moolenbroek 	 */
1064*00b67f09SDavid van Moolenbroek 	isc_buffer_usedregion(buffer, &r);
1065*00b67f09SDavid van Moolenbroek 	isc_buffer_clear(buffer);
1066*00b67f09SDavid van Moolenbroek 	isc_buffer_putuint32(buffer, totallen);
1067*00b67f09SDavid van Moolenbroek 	INSIST(isc_buffer_usedlength(buffer) < totallen);
1068*00b67f09SDavid van Moolenbroek 
1069*00b67f09SDavid van Moolenbroek 	/*
1070*00b67f09SDavid van Moolenbroek 	 * Write the buffer contents to the raw master file.
1071*00b67f09SDavid van Moolenbroek 	 */
1072*00b67f09SDavid van Moolenbroek 	result = isc_stdio_write(r.base, 1, (size_t)r.length, f, NULL);
1073*00b67f09SDavid van Moolenbroek 
1074*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1075*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
1076*00b67f09SDavid van Moolenbroek 				 "raw master file write failed: %s",
1077*00b67f09SDavid van Moolenbroek 				 isc_result_totext(result));
1078*00b67f09SDavid van Moolenbroek 		return (result);
1079*00b67f09SDavid van Moolenbroek 	}
1080*00b67f09SDavid van Moolenbroek 
1081*00b67f09SDavid van Moolenbroek 	return (result);
1082*00b67f09SDavid van Moolenbroek }
1083*00b67f09SDavid van Moolenbroek 
1084*00b67f09SDavid van Moolenbroek static isc_result_t
dump_rdatasets_raw(isc_mem_t * mctx,dns_name_t * name,dns_rdatasetiter_t * rdsiter,dns_totext_ctx_t * ctx,isc_buffer_t * buffer,FILE * f)1085*00b67f09SDavid van Moolenbroek dump_rdatasets_raw(isc_mem_t *mctx, dns_name_t *name,
1086*00b67f09SDavid van Moolenbroek 		   dns_rdatasetiter_t *rdsiter, dns_totext_ctx_t *ctx,
1087*00b67f09SDavid van Moolenbroek 		   isc_buffer_t *buffer, FILE *f)
1088*00b67f09SDavid van Moolenbroek {
1089*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1090*00b67f09SDavid van Moolenbroek 	dns_rdataset_t rdataset;
1091*00b67f09SDavid van Moolenbroek 
1092*00b67f09SDavid van Moolenbroek 	for (result = dns_rdatasetiter_first(rdsiter);
1093*00b67f09SDavid van Moolenbroek 	     result == ISC_R_SUCCESS;
1094*00b67f09SDavid van Moolenbroek 	     result = dns_rdatasetiter_next(rdsiter)) {
1095*00b67f09SDavid van Moolenbroek 
1096*00b67f09SDavid van Moolenbroek 		dns_rdataset_init(&rdataset);
1097*00b67f09SDavid van Moolenbroek 		dns_rdatasetiter_current(rdsiter, &rdataset);
1098*00b67f09SDavid van Moolenbroek 
1099*00b67f09SDavid van Moolenbroek 		if (((rdataset.attributes & DNS_RDATASETATTR_NEGATIVE) != 0) &&
1100*00b67f09SDavid van Moolenbroek 		    (ctx->style.flags & DNS_STYLEFLAG_NCACHE) == 0) {
1101*00b67f09SDavid van Moolenbroek 			/* Omit negative cache entries */
1102*00b67f09SDavid van Moolenbroek 		} else {
1103*00b67f09SDavid van Moolenbroek 			result = dump_rdataset_raw(mctx, name, &rdataset,
1104*00b67f09SDavid van Moolenbroek 						   buffer, f);
1105*00b67f09SDavid van Moolenbroek 		}
1106*00b67f09SDavid van Moolenbroek 		dns_rdataset_disassociate(&rdataset);
1107*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
1108*00b67f09SDavid van Moolenbroek 			return (result);
1109*00b67f09SDavid van Moolenbroek 	}
1110*00b67f09SDavid van Moolenbroek 
1111*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_NOMORE)
1112*00b67f09SDavid van Moolenbroek 		result = ISC_R_SUCCESS;
1113*00b67f09SDavid van Moolenbroek 
1114*00b67f09SDavid van Moolenbroek 	return (result);
1115*00b67f09SDavid van Moolenbroek }
1116*00b67f09SDavid van Moolenbroek 
1117*00b67f09SDavid van Moolenbroek static isc_result_t
dump_rdatasets_map(isc_mem_t * mctx,dns_name_t * name,dns_rdatasetiter_t * rdsiter,dns_totext_ctx_t * ctx,isc_buffer_t * buffer,FILE * f)1118*00b67f09SDavid van Moolenbroek dump_rdatasets_map(isc_mem_t *mctx, dns_name_t *name,
1119*00b67f09SDavid van Moolenbroek 		   dns_rdatasetiter_t *rdsiter, dns_totext_ctx_t *ctx,
1120*00b67f09SDavid van Moolenbroek 		   isc_buffer_t *buffer, FILE *f)
1121*00b67f09SDavid van Moolenbroek {
1122*00b67f09SDavid van Moolenbroek 	UNUSED(mctx);
1123*00b67f09SDavid van Moolenbroek 	UNUSED(name);
1124*00b67f09SDavid van Moolenbroek 	UNUSED(rdsiter);
1125*00b67f09SDavid van Moolenbroek 	UNUSED(ctx);
1126*00b67f09SDavid van Moolenbroek 	UNUSED(buffer);
1127*00b67f09SDavid van Moolenbroek 	UNUSED(f);
1128*00b67f09SDavid van Moolenbroek 
1129*00b67f09SDavid van Moolenbroek 	return (ISC_R_NOTIMPLEMENTED);
1130*00b67f09SDavid van Moolenbroek }
1131*00b67f09SDavid van Moolenbroek 
1132*00b67f09SDavid van Moolenbroek /*
1133*00b67f09SDavid van Moolenbroek  * Initial size of text conversion buffer.  The buffer is used
1134*00b67f09SDavid van Moolenbroek  * for several purposes: converting origin names, rdatasets,
1135*00b67f09SDavid van Moolenbroek  * $DATE timestamps, and comment strings for $TTL directives.
1136*00b67f09SDavid van Moolenbroek  *
1137*00b67f09SDavid van Moolenbroek  * When converting rdatasets, it is dynamically resized, but
1138*00b67f09SDavid van Moolenbroek  * when converting origins, timestamps, etc it is not.  Therefore,
1139*00b67f09SDavid van Moolenbroek  * the initial size must large enough to hold the longest possible
1140*00b67f09SDavid van Moolenbroek  * text representation of any domain name (for $ORIGIN).
1141*00b67f09SDavid van Moolenbroek  */
1142*00b67f09SDavid van Moolenbroek static const int initial_buffer_length = 1200;
1143*00b67f09SDavid van Moolenbroek 
1144*00b67f09SDavid van Moolenbroek static isc_result_t
1145*00b67f09SDavid van Moolenbroek dumptostreaminc(dns_dumpctx_t *dctx);
1146*00b67f09SDavid van Moolenbroek 
1147*00b67f09SDavid van Moolenbroek static void
dumpctx_destroy(dns_dumpctx_t * dctx)1148*00b67f09SDavid van Moolenbroek dumpctx_destroy(dns_dumpctx_t *dctx) {
1149*00b67f09SDavid van Moolenbroek 
1150*00b67f09SDavid van Moolenbroek 	dctx->magic = 0;
1151*00b67f09SDavid van Moolenbroek 	DESTROYLOCK(&dctx->lock);
1152*00b67f09SDavid van Moolenbroek 	dns_dbiterator_destroy(&dctx->dbiter);
1153*00b67f09SDavid van Moolenbroek 	if (dctx->version != NULL)
1154*00b67f09SDavid van Moolenbroek 		dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
1155*00b67f09SDavid van Moolenbroek 	dns_db_detach(&dctx->db);
1156*00b67f09SDavid van Moolenbroek 	if (dctx->task != NULL)
1157*00b67f09SDavid van Moolenbroek 		isc_task_detach(&dctx->task);
1158*00b67f09SDavid van Moolenbroek 	if (dctx->file != NULL)
1159*00b67f09SDavid van Moolenbroek 		isc_mem_free(dctx->mctx, dctx->file);
1160*00b67f09SDavid van Moolenbroek 	if (dctx->tmpfile != NULL)
1161*00b67f09SDavid van Moolenbroek 		isc_mem_free(dctx->mctx, dctx->tmpfile);
1162*00b67f09SDavid van Moolenbroek 	isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(*dctx));
1163*00b67f09SDavid van Moolenbroek }
1164*00b67f09SDavid van Moolenbroek 
1165*00b67f09SDavid van Moolenbroek void
dns_dumpctx_attach(dns_dumpctx_t * source,dns_dumpctx_t ** target)1166*00b67f09SDavid van Moolenbroek dns_dumpctx_attach(dns_dumpctx_t *source, dns_dumpctx_t **target) {
1167*00b67f09SDavid van Moolenbroek 
1168*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_DCTX_VALID(source));
1169*00b67f09SDavid van Moolenbroek 	REQUIRE(target != NULL && *target == NULL);
1170*00b67f09SDavid van Moolenbroek 
1171*00b67f09SDavid van Moolenbroek 	LOCK(&source->lock);
1172*00b67f09SDavid van Moolenbroek 	INSIST(source->references > 0);
1173*00b67f09SDavid van Moolenbroek 	source->references++;
1174*00b67f09SDavid van Moolenbroek 	INSIST(source->references != 0);	/* Overflow? */
1175*00b67f09SDavid van Moolenbroek 	UNLOCK(&source->lock);
1176*00b67f09SDavid van Moolenbroek 
1177*00b67f09SDavid van Moolenbroek 	*target = source;
1178*00b67f09SDavid van Moolenbroek }
1179*00b67f09SDavid van Moolenbroek 
1180*00b67f09SDavid van Moolenbroek void
dns_dumpctx_detach(dns_dumpctx_t ** dctxp)1181*00b67f09SDavid van Moolenbroek dns_dumpctx_detach(dns_dumpctx_t **dctxp) {
1182*00b67f09SDavid van Moolenbroek 	dns_dumpctx_t *dctx;
1183*00b67f09SDavid van Moolenbroek 	isc_boolean_t need_destroy = ISC_FALSE;
1184*00b67f09SDavid van Moolenbroek 
1185*00b67f09SDavid van Moolenbroek 	REQUIRE(dctxp != NULL);
1186*00b67f09SDavid van Moolenbroek 	dctx = *dctxp;
1187*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_DCTX_VALID(dctx));
1188*00b67f09SDavid van Moolenbroek 
1189*00b67f09SDavid van Moolenbroek 	*dctxp = NULL;
1190*00b67f09SDavid van Moolenbroek 
1191*00b67f09SDavid van Moolenbroek 	LOCK(&dctx->lock);
1192*00b67f09SDavid van Moolenbroek 	INSIST(dctx->references != 0);
1193*00b67f09SDavid van Moolenbroek 	dctx->references--;
1194*00b67f09SDavid van Moolenbroek 	if (dctx->references == 0)
1195*00b67f09SDavid van Moolenbroek 		need_destroy = ISC_TRUE;
1196*00b67f09SDavid van Moolenbroek 	UNLOCK(&dctx->lock);
1197*00b67f09SDavid van Moolenbroek 	if (need_destroy)
1198*00b67f09SDavid van Moolenbroek 		dumpctx_destroy(dctx);
1199*00b67f09SDavid van Moolenbroek }
1200*00b67f09SDavid van Moolenbroek 
1201*00b67f09SDavid van Moolenbroek dns_dbversion_t *
dns_dumpctx_version(dns_dumpctx_t * dctx)1202*00b67f09SDavid van Moolenbroek dns_dumpctx_version(dns_dumpctx_t *dctx) {
1203*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_DCTX_VALID(dctx));
1204*00b67f09SDavid van Moolenbroek 	return (dctx->version);
1205*00b67f09SDavid van Moolenbroek }
1206*00b67f09SDavid van Moolenbroek 
1207*00b67f09SDavid van Moolenbroek dns_db_t *
dns_dumpctx_db(dns_dumpctx_t * dctx)1208*00b67f09SDavid van Moolenbroek dns_dumpctx_db(dns_dumpctx_t *dctx) {
1209*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_DCTX_VALID(dctx));
1210*00b67f09SDavid van Moolenbroek 	return (dctx->db);
1211*00b67f09SDavid van Moolenbroek }
1212*00b67f09SDavid van Moolenbroek 
1213*00b67f09SDavid van Moolenbroek void
dns_dumpctx_cancel(dns_dumpctx_t * dctx)1214*00b67f09SDavid van Moolenbroek dns_dumpctx_cancel(dns_dumpctx_t *dctx) {
1215*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_DCTX_VALID(dctx));
1216*00b67f09SDavid van Moolenbroek 
1217*00b67f09SDavid van Moolenbroek 	LOCK(&dctx->lock);
1218*00b67f09SDavid van Moolenbroek 	dctx->canceled = ISC_TRUE;
1219*00b67f09SDavid van Moolenbroek 	UNLOCK(&dctx->lock);
1220*00b67f09SDavid van Moolenbroek }
1221*00b67f09SDavid van Moolenbroek 
1222*00b67f09SDavid van Moolenbroek static isc_result_t
flushandsync(FILE * f,isc_result_t result,const char * temp)1223*00b67f09SDavid van Moolenbroek flushandsync(FILE *f, isc_result_t result, const char *temp) {
1224*00b67f09SDavid van Moolenbroek 	isc_boolean_t logit = ISC_TF(result == ISC_R_SUCCESS);
1225*00b67f09SDavid van Moolenbroek 
1226*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
1227*00b67f09SDavid van Moolenbroek 		result = isc_stdio_flush(f);
1228*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS && logit) {
1229*00b67f09SDavid van Moolenbroek 		if (temp != NULL)
1230*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1231*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1232*00b67f09SDavid van Moolenbroek 				      "dumping to master file: %s: flush: %s",
1233*00b67f09SDavid van Moolenbroek 				      temp, isc_result_totext(result));
1234*00b67f09SDavid van Moolenbroek 		else
1235*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1236*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1237*00b67f09SDavid van Moolenbroek 				      "dumping to stream: flush: %s",
1238*00b67f09SDavid van Moolenbroek 				      isc_result_totext(result));
1239*00b67f09SDavid van Moolenbroek 		logit = ISC_FALSE;
1240*00b67f09SDavid van Moolenbroek 	}
1241*00b67f09SDavid van Moolenbroek 
1242*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
1243*00b67f09SDavid van Moolenbroek 		result = isc_stdio_sync(f);
1244*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS && logit) {
1245*00b67f09SDavid van Moolenbroek 		if (temp != NULL)
1246*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1247*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1248*00b67f09SDavid van Moolenbroek 				      "dumping to master file: %s: fsync: %s",
1249*00b67f09SDavid van Moolenbroek 				      temp, isc_result_totext(result));
1250*00b67f09SDavid van Moolenbroek 		else
1251*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1252*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1253*00b67f09SDavid van Moolenbroek 				      "dumping to stream: fsync: %s",
1254*00b67f09SDavid van Moolenbroek 				      isc_result_totext(result));
1255*00b67f09SDavid van Moolenbroek 	}
1256*00b67f09SDavid van Moolenbroek 	return (result);
1257*00b67f09SDavid van Moolenbroek }
1258*00b67f09SDavid van Moolenbroek 
1259*00b67f09SDavid van Moolenbroek static isc_result_t
closeandrename(FILE * f,isc_result_t result,const char * temp,const char * file)1260*00b67f09SDavid van Moolenbroek closeandrename(FILE *f, isc_result_t result, const char *temp, const char *file)
1261*00b67f09SDavid van Moolenbroek {
1262*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
1263*00b67f09SDavid van Moolenbroek 	isc_boolean_t logit = ISC_TF(result == ISC_R_SUCCESS);
1264*00b67f09SDavid van Moolenbroek 
1265*00b67f09SDavid van Moolenbroek 	result = flushandsync(f, result, temp);
1266*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1267*00b67f09SDavid van Moolenbroek 		logit = ISC_FALSE;
1268*00b67f09SDavid van Moolenbroek 
1269*00b67f09SDavid van Moolenbroek 	tresult = isc_stdio_close(f);
1270*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
1271*00b67f09SDavid van Moolenbroek 		result = tresult;
1272*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS && logit) {
1273*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1274*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1275*00b67f09SDavid van Moolenbroek 			      "dumping master file: %s: fclose: %s",
1276*00b67f09SDavid van Moolenbroek 			      temp, isc_result_totext(result));
1277*00b67f09SDavid van Moolenbroek 		logit = ISC_FALSE;
1278*00b67f09SDavid van Moolenbroek 	}
1279*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
1280*00b67f09SDavid van Moolenbroek 		result = isc_file_rename(temp, file);
1281*00b67f09SDavid van Moolenbroek 	else
1282*00b67f09SDavid van Moolenbroek 		(void)isc_file_remove(temp);
1283*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS && logit) {
1284*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1285*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1286*00b67f09SDavid van Moolenbroek 			      "dumping master file: rename: %s: %s",
1287*00b67f09SDavid van Moolenbroek 			      file, isc_result_totext(result));
1288*00b67f09SDavid van Moolenbroek 	}
1289*00b67f09SDavid van Moolenbroek 	return (result);
1290*00b67f09SDavid van Moolenbroek }
1291*00b67f09SDavid van Moolenbroek 
1292*00b67f09SDavid van Moolenbroek static void
dump_quantum(isc_task_t * task,isc_event_t * event)1293*00b67f09SDavid van Moolenbroek dump_quantum(isc_task_t *task, isc_event_t *event) {
1294*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1295*00b67f09SDavid van Moolenbroek 	isc_result_t tresult;
1296*00b67f09SDavid van Moolenbroek 	dns_dumpctx_t *dctx;
1297*00b67f09SDavid van Moolenbroek 
1298*00b67f09SDavid van Moolenbroek 	REQUIRE(event != NULL);
1299*00b67f09SDavid van Moolenbroek 	dctx = event->ev_arg;
1300*00b67f09SDavid van Moolenbroek 	REQUIRE(DNS_DCTX_VALID(dctx));
1301*00b67f09SDavid van Moolenbroek 	if (dctx->canceled)
1302*00b67f09SDavid van Moolenbroek 		result = ISC_R_CANCELED;
1303*00b67f09SDavid van Moolenbroek 	else
1304*00b67f09SDavid van Moolenbroek 		result = dumptostreaminc(dctx);
1305*00b67f09SDavid van Moolenbroek 	if (result == DNS_R_CONTINUE) {
1306*00b67f09SDavid van Moolenbroek 		event->ev_arg = dctx;
1307*00b67f09SDavid van Moolenbroek 		isc_task_send(task, &event);
1308*00b67f09SDavid van Moolenbroek 		return;
1309*00b67f09SDavid van Moolenbroek 	}
1310*00b67f09SDavid van Moolenbroek 
1311*00b67f09SDavid van Moolenbroek 	if (dctx->file != NULL) {
1312*00b67f09SDavid van Moolenbroek 		tresult = closeandrename(dctx->f, result,
1313*00b67f09SDavid van Moolenbroek 					 dctx->tmpfile, dctx->file);
1314*00b67f09SDavid van Moolenbroek 		if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
1315*00b67f09SDavid van Moolenbroek 			result = tresult;
1316*00b67f09SDavid van Moolenbroek 	} else
1317*00b67f09SDavid van Moolenbroek 		result = flushandsync(dctx->f, result, NULL);
1318*00b67f09SDavid van Moolenbroek 	(dctx->done)(dctx->done_arg, result);
1319*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
1320*00b67f09SDavid van Moolenbroek 	dns_dumpctx_detach(&dctx);
1321*00b67f09SDavid van Moolenbroek }
1322*00b67f09SDavid van Moolenbroek 
1323*00b67f09SDavid van Moolenbroek static isc_result_t
task_send(dns_dumpctx_t * dctx)1324*00b67f09SDavid van Moolenbroek task_send(dns_dumpctx_t *dctx) {
1325*00b67f09SDavid van Moolenbroek 	isc_event_t *event;
1326*00b67f09SDavid van Moolenbroek 
1327*00b67f09SDavid van Moolenbroek 	event = isc_event_allocate(dctx->mctx, NULL, DNS_EVENT_DUMPQUANTUM,
1328*00b67f09SDavid van Moolenbroek 				   dump_quantum, dctx, sizeof(*event));
1329*00b67f09SDavid van Moolenbroek 	if (event == NULL)
1330*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
1331*00b67f09SDavid van Moolenbroek 	isc_task_send(dctx->task, &event);
1332*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
1333*00b67f09SDavid van Moolenbroek }
1334*00b67f09SDavid van Moolenbroek 
1335*00b67f09SDavid van Moolenbroek static isc_result_t
dumpctx_create(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,FILE * f,dns_dumpctx_t ** dctxp,dns_masterformat_t format,dns_masterrawheader_t * header)1336*00b67f09SDavid van Moolenbroek dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1337*00b67f09SDavid van Moolenbroek 	       const dns_master_style_t *style, FILE *f, dns_dumpctx_t **dctxp,
1338*00b67f09SDavid van Moolenbroek 	       dns_masterformat_t format, dns_masterrawheader_t *header)
1339*00b67f09SDavid van Moolenbroek {
1340*00b67f09SDavid van Moolenbroek 	dns_dumpctx_t *dctx;
1341*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1342*00b67f09SDavid van Moolenbroek 	unsigned int options;
1343*00b67f09SDavid van Moolenbroek 
1344*00b67f09SDavid van Moolenbroek 	dctx = isc_mem_get(mctx, sizeof(*dctx));
1345*00b67f09SDavid van Moolenbroek 	if (dctx == NULL)
1346*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
1347*00b67f09SDavid van Moolenbroek 
1348*00b67f09SDavid van Moolenbroek 	dctx->mctx = NULL;
1349*00b67f09SDavid van Moolenbroek 	dctx->f = f;
1350*00b67f09SDavid van Moolenbroek 	dctx->dbiter = NULL;
1351*00b67f09SDavid van Moolenbroek 	dctx->db = NULL;
1352*00b67f09SDavid van Moolenbroek 	dctx->version = NULL;
1353*00b67f09SDavid van Moolenbroek 	dctx->done = NULL;
1354*00b67f09SDavid van Moolenbroek 	dctx->done_arg = NULL;
1355*00b67f09SDavid van Moolenbroek 	dctx->task = NULL;
1356*00b67f09SDavid van Moolenbroek 	dctx->nodes = 0;
1357*00b67f09SDavid van Moolenbroek 	dctx->first = ISC_TRUE;
1358*00b67f09SDavid van Moolenbroek 	dctx->canceled = ISC_FALSE;
1359*00b67f09SDavid van Moolenbroek 	dctx->file = NULL;
1360*00b67f09SDavid van Moolenbroek 	dctx->tmpfile = NULL;
1361*00b67f09SDavid van Moolenbroek 	dctx->format = format;
1362*00b67f09SDavid van Moolenbroek 	if (header == NULL)
1363*00b67f09SDavid van Moolenbroek 		dns_master_initrawheader(&dctx->header);
1364*00b67f09SDavid van Moolenbroek 	else
1365*00b67f09SDavid van Moolenbroek 		dctx->header = *header;
1366*00b67f09SDavid van Moolenbroek 
1367*00b67f09SDavid van Moolenbroek 	switch (format) {
1368*00b67f09SDavid van Moolenbroek 	case dns_masterformat_text:
1369*00b67f09SDavid van Moolenbroek 		dctx->dumpsets = dump_rdatasets_text;
1370*00b67f09SDavid van Moolenbroek 		break;
1371*00b67f09SDavid van Moolenbroek 	case dns_masterformat_raw:
1372*00b67f09SDavid van Moolenbroek 		dctx->dumpsets = dump_rdatasets_raw;
1373*00b67f09SDavid van Moolenbroek 		break;
1374*00b67f09SDavid van Moolenbroek 	case dns_masterformat_map:
1375*00b67f09SDavid van Moolenbroek 		dctx->dumpsets = dump_rdatasets_map;
1376*00b67f09SDavid van Moolenbroek 		break;
1377*00b67f09SDavid van Moolenbroek 	default:
1378*00b67f09SDavid van Moolenbroek 		INSIST(0);
1379*00b67f09SDavid van Moolenbroek 		break;
1380*00b67f09SDavid van Moolenbroek 	}
1381*00b67f09SDavid van Moolenbroek 
1382*00b67f09SDavid van Moolenbroek 	result = totext_ctx_init(style, &dctx->tctx);
1383*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1384*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
1385*00b67f09SDavid van Moolenbroek 				 "could not set master file style");
1386*00b67f09SDavid van Moolenbroek 		goto cleanup;
1387*00b67f09SDavid van Moolenbroek 	}
1388*00b67f09SDavid van Moolenbroek 
1389*00b67f09SDavid van Moolenbroek 	isc_stdtime_get(&dctx->now);
1390*00b67f09SDavid van Moolenbroek 	dns_db_attach(db, &dctx->db);
1391*00b67f09SDavid van Moolenbroek 
1392*00b67f09SDavid van Moolenbroek 	dctx->do_date = dns_db_iscache(dctx->db);
1393*00b67f09SDavid van Moolenbroek 
1394*00b67f09SDavid van Moolenbroek 	if (dctx->format == dns_masterformat_text &&
1395*00b67f09SDavid van Moolenbroek 	    (dctx->tctx.style.flags & DNS_STYLEFLAG_REL_OWNER) != 0) {
1396*00b67f09SDavid van Moolenbroek 		options = DNS_DB_RELATIVENAMES;
1397*00b67f09SDavid van Moolenbroek 	} else
1398*00b67f09SDavid van Moolenbroek 		options = 0;
1399*00b67f09SDavid van Moolenbroek 	result = dns_db_createiterator(dctx->db, options, &dctx->dbiter);
1400*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1401*00b67f09SDavid van Moolenbroek 		goto cleanup;
1402*00b67f09SDavid van Moolenbroek 
1403*00b67f09SDavid van Moolenbroek 	result = isc_mutex_init(&dctx->lock);
1404*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1405*00b67f09SDavid van Moolenbroek 		goto cleanup;
1406*00b67f09SDavid van Moolenbroek 	if (version != NULL)
1407*00b67f09SDavid van Moolenbroek 		dns_db_attachversion(dctx->db, version, &dctx->version);
1408*00b67f09SDavid van Moolenbroek 	else if (!dns_db_iscache(db))
1409*00b67f09SDavid van Moolenbroek 		dns_db_currentversion(dctx->db, &dctx->version);
1410*00b67f09SDavid van Moolenbroek 	isc_mem_attach(mctx, &dctx->mctx);
1411*00b67f09SDavid van Moolenbroek 	dctx->references = 1;
1412*00b67f09SDavid van Moolenbroek 	dctx->magic = DNS_DCTX_MAGIC;
1413*00b67f09SDavid van Moolenbroek 	*dctxp = dctx;
1414*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
1415*00b67f09SDavid van Moolenbroek 
1416*00b67f09SDavid van Moolenbroek  cleanup:
1417*00b67f09SDavid van Moolenbroek 	if (dctx->dbiter != NULL)
1418*00b67f09SDavid van Moolenbroek 		dns_dbiterator_destroy(&dctx->dbiter);
1419*00b67f09SDavid van Moolenbroek 	if (dctx->db != NULL)
1420*00b67f09SDavid van Moolenbroek 		dns_db_detach(&dctx->db);
1421*00b67f09SDavid van Moolenbroek 	if (dctx != NULL)
1422*00b67f09SDavid van Moolenbroek 		isc_mem_put(mctx, dctx, sizeof(*dctx));
1423*00b67f09SDavid van Moolenbroek 	return (result);
1424*00b67f09SDavid van Moolenbroek }
1425*00b67f09SDavid van Moolenbroek 
1426*00b67f09SDavid van Moolenbroek static isc_result_t
writeheader(dns_dumpctx_t * dctx)1427*00b67f09SDavid van Moolenbroek writeheader(dns_dumpctx_t *dctx) {
1428*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
1429*00b67f09SDavid van Moolenbroek 	isc_buffer_t buffer;
1430*00b67f09SDavid van Moolenbroek 	char *bufmem;
1431*00b67f09SDavid van Moolenbroek 	isc_region_t r;
1432*00b67f09SDavid van Moolenbroek 	dns_masterrawheader_t rawheader;
1433*00b67f09SDavid van Moolenbroek 	isc_uint32_t rawversion, now32;
1434*00b67f09SDavid van Moolenbroek 
1435*00b67f09SDavid van Moolenbroek 	bufmem = isc_mem_get(dctx->mctx, initial_buffer_length);
1436*00b67f09SDavid van Moolenbroek 	if (bufmem == NULL)
1437*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
1438*00b67f09SDavid van Moolenbroek 
1439*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&buffer, bufmem, initial_buffer_length);
1440*00b67f09SDavid van Moolenbroek 
1441*00b67f09SDavid van Moolenbroek 	switch (dctx->format) {
1442*00b67f09SDavid van Moolenbroek 	case dns_masterformat_text:
1443*00b67f09SDavid van Moolenbroek 		/*
1444*00b67f09SDavid van Moolenbroek 		 * If the database has cache semantics, output an
1445*00b67f09SDavid van Moolenbroek 		 * RFC2540 $DATE directive so that the TTLs can be
1446*00b67f09SDavid van Moolenbroek 		 * adjusted when it is reloaded.  For zones it is not
1447*00b67f09SDavid van Moolenbroek 		 * really needed, and it would make the file
1448*00b67f09SDavid van Moolenbroek 		 * incompatible with pre-RFC2540 software, so we omit
1449*00b67f09SDavid van Moolenbroek 		 * it in the zone case.
1450*00b67f09SDavid van Moolenbroek 		 */
1451*00b67f09SDavid van Moolenbroek 		if (dctx->do_date) {
1452*00b67f09SDavid van Moolenbroek 			result = dns_time32_totext(dctx->now, &buffer);
1453*00b67f09SDavid van Moolenbroek 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
1454*00b67f09SDavid van Moolenbroek 			isc_buffer_usedregion(&buffer, &r);
1455*00b67f09SDavid van Moolenbroek 			fprintf(dctx->f, "$DATE %.*s\n",
1456*00b67f09SDavid van Moolenbroek 				(int) r.length, (char *) r.base);
1457*00b67f09SDavid van Moolenbroek 		}
1458*00b67f09SDavid van Moolenbroek 		break;
1459*00b67f09SDavid van Moolenbroek 	case dns_masterformat_raw:
1460*00b67f09SDavid van Moolenbroek 	case dns_masterformat_map:
1461*00b67f09SDavid van Moolenbroek 		r.base = (unsigned char *)&rawheader;
1462*00b67f09SDavid van Moolenbroek 		r.length = sizeof(rawheader);
1463*00b67f09SDavid van Moolenbroek 		isc_buffer_region(&buffer, &r);
1464*00b67f09SDavid van Moolenbroek #if !defined(STDTIME_ON_32BITS) || (STDTIME_ON_32BITS + 0) != 1
1465*00b67f09SDavid van Moolenbroek 		/*
1466*00b67f09SDavid van Moolenbroek 		 * We assume isc_stdtime_t is a 32-bit integer,
1467*00b67f09SDavid van Moolenbroek 		 * which should be the case on most platforms.
1468*00b67f09SDavid van Moolenbroek 		 * If it turns out to be uncommon, we'll need
1469*00b67f09SDavid van Moolenbroek 		 * to bump the version number and revise the
1470*00b67f09SDavid van Moolenbroek 		 * header format.
1471*00b67f09SDavid van Moolenbroek 		 */
1472*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx,
1473*00b67f09SDavid van Moolenbroek 			      ISC_LOGCATEGORY_GENERAL,
1474*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_MASTERDUMP,
1475*00b67f09SDavid van Moolenbroek 			      ISC_LOG_INFO,
1476*00b67f09SDavid van Moolenbroek 			      "dumping master file in raw "
1477*00b67f09SDavid van Moolenbroek 			      "format: stdtime is not 32bits");
1478*00b67f09SDavid van Moolenbroek 		now32 = 0;
1479*00b67f09SDavid van Moolenbroek #else
1480*00b67f09SDavid van Moolenbroek 		now32 = dctx->now;
1481*00b67f09SDavid van Moolenbroek #endif
1482*00b67f09SDavid van Moolenbroek 		rawversion = 1;
1483*00b67f09SDavid van Moolenbroek 		if ((dctx->header.flags & DNS_MASTERRAW_COMPAT) != 0)
1484*00b67f09SDavid van Moolenbroek 			rawversion = 0;
1485*00b67f09SDavid van Moolenbroek 
1486*00b67f09SDavid van Moolenbroek 		isc_buffer_putuint32(&buffer, dctx->format);
1487*00b67f09SDavid van Moolenbroek 		isc_buffer_putuint32(&buffer, rawversion);
1488*00b67f09SDavid van Moolenbroek 		isc_buffer_putuint32(&buffer, now32);
1489*00b67f09SDavid van Moolenbroek 
1490*00b67f09SDavid van Moolenbroek 		if (rawversion == 1) {
1491*00b67f09SDavid van Moolenbroek 			isc_buffer_putuint32(&buffer, dctx->header.flags);
1492*00b67f09SDavid van Moolenbroek 			isc_buffer_putuint32(&buffer,
1493*00b67f09SDavid van Moolenbroek 					     dctx->header.sourceserial);
1494*00b67f09SDavid van Moolenbroek 			isc_buffer_putuint32(&buffer, dctx->header.lastxfrin);
1495*00b67f09SDavid van Moolenbroek 		}
1496*00b67f09SDavid van Moolenbroek 
1497*00b67f09SDavid van Moolenbroek 		INSIST(isc_buffer_usedlength(&buffer) <= sizeof(rawheader));
1498*00b67f09SDavid van Moolenbroek 		result = isc_stdio_write(buffer.base, 1,
1499*00b67f09SDavid van Moolenbroek 					 isc_buffer_usedlength(&buffer),
1500*00b67f09SDavid van Moolenbroek 					 dctx->f, NULL);
1501*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
1502*00b67f09SDavid van Moolenbroek 			break;
1503*00b67f09SDavid van Moolenbroek 
1504*00b67f09SDavid van Moolenbroek 		break;
1505*00b67f09SDavid van Moolenbroek 	default:
1506*00b67f09SDavid van Moolenbroek 		INSIST(0);
1507*00b67f09SDavid van Moolenbroek 	}
1508*00b67f09SDavid van Moolenbroek 
1509*00b67f09SDavid van Moolenbroek 	isc_mem_put(dctx->mctx, buffer.base, buffer.length);
1510*00b67f09SDavid van Moolenbroek 	return (result);
1511*00b67f09SDavid van Moolenbroek }
1512*00b67f09SDavid van Moolenbroek 
1513*00b67f09SDavid van Moolenbroek static isc_result_t
dumptostreaminc(dns_dumpctx_t * dctx)1514*00b67f09SDavid van Moolenbroek dumptostreaminc(dns_dumpctx_t *dctx) {
1515*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
1516*00b67f09SDavid van Moolenbroek 	isc_buffer_t buffer;
1517*00b67f09SDavid van Moolenbroek 	char *bufmem;
1518*00b67f09SDavid van Moolenbroek 	dns_name_t *name;
1519*00b67f09SDavid van Moolenbroek 	dns_fixedname_t fixname;
1520*00b67f09SDavid van Moolenbroek 	unsigned int nodes;
1521*00b67f09SDavid van Moolenbroek 	isc_time_t start;
1522*00b67f09SDavid van Moolenbroek 
1523*00b67f09SDavid van Moolenbroek 	bufmem = isc_mem_get(dctx->mctx, initial_buffer_length);
1524*00b67f09SDavid van Moolenbroek 	if (bufmem == NULL)
1525*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
1526*00b67f09SDavid van Moolenbroek 
1527*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&buffer, bufmem, initial_buffer_length);
1528*00b67f09SDavid van Moolenbroek 
1529*00b67f09SDavid van Moolenbroek 	dns_fixedname_init(&fixname);
1530*00b67f09SDavid van Moolenbroek 	name = dns_fixedname_name(&fixname);
1531*00b67f09SDavid van Moolenbroek 
1532*00b67f09SDavid van Moolenbroek 	if (dctx->first) {
1533*00b67f09SDavid van Moolenbroek 		CHECK(writeheader(dctx));
1534*00b67f09SDavid van Moolenbroek 
1535*00b67f09SDavid van Moolenbroek 		/*
1536*00b67f09SDavid van Moolenbroek 		 * Fast format is not currently written incrementally,
1537*00b67f09SDavid van Moolenbroek 		 * so we make the call to dns_db_serialize() here.
1538*00b67f09SDavid van Moolenbroek 		 * If the database is anything other than an rbtdb,
1539*00b67f09SDavid van Moolenbroek 		 * this should result in not implemented
1540*00b67f09SDavid van Moolenbroek 		 */
1541*00b67f09SDavid van Moolenbroek 		if (dctx->format == dns_masterformat_map) {
1542*00b67f09SDavid van Moolenbroek 			result = dns_db_serialize(dctx->db, dctx->version,
1543*00b67f09SDavid van Moolenbroek 						  dctx->f);
1544*00b67f09SDavid van Moolenbroek 			goto cleanup;
1545*00b67f09SDavid van Moolenbroek 		}
1546*00b67f09SDavid van Moolenbroek 
1547*00b67f09SDavid van Moolenbroek 		result = dns_dbiterator_first(dctx->dbiter);
1548*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
1549*00b67f09SDavid van Moolenbroek 			goto cleanup;
1550*00b67f09SDavid van Moolenbroek 
1551*00b67f09SDavid van Moolenbroek 		dctx->first = ISC_FALSE;
1552*00b67f09SDavid van Moolenbroek 	} else
1553*00b67f09SDavid van Moolenbroek 		result = ISC_R_SUCCESS;
1554*00b67f09SDavid van Moolenbroek 
1555*00b67f09SDavid van Moolenbroek 	nodes = dctx->nodes;
1556*00b67f09SDavid van Moolenbroek 	isc_time_now(&start);
1557*00b67f09SDavid van Moolenbroek 	while (result == ISC_R_SUCCESS && (dctx->nodes == 0 || nodes--)) {
1558*00b67f09SDavid van Moolenbroek 		dns_rdatasetiter_t *rdsiter = NULL;
1559*00b67f09SDavid van Moolenbroek 		dns_dbnode_t *node = NULL;
1560*00b67f09SDavid van Moolenbroek 
1561*00b67f09SDavid van Moolenbroek 		result = dns_dbiterator_current(dctx->dbiter, &node, name);
1562*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
1563*00b67f09SDavid van Moolenbroek 			break;
1564*00b67f09SDavid van Moolenbroek 		if (result == DNS_R_NEWORIGIN) {
1565*00b67f09SDavid van Moolenbroek 			dns_name_t *origin =
1566*00b67f09SDavid van Moolenbroek 				dns_fixedname_name(&dctx->tctx.origin_fixname);
1567*00b67f09SDavid van Moolenbroek 			result = dns_dbiterator_origin(dctx->dbiter, origin);
1568*00b67f09SDavid van Moolenbroek 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
1569*00b67f09SDavid van Moolenbroek 			if ((dctx->tctx.style.flags &
1570*00b67f09SDavid van Moolenbroek 			     DNS_STYLEFLAG_REL_DATA) != 0)
1571*00b67f09SDavid van Moolenbroek 				dctx->tctx.origin = origin;
1572*00b67f09SDavid van Moolenbroek 			dctx->tctx.neworigin = origin;
1573*00b67f09SDavid van Moolenbroek 		}
1574*00b67f09SDavid van Moolenbroek 		result = dns_db_allrdatasets(dctx->db, node, dctx->version,
1575*00b67f09SDavid van Moolenbroek 					     dctx->now, &rdsiter);
1576*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
1577*00b67f09SDavid van Moolenbroek 			dns_db_detachnode(dctx->db, &node);
1578*00b67f09SDavid van Moolenbroek 			goto cleanup;
1579*00b67f09SDavid van Moolenbroek 		}
1580*00b67f09SDavid van Moolenbroek 		result = (dctx->dumpsets)(dctx->mctx, name, rdsiter,
1581*00b67f09SDavid van Moolenbroek 					  &dctx->tctx, &buffer, dctx->f);
1582*00b67f09SDavid van Moolenbroek 		dns_rdatasetiter_destroy(&rdsiter);
1583*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
1584*00b67f09SDavid van Moolenbroek 			dns_db_detachnode(dctx->db, &node);
1585*00b67f09SDavid van Moolenbroek 			goto cleanup;
1586*00b67f09SDavid van Moolenbroek 		}
1587*00b67f09SDavid van Moolenbroek 		dns_db_detachnode(dctx->db, &node);
1588*00b67f09SDavid van Moolenbroek 		result = dns_dbiterator_next(dctx->dbiter);
1589*00b67f09SDavid van Moolenbroek 	}
1590*00b67f09SDavid van Moolenbroek 
1591*00b67f09SDavid van Moolenbroek 	/*
1592*00b67f09SDavid van Moolenbroek 	 * Work out how many nodes can be written in the time between
1593*00b67f09SDavid van Moolenbroek 	 * two requests to the nameserver.  Smooth the resulting number and
1594*00b67f09SDavid van Moolenbroek 	 * use it as a estimate for the number of nodes to be written in the
1595*00b67f09SDavid van Moolenbroek 	 * next iteration.
1596*00b67f09SDavid van Moolenbroek 	 */
1597*00b67f09SDavid van Moolenbroek 	if (dctx->nodes != 0 && result == ISC_R_SUCCESS) {
1598*00b67f09SDavid van Moolenbroek 		unsigned int pps = dns_pps;	/* packets per second */
1599*00b67f09SDavid van Moolenbroek 		unsigned int interval;
1600*00b67f09SDavid van Moolenbroek 		isc_uint64_t usecs;
1601*00b67f09SDavid van Moolenbroek 		isc_time_t end;
1602*00b67f09SDavid van Moolenbroek 
1603*00b67f09SDavid van Moolenbroek 		isc_time_now(&end);
1604*00b67f09SDavid van Moolenbroek 		if (pps < 100)
1605*00b67f09SDavid van Moolenbroek 			pps = 100;
1606*00b67f09SDavid van Moolenbroek 		interval = 1000000 / pps;	/* interval in usecs */
1607*00b67f09SDavid van Moolenbroek 		if (interval == 0)
1608*00b67f09SDavid van Moolenbroek 			interval = 1;
1609*00b67f09SDavid van Moolenbroek 		usecs = isc_time_microdiff(&end, &start);
1610*00b67f09SDavid van Moolenbroek 		if (usecs == 0) {
1611*00b67f09SDavid van Moolenbroek 			dctx->nodes = dctx->nodes * 2;
1612*00b67f09SDavid van Moolenbroek 			if (dctx->nodes > 1000)
1613*00b67f09SDavid van Moolenbroek 				dctx->nodes = 1000;
1614*00b67f09SDavid van Moolenbroek 		} else {
1615*00b67f09SDavid van Moolenbroek 			nodes = dctx->nodes * interval;
1616*00b67f09SDavid van Moolenbroek 			nodes /= (unsigned int)usecs;
1617*00b67f09SDavid van Moolenbroek 			if (nodes == 0)
1618*00b67f09SDavid van Moolenbroek 				nodes = 1;
1619*00b67f09SDavid van Moolenbroek 			else if (nodes > 1000)
1620*00b67f09SDavid van Moolenbroek 				nodes = 1000;
1621*00b67f09SDavid van Moolenbroek 
1622*00b67f09SDavid van Moolenbroek 			/* Smooth and assign. */
1623*00b67f09SDavid van Moolenbroek 			dctx->nodes = (nodes + dctx->nodes * 7) / 8;
1624*00b67f09SDavid van Moolenbroek 
1625*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1626*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_MASTERDUMP,
1627*00b67f09SDavid van Moolenbroek 				      ISC_LOG_DEBUG(1),
1628*00b67f09SDavid van Moolenbroek 				      "dumptostreaminc(%p) new nodes -> %d\n",
1629*00b67f09SDavid van Moolenbroek 				      dctx, dctx->nodes);
1630*00b67f09SDavid van Moolenbroek 		}
1631*00b67f09SDavid van Moolenbroek 		result = DNS_R_CONTINUE;
1632*00b67f09SDavid van Moolenbroek 	} else if (result == ISC_R_NOMORE)
1633*00b67f09SDavid van Moolenbroek 		result = ISC_R_SUCCESS;
1634*00b67f09SDavid van Moolenbroek  cleanup:
1635*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(dns_dbiterator_pause(dctx->dbiter) == ISC_R_SUCCESS);
1636*00b67f09SDavid van Moolenbroek 	isc_mem_put(dctx->mctx, buffer.base, buffer.length);
1637*00b67f09SDavid van Moolenbroek 	return (result);
1638*00b67f09SDavid van Moolenbroek }
1639*00b67f09SDavid van Moolenbroek 
1640*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumptostreaminc(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,FILE * f,isc_task_t * task,dns_dumpdonefunc_t done,void * done_arg,dns_dumpctx_t ** dctxp)1641*00b67f09SDavid van Moolenbroek dns_master_dumptostreaminc(isc_mem_t *mctx, dns_db_t *db,
1642*00b67f09SDavid van Moolenbroek 			   dns_dbversion_t *version,
1643*00b67f09SDavid van Moolenbroek 			   const dns_master_style_t *style,
1644*00b67f09SDavid van Moolenbroek 			   FILE *f, isc_task_t *task,
1645*00b67f09SDavid van Moolenbroek 			   dns_dumpdonefunc_t done, void *done_arg,
1646*00b67f09SDavid van Moolenbroek 			   dns_dumpctx_t **dctxp)
1647*00b67f09SDavid van Moolenbroek {
1648*00b67f09SDavid van Moolenbroek 	dns_dumpctx_t *dctx = NULL;
1649*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1650*00b67f09SDavid van Moolenbroek 
1651*00b67f09SDavid van Moolenbroek 	REQUIRE(task != NULL);
1652*00b67f09SDavid van Moolenbroek 	REQUIRE(f != NULL);
1653*00b67f09SDavid van Moolenbroek 	REQUIRE(done != NULL);
1654*00b67f09SDavid van Moolenbroek 
1655*00b67f09SDavid van Moolenbroek 	result = dumpctx_create(mctx, db, version, style, f, &dctx,
1656*00b67f09SDavid van Moolenbroek 				dns_masterformat_text, NULL);
1657*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1658*00b67f09SDavid van Moolenbroek 		return (result);
1659*00b67f09SDavid van Moolenbroek 	isc_task_attach(task, &dctx->task);
1660*00b67f09SDavid van Moolenbroek 	dctx->done = done;
1661*00b67f09SDavid van Moolenbroek 	dctx->done_arg = done_arg;
1662*00b67f09SDavid van Moolenbroek 	dctx->nodes = 100;
1663*00b67f09SDavid van Moolenbroek 
1664*00b67f09SDavid van Moolenbroek 	result = task_send(dctx);
1665*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS) {
1666*00b67f09SDavid van Moolenbroek 		dns_dumpctx_attach(dctx, dctxp);
1667*00b67f09SDavid van Moolenbroek 		return (DNS_R_CONTINUE);
1668*00b67f09SDavid van Moolenbroek 	}
1669*00b67f09SDavid van Moolenbroek 
1670*00b67f09SDavid van Moolenbroek 	dns_dumpctx_detach(&dctx);
1671*00b67f09SDavid van Moolenbroek 	return (result);
1672*00b67f09SDavid van Moolenbroek }
1673*00b67f09SDavid van Moolenbroek 
1674*00b67f09SDavid van Moolenbroek /*
1675*00b67f09SDavid van Moolenbroek  * Dump an entire database into a master file.
1676*00b67f09SDavid van Moolenbroek  */
1677*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumptostream(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,FILE * f)1678*00b67f09SDavid van Moolenbroek dns_master_dumptostream(isc_mem_t *mctx, dns_db_t *db,
1679*00b67f09SDavid van Moolenbroek 			dns_dbversion_t *version,
1680*00b67f09SDavid van Moolenbroek 			const dns_master_style_t *style,
1681*00b67f09SDavid van Moolenbroek 			FILE *f)
1682*00b67f09SDavid van Moolenbroek {
1683*00b67f09SDavid van Moolenbroek 	return (dns_master_dumptostream3(mctx, db, version, style,
1684*00b67f09SDavid van Moolenbroek 					 dns_masterformat_text, NULL, f));
1685*00b67f09SDavid van Moolenbroek }
1686*00b67f09SDavid van Moolenbroek 
1687*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumptostream2(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,dns_masterformat_t format,FILE * f)1688*00b67f09SDavid van Moolenbroek dns_master_dumptostream2(isc_mem_t *mctx, dns_db_t *db,
1689*00b67f09SDavid van Moolenbroek 			 dns_dbversion_t *version,
1690*00b67f09SDavid van Moolenbroek 			 const dns_master_style_t *style,
1691*00b67f09SDavid van Moolenbroek 			 dns_masterformat_t format, FILE *f)
1692*00b67f09SDavid van Moolenbroek {
1693*00b67f09SDavid van Moolenbroek 	return (dns_master_dumptostream3(mctx, db, version, style,
1694*00b67f09SDavid van Moolenbroek 					 format, NULL, f));
1695*00b67f09SDavid van Moolenbroek }
1696*00b67f09SDavid van Moolenbroek 
1697*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumptostream3(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,dns_masterformat_t format,dns_masterrawheader_t * header,FILE * f)1698*00b67f09SDavid van Moolenbroek dns_master_dumptostream3(isc_mem_t *mctx, dns_db_t *db,
1699*00b67f09SDavid van Moolenbroek 			 dns_dbversion_t *version,
1700*00b67f09SDavid van Moolenbroek 			 const dns_master_style_t *style,
1701*00b67f09SDavid van Moolenbroek 			 dns_masterformat_t format,
1702*00b67f09SDavid van Moolenbroek 			 dns_masterrawheader_t *header, FILE *f)
1703*00b67f09SDavid van Moolenbroek {
1704*00b67f09SDavid van Moolenbroek 	dns_dumpctx_t *dctx = NULL;
1705*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1706*00b67f09SDavid van Moolenbroek 
1707*00b67f09SDavid van Moolenbroek 	result = dumpctx_create(mctx, db, version, style, f, &dctx,
1708*00b67f09SDavid van Moolenbroek 				format, header);
1709*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1710*00b67f09SDavid van Moolenbroek 		return (result);
1711*00b67f09SDavid van Moolenbroek 
1712*00b67f09SDavid van Moolenbroek 	result = dumptostreaminc(dctx);
1713*00b67f09SDavid van Moolenbroek 	INSIST(result != DNS_R_CONTINUE);
1714*00b67f09SDavid van Moolenbroek 	dns_dumpctx_detach(&dctx);
1715*00b67f09SDavid van Moolenbroek 
1716*00b67f09SDavid van Moolenbroek 	result = flushandsync(f, result, NULL);
1717*00b67f09SDavid van Moolenbroek 	return (result);
1718*00b67f09SDavid van Moolenbroek }
1719*00b67f09SDavid van Moolenbroek 
1720*00b67f09SDavid van Moolenbroek static isc_result_t
opentmp(isc_mem_t * mctx,dns_masterformat_t format,const char * file,char ** tempp,FILE ** fp)1721*00b67f09SDavid van Moolenbroek opentmp(isc_mem_t *mctx, dns_masterformat_t format, const char *file,
1722*00b67f09SDavid van Moolenbroek 	char **tempp, FILE **fp) {
1723*00b67f09SDavid van Moolenbroek 	FILE *f = NULL;
1724*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1725*00b67f09SDavid van Moolenbroek 	char *tempname = NULL;
1726*00b67f09SDavid van Moolenbroek 	int tempnamelen;
1727*00b67f09SDavid van Moolenbroek 
1728*00b67f09SDavid van Moolenbroek 	tempnamelen = strlen(file) + 20;
1729*00b67f09SDavid van Moolenbroek 	tempname = isc_mem_allocate(mctx, tempnamelen);
1730*00b67f09SDavid van Moolenbroek 	if (tempname == NULL)
1731*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
1732*00b67f09SDavid van Moolenbroek 
1733*00b67f09SDavid van Moolenbroek 	result = isc_file_mktemplate(file, tempname, tempnamelen);
1734*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1735*00b67f09SDavid van Moolenbroek 		goto cleanup;
1736*00b67f09SDavid van Moolenbroek 
1737*00b67f09SDavid van Moolenbroek 	if (format == dns_masterformat_text)
1738*00b67f09SDavid van Moolenbroek 		result = isc_file_openunique(tempname, &f);
1739*00b67f09SDavid van Moolenbroek 	else
1740*00b67f09SDavid van Moolenbroek 		result = isc_file_bopenunique(tempname, &f);
1741*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1742*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1743*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1744*00b67f09SDavid van Moolenbroek 			      "dumping master file: %s: open: %s",
1745*00b67f09SDavid van Moolenbroek 			      tempname, isc_result_totext(result));
1746*00b67f09SDavid van Moolenbroek 		goto cleanup;
1747*00b67f09SDavid van Moolenbroek 	}
1748*00b67f09SDavid van Moolenbroek 	*tempp = tempname;
1749*00b67f09SDavid van Moolenbroek 	*fp = f;
1750*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
1751*00b67f09SDavid van Moolenbroek 
1752*00b67f09SDavid van Moolenbroek cleanup:
1753*00b67f09SDavid van Moolenbroek 	isc_mem_free(mctx, tempname);
1754*00b67f09SDavid van Moolenbroek 	return (result);
1755*00b67f09SDavid van Moolenbroek }
1756*00b67f09SDavid van Moolenbroek 
1757*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumpinc(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,const char * filename,isc_task_t * task,dns_dumpdonefunc_t done,void * done_arg,dns_dumpctx_t ** dctxp)1758*00b67f09SDavid van Moolenbroek dns_master_dumpinc(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1759*00b67f09SDavid van Moolenbroek 		   const dns_master_style_t *style, const char *filename,
1760*00b67f09SDavid van Moolenbroek 		   isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg,
1761*00b67f09SDavid van Moolenbroek 		   dns_dumpctx_t **dctxp)
1762*00b67f09SDavid van Moolenbroek {
1763*00b67f09SDavid van Moolenbroek 	return (dns_master_dumpinc3(mctx, db, version, style, filename, task,
1764*00b67f09SDavid van Moolenbroek 				    done, done_arg, dctxp,
1765*00b67f09SDavid van Moolenbroek 				    dns_masterformat_text, NULL));
1766*00b67f09SDavid van Moolenbroek }
1767*00b67f09SDavid van Moolenbroek 
1768*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumpinc2(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,const char * filename,isc_task_t * task,dns_dumpdonefunc_t done,void * done_arg,dns_dumpctx_t ** dctxp,dns_masterformat_t format)1769*00b67f09SDavid van Moolenbroek dns_master_dumpinc2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1770*00b67f09SDavid van Moolenbroek 		    const dns_master_style_t *style, const char *filename,
1771*00b67f09SDavid van Moolenbroek 		    isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg,
1772*00b67f09SDavid van Moolenbroek 		    dns_dumpctx_t **dctxp, dns_masterformat_t format)
1773*00b67f09SDavid van Moolenbroek {
1774*00b67f09SDavid van Moolenbroek 	return (dns_master_dumpinc3(mctx, db, version, style, filename, task,
1775*00b67f09SDavid van Moolenbroek 				    done, done_arg, dctxp, format, NULL));
1776*00b67f09SDavid van Moolenbroek }
1777*00b67f09SDavid van Moolenbroek 
1778*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumpinc3(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,const char * filename,isc_task_t * task,dns_dumpdonefunc_t done,void * done_arg,dns_dumpctx_t ** dctxp,dns_masterformat_t format,dns_masterrawheader_t * header)1779*00b67f09SDavid van Moolenbroek dns_master_dumpinc3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1780*00b67f09SDavid van Moolenbroek 		    const dns_master_style_t *style, const char *filename,
1781*00b67f09SDavid van Moolenbroek 		    isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg,
1782*00b67f09SDavid van Moolenbroek 		    dns_dumpctx_t **dctxp, dns_masterformat_t format,
1783*00b67f09SDavid van Moolenbroek 		    dns_masterrawheader_t *header)
1784*00b67f09SDavid van Moolenbroek {
1785*00b67f09SDavid van Moolenbroek 	FILE *f = NULL;
1786*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1787*00b67f09SDavid van Moolenbroek 	char *tempname = NULL;
1788*00b67f09SDavid van Moolenbroek 	char *file = NULL;
1789*00b67f09SDavid van Moolenbroek 	dns_dumpctx_t *dctx = NULL;
1790*00b67f09SDavid van Moolenbroek 
1791*00b67f09SDavid van Moolenbroek 	file = isc_mem_strdup(mctx, filename);
1792*00b67f09SDavid van Moolenbroek 	if (file == NULL)
1793*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
1794*00b67f09SDavid van Moolenbroek 
1795*00b67f09SDavid van Moolenbroek 	result = opentmp(mctx, format, filename, &tempname, &f);
1796*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1797*00b67f09SDavid van Moolenbroek 		goto cleanup;
1798*00b67f09SDavid van Moolenbroek 
1799*00b67f09SDavid van Moolenbroek 	result = dumpctx_create(mctx, db, version, style, f, &dctx,
1800*00b67f09SDavid van Moolenbroek 				format, header);
1801*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1802*00b67f09SDavid van Moolenbroek 		(void)isc_stdio_close(f);
1803*00b67f09SDavid van Moolenbroek 		(void)isc_file_remove(tempname);
1804*00b67f09SDavid van Moolenbroek 		goto cleanup;
1805*00b67f09SDavid van Moolenbroek 	}
1806*00b67f09SDavid van Moolenbroek 
1807*00b67f09SDavid van Moolenbroek 	isc_task_attach(task, &dctx->task);
1808*00b67f09SDavid van Moolenbroek 	dctx->done = done;
1809*00b67f09SDavid van Moolenbroek 	dctx->done_arg = done_arg;
1810*00b67f09SDavid van Moolenbroek 	dctx->nodes = 100;
1811*00b67f09SDavid van Moolenbroek 	dctx->file = file;
1812*00b67f09SDavid van Moolenbroek 	file = NULL;
1813*00b67f09SDavid van Moolenbroek 	dctx->tmpfile = tempname;
1814*00b67f09SDavid van Moolenbroek 	tempname = NULL;
1815*00b67f09SDavid van Moolenbroek 
1816*00b67f09SDavid van Moolenbroek 	result = task_send(dctx);
1817*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS) {
1818*00b67f09SDavid van Moolenbroek 		dns_dumpctx_attach(dctx, dctxp);
1819*00b67f09SDavid van Moolenbroek 		return (DNS_R_CONTINUE);
1820*00b67f09SDavid van Moolenbroek 	}
1821*00b67f09SDavid van Moolenbroek 
1822*00b67f09SDavid van Moolenbroek  cleanup:
1823*00b67f09SDavid van Moolenbroek 	if (dctx != NULL)
1824*00b67f09SDavid van Moolenbroek 		dns_dumpctx_detach(&dctx);
1825*00b67f09SDavid van Moolenbroek 	if (file != NULL)
1826*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, file);
1827*00b67f09SDavid van Moolenbroek 	if (tempname != NULL)
1828*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, tempname);
1829*00b67f09SDavid van Moolenbroek 	return (result);
1830*00b67f09SDavid van Moolenbroek }
1831*00b67f09SDavid van Moolenbroek 
1832*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dump(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,const char * filename)1833*00b67f09SDavid van Moolenbroek dns_master_dump(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1834*00b67f09SDavid van Moolenbroek 		const dns_master_style_t *style, const char *filename)
1835*00b67f09SDavid van Moolenbroek {
1836*00b67f09SDavid van Moolenbroek 	return (dns_master_dump3(mctx, db, version, style, filename,
1837*00b67f09SDavid van Moolenbroek 				 dns_masterformat_text, NULL));
1838*00b67f09SDavid van Moolenbroek }
1839*00b67f09SDavid van Moolenbroek 
1840*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dump2(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,const char * filename,dns_masterformat_t format)1841*00b67f09SDavid van Moolenbroek dns_master_dump2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1842*00b67f09SDavid van Moolenbroek 		 const dns_master_style_t *style, const char *filename,
1843*00b67f09SDavid van Moolenbroek 		 dns_masterformat_t format)
1844*00b67f09SDavid van Moolenbroek {
1845*00b67f09SDavid van Moolenbroek 	return (dns_master_dump3(mctx, db, version, style, filename,
1846*00b67f09SDavid van Moolenbroek 				 format, NULL));
1847*00b67f09SDavid van Moolenbroek }
1848*00b67f09SDavid van Moolenbroek 
1849*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dump3(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,const dns_master_style_t * style,const char * filename,dns_masterformat_t format,dns_masterrawheader_t * header)1850*00b67f09SDavid van Moolenbroek dns_master_dump3(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1851*00b67f09SDavid van Moolenbroek 		 const dns_master_style_t *style, const char *filename,
1852*00b67f09SDavid van Moolenbroek 		 dns_masterformat_t format, dns_masterrawheader_t *header)
1853*00b67f09SDavid van Moolenbroek {
1854*00b67f09SDavid van Moolenbroek 	FILE *f = NULL;
1855*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1856*00b67f09SDavid van Moolenbroek 	char *tempname;
1857*00b67f09SDavid van Moolenbroek 	dns_dumpctx_t *dctx = NULL;
1858*00b67f09SDavid van Moolenbroek 
1859*00b67f09SDavid van Moolenbroek 	result = opentmp(mctx, format, filename, &tempname, &f);
1860*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1861*00b67f09SDavid van Moolenbroek 		return (result);
1862*00b67f09SDavid van Moolenbroek 
1863*00b67f09SDavid van Moolenbroek 	result = dumpctx_create(mctx, db, version, style, f, &dctx,
1864*00b67f09SDavid van Moolenbroek 				format, header);
1865*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1866*00b67f09SDavid van Moolenbroek 		goto cleanup;
1867*00b67f09SDavid van Moolenbroek 
1868*00b67f09SDavid van Moolenbroek 	result = dumptostreaminc(dctx);
1869*00b67f09SDavid van Moolenbroek 	INSIST(result != DNS_R_CONTINUE);
1870*00b67f09SDavid van Moolenbroek 	dns_dumpctx_detach(&dctx);
1871*00b67f09SDavid van Moolenbroek 
1872*00b67f09SDavid van Moolenbroek 	result = closeandrename(f, result, tempname, filename);
1873*00b67f09SDavid van Moolenbroek 
1874*00b67f09SDavid van Moolenbroek  cleanup:
1875*00b67f09SDavid van Moolenbroek 	isc_mem_free(mctx, tempname);
1876*00b67f09SDavid van Moolenbroek 	return (result);
1877*00b67f09SDavid van Moolenbroek }
1878*00b67f09SDavid van Moolenbroek 
1879*00b67f09SDavid van Moolenbroek /*
1880*00b67f09SDavid van Moolenbroek  * Dump a database node into a master file.
1881*00b67f09SDavid van Moolenbroek  * XXX: this function assumes the text format.
1882*00b67f09SDavid van Moolenbroek  */
1883*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumpnodetostream(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,dns_dbnode_t * node,dns_name_t * name,const dns_master_style_t * style,FILE * f)1884*00b67f09SDavid van Moolenbroek dns_master_dumpnodetostream(isc_mem_t *mctx, dns_db_t *db,
1885*00b67f09SDavid van Moolenbroek 			    dns_dbversion_t *version,
1886*00b67f09SDavid van Moolenbroek 			    dns_dbnode_t *node, dns_name_t *name,
1887*00b67f09SDavid van Moolenbroek 			    const dns_master_style_t *style,
1888*00b67f09SDavid van Moolenbroek 			    FILE *f)
1889*00b67f09SDavid van Moolenbroek {
1890*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1891*00b67f09SDavid van Moolenbroek 	isc_buffer_t buffer;
1892*00b67f09SDavid van Moolenbroek 	char *bufmem;
1893*00b67f09SDavid van Moolenbroek 	isc_stdtime_t now;
1894*00b67f09SDavid van Moolenbroek 	dns_totext_ctx_t ctx;
1895*00b67f09SDavid van Moolenbroek 	dns_rdatasetiter_t *rdsiter = NULL;
1896*00b67f09SDavid van Moolenbroek 
1897*00b67f09SDavid van Moolenbroek 	result = totext_ctx_init(style, &ctx);
1898*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1899*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
1900*00b67f09SDavid van Moolenbroek 				 "could not set master file style");
1901*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
1902*00b67f09SDavid van Moolenbroek 	}
1903*00b67f09SDavid van Moolenbroek 
1904*00b67f09SDavid van Moolenbroek 	isc_stdtime_get(&now);
1905*00b67f09SDavid van Moolenbroek 
1906*00b67f09SDavid van Moolenbroek 	bufmem = isc_mem_get(mctx, initial_buffer_length);
1907*00b67f09SDavid van Moolenbroek 	if (bufmem == NULL)
1908*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
1909*00b67f09SDavid van Moolenbroek 
1910*00b67f09SDavid van Moolenbroek 	isc_buffer_init(&buffer, bufmem, initial_buffer_length);
1911*00b67f09SDavid van Moolenbroek 
1912*00b67f09SDavid van Moolenbroek 	result = dns_db_allrdatasets(db, node, version, now, &rdsiter);
1913*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1914*00b67f09SDavid van Moolenbroek 		goto failure;
1915*00b67f09SDavid van Moolenbroek 	result = dump_rdatasets_text(mctx, name, rdsiter, &ctx, &buffer, f);
1916*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1917*00b67f09SDavid van Moolenbroek 		goto failure;
1918*00b67f09SDavid van Moolenbroek 	dns_rdatasetiter_destroy(&rdsiter);
1919*00b67f09SDavid van Moolenbroek 
1920*00b67f09SDavid van Moolenbroek 	result = ISC_R_SUCCESS;
1921*00b67f09SDavid van Moolenbroek 
1922*00b67f09SDavid van Moolenbroek  failure:
1923*00b67f09SDavid van Moolenbroek 	isc_mem_put(mctx, buffer.base, buffer.length);
1924*00b67f09SDavid van Moolenbroek 	return (result);
1925*00b67f09SDavid van Moolenbroek }
1926*00b67f09SDavid van Moolenbroek 
1927*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_dumpnode(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * version,dns_dbnode_t * node,dns_name_t * name,const dns_master_style_t * style,const char * filename)1928*00b67f09SDavid van Moolenbroek dns_master_dumpnode(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
1929*00b67f09SDavid van Moolenbroek 		    dns_dbnode_t *node, dns_name_t *name,
1930*00b67f09SDavid van Moolenbroek 		    const dns_master_style_t *style, const char *filename)
1931*00b67f09SDavid van Moolenbroek {
1932*00b67f09SDavid van Moolenbroek 	FILE *f = NULL;
1933*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1934*00b67f09SDavid van Moolenbroek 
1935*00b67f09SDavid van Moolenbroek 	result = isc_stdio_open(filename, "w", &f);
1936*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1937*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1938*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1939*00b67f09SDavid van Moolenbroek 			      "dumping node to file: %s: open: %s", filename,
1940*00b67f09SDavid van Moolenbroek 			      isc_result_totext(result));
1941*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
1942*00b67f09SDavid van Moolenbroek 	}
1943*00b67f09SDavid van Moolenbroek 
1944*00b67f09SDavid van Moolenbroek 	result = dns_master_dumpnodetostream(mctx, db, version, node, name,
1945*00b67f09SDavid van Moolenbroek 					     style, f);
1946*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1947*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1948*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1949*00b67f09SDavid van Moolenbroek 			      "dumping master file: %s: dump: %s", filename,
1950*00b67f09SDavid van Moolenbroek 			      isc_result_totext(result));
1951*00b67f09SDavid van Moolenbroek 		(void)isc_stdio_close(f);
1952*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
1953*00b67f09SDavid van Moolenbroek 	}
1954*00b67f09SDavid van Moolenbroek 
1955*00b67f09SDavid van Moolenbroek 	result = isc_stdio_close(f);
1956*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1957*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
1958*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
1959*00b67f09SDavid van Moolenbroek 			      "dumping master file: %s: close: %s", filename,
1960*00b67f09SDavid van Moolenbroek 			      isc_result_totext(result));
1961*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
1962*00b67f09SDavid van Moolenbroek 	}
1963*00b67f09SDavid van Moolenbroek 
1964*00b67f09SDavid van Moolenbroek 	return (result);
1965*00b67f09SDavid van Moolenbroek }
1966*00b67f09SDavid van Moolenbroek 
1967*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_stylecreate(dns_master_style_t ** stylep,unsigned int flags,unsigned int ttl_column,unsigned int class_column,unsigned int type_column,unsigned int rdata_column,unsigned int line_length,unsigned int tab_width,isc_mem_t * mctx)1968*00b67f09SDavid van Moolenbroek dns_master_stylecreate(dns_master_style_t **stylep, unsigned int flags,
1969*00b67f09SDavid van Moolenbroek 		       unsigned int ttl_column, unsigned int class_column,
1970*00b67f09SDavid van Moolenbroek 		       unsigned int type_column, unsigned int rdata_column,
1971*00b67f09SDavid van Moolenbroek 		       unsigned int line_length, unsigned int tab_width,
1972*00b67f09SDavid van Moolenbroek 		       isc_mem_t *mctx)
1973*00b67f09SDavid van Moolenbroek {
1974*00b67f09SDavid van Moolenbroek 	return (dns_master_stylecreate2(stylep, flags, ttl_column,
1975*00b67f09SDavid van Moolenbroek 					class_column, type_column,
1976*00b67f09SDavid van Moolenbroek 					rdata_column, line_length,
1977*00b67f09SDavid van Moolenbroek 					tab_width, 0xffffffff, mctx));
1978*00b67f09SDavid van Moolenbroek }
1979*00b67f09SDavid van Moolenbroek 
1980*00b67f09SDavid van Moolenbroek isc_result_t
dns_master_stylecreate2(dns_master_style_t ** stylep,unsigned int flags,unsigned int ttl_column,unsigned int class_column,unsigned int type_column,unsigned int rdata_column,unsigned int line_length,unsigned int tab_width,unsigned int split_width,isc_mem_t * mctx)1981*00b67f09SDavid van Moolenbroek dns_master_stylecreate2(dns_master_style_t **stylep, unsigned int flags,
1982*00b67f09SDavid van Moolenbroek 			unsigned int ttl_column, unsigned int class_column,
1983*00b67f09SDavid van Moolenbroek 			unsigned int type_column, unsigned int rdata_column,
1984*00b67f09SDavid van Moolenbroek 			unsigned int line_length, unsigned int tab_width,
1985*00b67f09SDavid van Moolenbroek 			unsigned int split_width, isc_mem_t *mctx)
1986*00b67f09SDavid van Moolenbroek {
1987*00b67f09SDavid van Moolenbroek 	dns_master_style_t *style;
1988*00b67f09SDavid van Moolenbroek 
1989*00b67f09SDavid van Moolenbroek 	REQUIRE(stylep != NULL && *stylep == NULL);
1990*00b67f09SDavid van Moolenbroek 	style = isc_mem_get(mctx, sizeof(*style));
1991*00b67f09SDavid van Moolenbroek 	if (style == NULL)
1992*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
1993*00b67f09SDavid van Moolenbroek 
1994*00b67f09SDavid van Moolenbroek 	style->flags = flags;
1995*00b67f09SDavid van Moolenbroek 	style->ttl_column = ttl_column;
1996*00b67f09SDavid van Moolenbroek 	style->class_column = class_column;
1997*00b67f09SDavid van Moolenbroek 	style->type_column = type_column;
1998*00b67f09SDavid van Moolenbroek 	style->rdata_column = rdata_column;
1999*00b67f09SDavid van Moolenbroek 	style->line_length = line_length;
2000*00b67f09SDavid van Moolenbroek 	style->tab_width = tab_width;
2001*00b67f09SDavid van Moolenbroek 	style->split_width = split_width;
2002*00b67f09SDavid van Moolenbroek 
2003*00b67f09SDavid van Moolenbroek 	*stylep = style;
2004*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
2005*00b67f09SDavid van Moolenbroek }
2006*00b67f09SDavid van Moolenbroek 
2007*00b67f09SDavid van Moolenbroek void
dns_master_styledestroy(dns_master_style_t ** stylep,isc_mem_t * mctx)2008*00b67f09SDavid van Moolenbroek dns_master_styledestroy(dns_master_style_t **stylep, isc_mem_t *mctx) {
2009*00b67f09SDavid van Moolenbroek 	dns_master_style_t *style;
2010*00b67f09SDavid van Moolenbroek 
2011*00b67f09SDavid van Moolenbroek 	REQUIRE(stylep != NULL && *stylep != NULL);
2012*00b67f09SDavid van Moolenbroek 	style = *stylep;
2013*00b67f09SDavid van Moolenbroek 	*stylep = NULL;
2014*00b67f09SDavid van Moolenbroek 	isc_mem_put(mctx, style, sizeof(*style));
2015*00b67f09SDavid van Moolenbroek }
2016