1998-12-12 20:48:14 +00:00
|
|
|
/*
|
2016-05-26 12:36:17 -07:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
1998-12-12 20:48:14 +00:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
2021-06-03 08:37:05 +02:00
|
|
|
*
|
1998-12-12 20:48:14 +00:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
1998-12-12 20:48:14 +00:00
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
1998-10-29 02:01:29 +00:00
|
|
|
* information regarding copyright ownership.
|
1998-12-12 20:48:14 +00:00
|
|
|
*/
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|
2000-06-22 22:00:42 +00:00
|
|
|
|
2018-03-28 14:56:40 +02:00
|
|
|
#include <inttypes.h>
|
|
|
|
#include <stdarg.h>
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
2018-03-28 14:56:40 +02:00
|
|
|
|
1998-10-29 02:01:29 +00:00
|
|
|
#include <isc/buffer.h>
|
2000-04-10 21:57:24 +00:00
|
|
|
#include <isc/mem.h>
|
2016-06-21 00:25:52 +10:00
|
|
|
#include <isc/print.h>
|
2000-04-10 21:57:24 +00:00
|
|
|
#include <isc/region.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/string.h>
|
2000-04-28 01:12:23 +00:00
|
|
|
#include <isc/util.h>
|
1998-10-29 02:01:29 +00:00
|
|
|
|
2006-12-21 06:03:37 +00:00
|
|
|
void
|
|
|
|
isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) {
|
|
|
|
/*
|
|
|
|
* Re-initialize the buffer enough to reconfigure the base of the
|
|
|
|
* buffer. We will swap in the new buffer, after copying any
|
|
|
|
* data we contain into the new buffer and adjusting all of our
|
|
|
|
* internal pointers.
|
|
|
|
*
|
|
|
|
* The buffer must not be smaller than the length of the original
|
|
|
|
* buffer.
|
|
|
|
*/
|
|
|
|
REQUIRE(b->length <= length);
|
|
|
|
REQUIRE(base != NULL);
|
2022-12-15 22:27:12 +01:00
|
|
|
REQUIRE(b->mctx == NULL);
|
2006-12-21 06:03:37 +00:00
|
|
|
|
2018-05-15 08:18:01 +02:00
|
|
|
if (b->length > 0U) {
|
|
|
|
(void)memmove(base, b->base, b->length);
|
|
|
|
}
|
|
|
|
|
2006-12-21 06:03:37 +00:00
|
|
|
b->base = base;
|
|
|
|
b->length = length;
|
|
|
|
}
|
|
|
|
|
1998-10-29 02:01:29 +00:00
|
|
|
void
|
1998-12-13 23:45:21 +00:00
|
|
|
isc_buffer_compact(isc_buffer_t *b) {
|
1998-10-29 02:01:29 +00:00
|
|
|
unsigned int length;
|
1999-01-06 05:37:54 +00:00
|
|
|
void *src;
|
1998-10-29 02:01:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Compact the used region by moving the remaining region so it occurs
|
|
|
|
* at the start of the buffer. The used region is shrunk by the size
|
|
|
|
* of the consumed region, and the consumed region is then made empty.
|
|
|
|
*/
|
|
|
|
|
1999-09-10 01:54:08 +00:00
|
|
|
REQUIRE(ISC_BUFFER_VALID(b));
|
1998-10-29 02:01:29 +00:00
|
|
|
|
2000-06-01 17:20:56 +00:00
|
|
|
src = isc_buffer_current(b);
|
|
|
|
length = isc_buffer_remaininglength(b);
|
2018-05-15 08:18:01 +02:00
|
|
|
if (length > 0U) {
|
|
|
|
(void)memmove(b->base, src, (size_t)length);
|
|
|
|
}
|
1998-10-29 02:01:29 +00:00
|
|
|
|
1999-01-20 02:42:22 +00:00
|
|
|
if (b->active > b->current) {
|
|
|
|
b->active -= b->current;
|
|
|
|
} else {
|
|
|
|
b->active = 0;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-01-06 05:37:54 +00:00
|
|
|
b->current = 0;
|
1998-10-29 02:01:29 +00:00
|
|
|
b->used = length;
|
|
|
|
}
|
1999-01-07 02:06:48 +00:00
|
|
|
|
2016-06-20 13:39:44 +02:00
|
|
|
isc_result_t
|
|
|
|
isc_buffer_dup(isc_mem_t *mctx, isc_buffer_t **dstp, const isc_buffer_t *src) {
|
|
|
|
isc_buffer_t *dst = NULL;
|
|
|
|
isc_region_t region;
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
REQUIRE(dstp != NULL && *dstp == NULL);
|
|
|
|
REQUIRE(ISC_BUFFER_VALID(src));
|
|
|
|
|
|
|
|
isc_buffer_usedregion(src, ®ion);
|
|
|
|
|
2020-02-02 08:35:46 +01:00
|
|
|
isc_buffer_allocate(mctx, &dst, region.length);
|
2016-06-20 13:39:44 +02:00
|
|
|
|
|
|
|
result = isc_buffer_copyregion(dst, ®ion);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS); /* NOSPACE is impossible */
|
|
|
|
*dstp = dst;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
1999-09-22 00:35:59 +00:00
|
|
|
isc_result_t
|
2000-08-17 02:09:12 +00:00
|
|
|
isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
|
2016-06-20 13:39:44 +02:00
|
|
|
isc_result_t result;
|
1999-09-22 00:35:59 +00:00
|
|
|
|
|
|
|
REQUIRE(ISC_BUFFER_VALID(b));
|
|
|
|
REQUIRE(r != NULL);
|
|
|
|
|
2022-12-15 22:27:12 +01:00
|
|
|
if (b->mctx) {
|
2022-12-15 11:54:51 +01:00
|
|
|
result = isc_buffer_reserve(b, r->length);
|
2018-10-30 13:33:25 +01:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2016-06-20 13:39:44 +02:00
|
|
|
return (result);
|
2018-10-30 13:33:25 +01:00
|
|
|
}
|
2016-06-20 13:39:44 +02:00
|
|
|
}
|
2018-10-30 13:33:25 +01:00
|
|
|
|
|
|
|
if (r->length > isc_buffer_availablelength(b)) {
|
1999-09-22 00:35:59 +00:00
|
|
|
return (ISC_R_NOSPACE);
|
2018-10-30 13:33:25 +01:00
|
|
|
}
|
|
|
|
|
2018-05-15 08:18:01 +02:00
|
|
|
if (r->length > 0U) {
|
2018-10-30 13:33:25 +01:00
|
|
|
memmove(isc_buffer_used(b), r->base, r->length);
|
2018-05-15 08:18:01 +02:00
|
|
|
b->used += r->length;
|
|
|
|
}
|
1999-09-22 00:35:59 +00:00
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2020-02-02 08:00:20 +01:00
|
|
|
void
|
1999-09-02 02:10:44 +00:00
|
|
|
isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
unsigned int length) {
|
2020-02-02 08:00:20 +01:00
|
|
|
REQUIRE(dynbuffer != NULL && *dynbuffer == NULL);
|
1999-04-19 23:56:36 +00:00
|
|
|
|
2020-02-02 08:00:20 +01:00
|
|
|
isc_buffer_t *dbuf = isc_mem_get(mctx, sizeof(isc_buffer_t));
|
|
|
|
unsigned char *bdata = isc_mem_get(mctx, length);
|
2016-05-26 21:23:19 +02:00
|
|
|
|
|
|
|
isc_buffer_init(dbuf, bdata, length);
|
1999-04-19 23:56:36 +00:00
|
|
|
|
2019-09-27 11:53:49 +02:00
|
|
|
dbuf->mctx = mctx;
|
|
|
|
|
1999-04-19 23:56:36 +00:00
|
|
|
*dynbuffer = dbuf;
|
|
|
|
}
|
|
|
|
|
2014-11-14 15:58:54 -08:00
|
|
|
isc_result_t
|
2022-12-15 11:54:51 +01:00
|
|
|
isc_buffer_reserve(isc_buffer_t *dynbuffer, unsigned int size) {
|
2021-09-22 20:01:20 +02:00
|
|
|
size_t len;
|
2014-11-14 15:58:54 -08:00
|
|
|
|
2022-12-15 11:54:51 +01:00
|
|
|
REQUIRE(ISC_BUFFER_VALID(dynbuffer));
|
2014-11-14 15:58:54 -08:00
|
|
|
|
2022-12-15 11:54:51 +01:00
|
|
|
len = dynbuffer->length;
|
|
|
|
if ((len - dynbuffer->used) >= size) {
|
2014-11-14 15:58:54 -08:00
|
|
|
return (ISC_R_SUCCESS);
|
2018-07-28 06:24:12 +02:00
|
|
|
}
|
2014-11-14 15:58:54 -08:00
|
|
|
|
2022-12-15 11:54:51 +01:00
|
|
|
if (dynbuffer->mctx == NULL) {
|
2015-02-05 17:18:15 -08:00
|
|
|
return (ISC_R_NOSPACE);
|
2018-07-28 06:24:12 +02:00
|
|
|
}
|
2015-02-05 17:18:15 -08:00
|
|
|
|
2014-11-14 15:58:54 -08:00
|
|
|
/* Round to nearest buffer size increment */
|
2022-12-15 11:54:51 +01:00
|
|
|
len = size + dynbuffer->used;
|
2014-11-14 15:58:54 -08:00
|
|
|
len = (len + ISC_BUFFER_INCR - 1 - ((len - 1) % ISC_BUFFER_INCR));
|
|
|
|
|
|
|
|
/* Cap at UINT_MAX */
|
|
|
|
if (len > UINT_MAX) {
|
|
|
|
len = UINT_MAX;
|
|
|
|
}
|
|
|
|
|
2022-12-15 11:54:51 +01:00
|
|
|
if ((len - dynbuffer->used) < size) {
|
2014-11-15 00:56:17 -08:00
|
|
|
return (ISC_R_NOMEMORY);
|
2018-07-28 06:24:12 +02:00
|
|
|
}
|
2014-11-15 00:56:17 -08:00
|
|
|
|
2022-12-15 11:54:51 +01:00
|
|
|
dynbuffer->base = isc_mem_reget(dynbuffer->mctx, dynbuffer->base,
|
|
|
|
dynbuffer->length, len);
|
|
|
|
dynbuffer->length = (unsigned int)len;
|
2018-07-28 06:24:12 +02:00
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
2014-11-14 15:58:54 -08:00
|
|
|
}
|
|
|
|
|
1999-04-29 05:59:51 +00:00
|
|
|
void
|
2000-06-01 17:20:56 +00:00
|
|
|
isc_buffer_free(isc_buffer_t **dynbuffer) {
|
1999-09-02 02:10:44 +00:00
|
|
|
isc_buffer_t *dbuf;
|
|
|
|
isc_mem_t *mctx;
|
1999-04-19 23:56:36 +00:00
|
|
|
|
|
|
|
REQUIRE(dynbuffer != NULL);
|
1999-09-10 01:54:08 +00:00
|
|
|
REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
|
1999-09-02 02:10:44 +00:00
|
|
|
REQUIRE((*dynbuffer)->mctx != NULL);
|
1999-04-19 23:56:36 +00:00
|
|
|
|
|
|
|
dbuf = *dynbuffer;
|
2020-02-08 04:37:54 -08:00
|
|
|
*dynbuffer = NULL; /* destroy external reference */
|
1999-09-02 02:10:44 +00:00
|
|
|
mctx = dbuf->mctx;
|
|
|
|
dbuf->mctx = NULL;
|
1999-04-19 23:56:36 +00:00
|
|
|
|
2016-05-26 21:23:19 +02:00
|
|
|
isc_mem_put(mctx, dbuf->base, dbuf->length);
|
|
|
|
isc_buffer_invalidate(dbuf);
|
|
|
|
isc_mem_put(mctx, dbuf, sizeof(isc_buffer_t));
|
1999-04-19 23:56:36 +00:00
|
|
|
}
|
2017-10-09 11:43:07 +02:00
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
isc_buffer_printf(isc_buffer_t *b, const char *format, ...) {
|
|
|
|
va_list ap;
|
|
|
|
int n;
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
REQUIRE(ISC_BUFFER_VALID(b));
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
n = vsnprintf(NULL, 0, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if (n < 0) {
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2022-12-15 22:27:12 +01:00
|
|
|
if (b->mctx) {
|
2022-12-15 11:54:51 +01:00
|
|
|
result = isc_buffer_reserve(b, n + 1);
|
2018-07-27 11:22:47 +02:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isc_buffer_availablelength(b) < (unsigned int)n + 1) {
|
|
|
|
return (ISC_R_NOSPACE);
|
2017-10-09 11:43:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
n = vsnprintf(isc_buffer_used(b), n + 1, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if (n < 0) {
|
|
|
|
return (ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
b->used += n;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|