From 61d59a061acf2eeeb328864d1aef8b10b6b6a1fb Mon Sep 17 00:00:00 2001 From: rpm-build Date: Mon, 20 Feb 2017 15:06:45 +0100 Subject: [PATCH 3/3] Replace unsupported autoreallocating buffer by custom print_buffer --- src/settings.c | 106 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 29 deletions(-) diff --git a/src/settings.c b/src/settings.c index 8f3ae34..7d41b66 100644 --- a/src/settings.c +++ b/src/settings.c @@ -553,19 +553,69 @@ settings_set_free(settings_set_t **set) { *set = NULL; } +static const unsigned int BUFFER_INCR = 2048; +/** Structure for unlimited buffer. + * + * Replace for isc_buffer with autoreallocation enabled from newer bind. */ +typedef struct print_buffer +{ + isc_mem_t *mctx; + isc_buffer_t *buffer; + isc_result_t allocated; +} print_buffer_t; + +/** Initialize print buffer with preallocated isc_buffer. */ +static isc_result_t +print_buffer_init(isc_mem_t *mctx, print_buffer_t *buffer) +{ + buffer->mctx = mctx; + buffer->buffer = NULL; + buffer->allocated = + isc_buffer_allocate(mctx, &buffer->buffer, BUFFER_INCR); + return buffer->allocated; +} + +static isc_result_t +print_buffer_increment(print_buffer_t *pb, unsigned int inclen) +{ + unsigned int increment = BUFFER_INCR; + isc_buffer_t *newbuffer = NULL; + unsigned int newsize; + if (increment < (inclen)) + increment = (((inclen)/BUFFER_INCR)+1)*BUFFER_INCR; + + newsize = isc_buffer_length(pb->buffer)+increment; + REQUIRE(newsize > isc_buffer_length(pb->buffer)); + pb->allocated = isc_buffer_allocate(pb->mctx, &newbuffer, newsize); + if (pb->allocated == ISC_R_SUCCESS) + { + isc_buffer_putmem(newbuffer, + isc_buffer_base(pb->buffer), + isc_buffer_length(pb->buffer)); + isc_buffer_free(&pb->buffer); + pb->buffer = newbuffer; + } + return pb->allocated; +} + /** - * Append textlen bytes from text to isc_buffer pointed to by closure. + * Append textlen bytes from text to print_buffer pointed to by closure. * - * @pre closure is an initialized isc_buffer with autoreallocation enabled. + * @pre closure is an initialized print_buffer . */ static void cfg_printer(void *closure, const char *text, int textlen) { - isc_buffer_t *logbuffer = closure; - - REQUIRE(logbuffer != NULL); - REQUIRE(logbuffer->autore == ISC_TRUE); + struct print_buffer * pb = closure; + REQUIRE(pb != NULL); + REQUIRE(pb->buffer != NULL); + REQUIRE(pb->mctx != NULL); + + /* I will append terminating '\0', make sure space is reserved */ + if (isc_buffer_availablelength(pb->buffer) < (unsigned)(textlen+1)) { + print_buffer_increment(pb, textlen+1); + } - isc_buffer_putmem(logbuffer, (const unsigned char *)text, textlen); + isc_buffer_putmem(pb->buffer, (const unsigned char *)text, textlen); } /** @@ -583,14 +633,12 @@ settings_set_fill(const cfg_obj_t *config, settings_set_t *set) { isc_result_t result; setting_t *setting; - isc_buffer_t *buf_value = NULL; + print_buffer_t buf_value; const cfg_obj_t *cfg_value; const char *str_value; REQUIRE(cfg_obj_ismap(config) == ISC_TRUE); - - CHECK(isc_buffer_allocate(set->mctx, &buf_value, ISC_BUFFER_INCR)); - isc_buffer_setautorealloc(buf_value, ISC_TRUE); + CHECK(print_buffer_init(set->mctx, &buf_value)); for (setting = set->first_setting; setting->name != NULL; @@ -605,21 +653,22 @@ settings_set_fill(const cfg_obj_t *config, settings_set_t *set) /* this avoids additional quotes around the string */ str_value = cfg_obj_asstring(cfg_value); } else { - cfg_print(cfg_value, cfg_printer, buf_value); - isc_buffer_putmem(buf_value, (unsigned char *)"\0", 1); - str_value = isc_buffer_base(buf_value); + cfg_print(cfg_value, cfg_printer, &buf_value); + CHECK(buf_value.allocated); + isc_buffer_putmem(buf_value.buffer, (unsigned char *)"\0", 1); + str_value = isc_buffer_base(buf_value.buffer); } result = set_value(set->mctx, set, setting, str_value); if (result != ISC_R_SUCCESS && result != ISC_R_IGNORE) goto cleanup; - isc_buffer_clear(buf_value); + isc_buffer_clear(buf_value.buffer); } cleanup: if (result != ISC_R_SUCCESS) log_error_r("cannot parse settings for '%s'", set->name); - if (buf_value != NULL) - isc_buffer_free(&buf_value); + if (buf_value.buffer != NULL) + isc_buffer_free(&buf_value.buffer); return result; } @@ -673,46 +722,45 @@ setting_set_parse_conf(isc_mem_t *mctx, const char *name, isc_result_t result; cfg_obj_t *config = NULL; isc_buffer_t in_buf; - isc_buffer_t *log_buf = NULL; + print_buffer_t pb; cfg_parser_t *parser = NULL; unsigned int len; REQUIRE(parameters != NULL); - CHECK(isc_buffer_allocate(mctx, &log_buf, ISC_BUFFER_INCR)); - isc_buffer_setautorealloc(log_buf, ISC_TRUE); + CHECK(print_buffer_init(mctx, &pb)); len = strlen(parameters); isc_buffer_constinit(&in_buf, parameters, len); isc_buffer_add(&in_buf, len); CHECK(cfg_parser_create(mctx, dns_lctx, &parser)); - result = cfg_parse_buffer2(parser, &in_buf, name, cfg_type_conf, + result = cfg_parse_buffer(parser, &in_buf, cfg_type_conf, &config); if (result == ISC_R_SUCCESS) { - cfg_print(config, cfg_printer, log_buf); + cfg_print(config, cfg_printer, &pb); cfg_obj_log(config, dns_lctx, ISC_LOG_DEBUG(10), "configuration for dyndb instance '%s' " "(starting in file %s on line %lu):\n" "%.*s", - name, file, line, isc_buffer_usedlength(log_buf), - (char *)isc_buffer_base(log_buf)); + name, file, line, isc_buffer_usedlength(pb.buffer), + (char *)isc_buffer_base(pb.buffer)); } else { log_error("configuration for dyndb instance '%s' " "(starting in file %s on line %lu) is invalid", name, file, line); - cfg_print_grammar(cfg_type_conf, cfg_printer, log_buf); + cfg_print_grammar(cfg_type_conf, cfg_printer, &pb); log_info("expected grammar:\n" - "%.*s", isc_buffer_usedlength(log_buf), - (char *)isc_buffer_base(log_buf)); + "%.*s", isc_buffer_usedlength(pb.buffer), + (char *)isc_buffer_base(pb.buffer)); goto cleanup; } CHECK(settings_set_fill(config, settings)); cleanup: - if (log_buf != NULL) - isc_buffer_free(&log_buf); + if (pb.buffer != NULL) + isc_buffer_free(&pb.buffer); if (config != NULL) cfg_obj_destroy(parser, &config); if (parser != NULL) -- 2.9.3