diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h index 200466fe72..f75f013977 100644 --- a/lib/dns/include/dns/rdata.h +++ b/lib/dns/include/dns/rdata.h @@ -126,21 +126,10 @@ struct dns_rdata { ISC_LINK(dns_rdata_t) link; }; -/* - * Context structure for the totext_ functions. Defines - * the way the rdata part of a master file line is - * formatted. - */ -typedef struct dns_rdata_textctx { - dns_name_t *origin; /* Current origin, or NULL. */ - unsigned int flags; /* DNS_STYLEFLAG_* */ - unsigned int width; /* Width of rdata column. */ - char *linebreak; /* Line break string. */ -} dns_rdata_textctx_t; - /* * Flags affecting rdata formatting style. Flags 0xFFFF0000 * are used by masterfile-level formatting and defined elsewhere. + * See additional comments at dns_rdata_tofmttext(). */ /* Split the rdata into multiple lines to try to keep it @@ -327,7 +316,9 @@ dns_result_t dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target); /* * Convert 'rdata' into text format, storing the result in 'target'. - * + * The text will consist of a single line, with fields separated by + * single spaces. + * * Notes: * If 'origin' is not NULL, then any names in the rdata that are * subdomains of 'origin' will be made relative it. @@ -354,6 +345,32 @@ dns_result_t dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, * Resource Limit: Not enough space */ +dns_result_t dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin, + unsigned int flags, unsigned int width, + char *linebreak, isc_buffer_t *target); +/* + * Like dns_rdata_totext, but do formatted output suitable for + * database dumps. This is intended for use by dns_db_dump(); + * library users are discouraged from calling it directly. + * + * If (flags & DNS_STYLEFLAG_MULTILINE) != 0, attempt to stay + * within 'width' by breaking the text into multiple lines. + * The string 'linebreak' is inserted between lines, and parentheses + * are added when necessary. Because RRs contain unbreakable elements + * such as domain names whose length is variable, unpredictable, and + * potentially large, there is no guarantee that the lines will + * not exceed 'width' anyway. + * + * If (flags & DNS_STYLEFLAG_MULTILINE) == 0, the rdata is always + * printed as a single line, and no parentheses are used. + * The 'width' and 'linebreak' arguments are ignored. + * + * If (flags & DNS_STYLEFLAG_COMMENT) != 0, output explanatory + * comments next to things like the SOA timer fields. Some + * comments (e.g., the SOA ones) are only printed when multiline + * output is selected. + */ + dns_result_t dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t class, dns_rdatatype_t type, void *source, diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index da35a75d1a..c918afa8fb 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -43,11 +43,6 @@ #include #include -/* XXX */ -dns_result_t -__dns_rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, - isc_buffer_t *target); - #define RETERR(x) do { \ dns_result_t __r = (x); \ if (__r != DNS_R_SUCCESS) \ @@ -121,9 +116,10 @@ struct dns_master_style { */ typedef struct dns_totext_ctx { dns_master_style_t style; - dns_rdata_textctx_t rdata_ctx; isc_boolean_t class_printed; - char linebreak[DNS_TOTEXT_LINEBREAK_MAXLEN]; + char * linebreak; + char linebreak_buf[DNS_TOTEXT_LINEBREAK_MAXLEN]; + dns_name_t * origin; dns_fixedname_t origin_fixname; isc_uint32_t current_ttl; isc_boolean_t current_ttl_valid; @@ -237,13 +233,13 @@ totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) REQUIRE(style->tab_width != 0); dns_fixedname_init(&ctx->origin_fixname); - /* Set up the line break string. */ + /* Set up the line break string if needed. */ if ((ctx->style.flags & DNS_STYLEFLAG_MULTILINE) != 0) { isc_buffer_t buf; isc_region_t r; int col = 0; - isc_buffer_init(&buf, ctx->linebreak, sizeof(ctx->linebreak), + isc_buffer_init(&buf, ctx->linebreak_buf, sizeof(ctx->linebreak_buf), ISC_BUFFERTYPE_TEXT); isc_buffer_available(&buf, &r); @@ -257,7 +253,7 @@ totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) /* * Do not return DNS_R_NOSPACE if the line break string * buffer is too small, because that would just make - * dump_rdataset() retry indenfinitely with ever + * dump_rdataset() retry indenfinitely with ever * bigger target buffers. That's a different buffer, * so it won't help. Use DNS_R_TEXTTOLONG as a substitute. */ @@ -271,22 +267,13 @@ totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) return (DNS_R_TEXTTOLONG); r.base[0] = '\0'; isc_buffer_add(&buf, 1); + ctx->linebreak = ctx->linebreak_buf; } else { - /* - * Single-line output. Use a single space where - * a line break would otherwise be used. - */ - INSIST(sizeof(ctx->linebreak) >= 2); - ctx->linebreak[0] = ' '; - ctx->linebreak[1] = '\0'; + ctx->linebreak = NULL; } ctx->class_printed = ISC_FALSE; - - ctx->rdata_ctx.origin = NULL; - ctx->rdata_ctx.width = ctx->style.line_length - ctx->style.rdata_column; - ctx->rdata_ctx.linebreak = ctx->linebreak; - ctx->rdata_ctx.flags = ctx->style.flags; + ctx->origin = NULL; return (DNS_R_SUCCESS); } @@ -403,7 +390,13 @@ rdataset_totext(dns_rdataset_t *rdataset, INDENT_TO(rdata_column); dns_rdataset_current(rdataset, &rdata); - RETERR(__dns_rdata_totext(&rdata, &ctx->rdata_ctx, target)); + RETERR(dns_rdata_tofmttext(&rdata, + ctx->origin, + ctx->style.flags, + ctx->style.line_length - + ctx->style.rdata_column, + ctx->linebreak, + target)); isc_buffer_available(target, &r); if (r.length < 1) @@ -724,8 +717,8 @@ dns_master_dumptostream(isc_mem_t *mctx, dns_db_t *db, isc_buffer_used(&buffer, &r); fprintf(f, "$ORIGIN %.*s\n", (int) r.length, (char *) r.base); - if (ctx.style.flags & DNS_STYLEFLAG_REL_DATA) - ctx.rdata_ctx.origin = origin; + if ((ctx.style.flags & DNS_STYLEFLAG_REL_DATA) != 0) + ctx.origin = origin; } result = dns_db_allrdatasets(db, node, version, now, &rdsiter); if (result != DNS_R_SUCCESS) { diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index b410322567..aa38465148 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: rdata.c,v 1.49 1999/06/08 20:46:43 gson Exp $ */ + /* $Id: rdata.c,v 1.50 1999/06/09 07:12:50 gson Exp $ */ #include @@ -48,6 +48,18 @@ return (__r); \ } while (0) +/* + * Context structure for the totext_ functions. + * Contains formatting options for rdata-to-text + * conversion. + */ +typedef struct dns_rdata_textctx { + dns_name_t *origin; /* Current origin, or NULL. */ + unsigned int flags; /* DNS_STYLEFLAG_* */ + unsigned int width; /* Width of rdata column. */ + char *linebreak; /* Line break string. */ +} dns_rdata_textctx_t; + static dns_result_t txt_totext(isc_region_t *source, isc_buffer_t *target); static dns_result_t txt_fromtext(isc_textregion_t *source, isc_buffer_t *target); @@ -88,9 +100,9 @@ static void fromtext_error(void (*callback)(dns_rdatacallbacks_t *, isc_token_t *token, dns_result_t result); -/* XXX */ -dns_result_t __dns_rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, - isc_buffer_t *target); +static dns_result_t __dns_rdata_totext(dns_rdata_t *rdata, + dns_rdata_textctx_t *tctx, + isc_buffer_t *target); static const char hexdigits[] = "0123456789abcdef"; static const char decdigits[] = "0123456789"; @@ -334,7 +346,7 @@ dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t class, isc_boolean_t use_default = ISC_FALSE; isc_token_t token; unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | - ISC_LEXOPT_DNSMULTILINE; + ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE; char *name; int line; void (*callback)(dns_rdatacallbacks_t *, char *, ...); @@ -449,6 +461,25 @@ dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, return (__dns_rdata_totext(rdata, &tctx, target)); } +dns_result_t +dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin, + unsigned int flags, unsigned int width, + char *linebreak, isc_buffer_t *target) +{ + /* Set up formatting options for formatted output. */ + dns_rdata_textctx_t tctx; + tctx.origin = origin; + tctx.flags = flags; + if ((flags & DNS_STYLEFLAG_MULTILINE) != 0) { + tctx.width = width; + tctx.linebreak = linebreak; + } else { + tctx.width = 60; /* Used for base64 word length only. */ + tctx.linebreak = " "; + } + return (__dns_rdata_totext(rdata, &tctx, target)); +} + dns_result_t dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t class, dns_rdatatype_t type, void *source, @@ -913,7 +944,7 @@ gettoken(isc_lex_t *lexer, isc_token_t *token, isc_tokentype_t expect, isc_boolean_t eol) { unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | - ISC_LEXOPT_DNSMULTILINE; + ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE; isc_result_t result; if (expect == isc_tokentype_qstring)