1 /* membuf.c - A simple implementation of a dynamic buffer.
2 * Copyright (C) 2001, 2003, 2009, 2011 Free Software Foundation, Inc.
3 * Copyright (C) 2013 Werner Koch
5 * This file is part of GnuPG.
7 * This file is free software; you can redistribute it and/or modify
8 * it under the terms of either
10 * - the GNU Lesser General Public License as published by the Free
11 * Software Foundation; either version 3 of the License, or (at
12 * your option) any later version.
16 * - the GNU General Public License as published by the Free
17 * Software Foundation; either version 2 of the License, or (at
18 * your option) any later version.
20 * or both in parallel, as here.
22 * This file is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, see <https://www.gnu.org/licenses/>.
40 /* A simple implementation of a dynamic buffer. Use init_membuf() to
41 create a buffer, put_membuf to append bytes and get_membuf to
42 release and return the buffer. Allocation errors are detected but
43 only returned at the final get_membuf(), this helps not to clutter
44 the code with out of core checks. */
47 init_membuf (membuf_t *mb, int initiallen)
50 mb->size = initiallen;
52 mb->buf = xtrymalloc (initiallen);
54 mb->out_of_core = errno;
57 /* Same as init_membuf but allocates the buffer in secure memory. */
59 init_membuf_secure (membuf_t *mb, int initiallen)
62 mb->size = initiallen;
64 mb->buf = xtrymalloc_secure (initiallen);
66 mb->out_of_core = errno;
70 /* Shift the the content of the membuf MB by AMOUNT bytes. The next
71 operation will then behave as if AMOUNT bytes had not been put into
72 the buffer. If AMOUNT is greater than the actual accumulated
73 bytes, the membuf is basically reset to its initial state. */
75 clear_membuf (membuf_t *mb, size_t amount)
77 /* No need to clear if we are already out of core. */
80 if (amount >= mb->len)
85 memmove (mb->buf, mb->buf+amount, mb->len);
91 put_membuf (membuf_t *mb, const void *buf, size_t len)
93 if (mb->out_of_core || !len)
96 if (mb->len + len >= mb->size)
100 mb->size += len + 1024;
101 p = xtryrealloc (mb->buf, mb->size);
104 mb->out_of_core = errno ? errno : ENOMEM;
105 /* Wipe out what we already accumulated. This is required
106 in case we are storing sensitive data here. The membuf
107 API does not provide another way to cleanup after an
109 wipememory (mb->buf, mb->len);
114 memcpy (mb->buf + mb->len, buf, len);
119 /* A variant of put_membuf accepting a void * and returning a
120 gpg_error_t (which will always return 0) to be used as a generic
121 callback handler. This function also allows buffer to be NULL. */
123 put_membuf_cb (void *opaque, const void *buf, size_t len)
125 membuf_t *data = opaque;
128 put_membuf (data, buf, len);
134 put_membuf_str (membuf_t *mb, const char *string)
136 put_membuf (mb, string, strlen (string));
141 put_membuf_printf (membuf_t *mb, const char *format, ...)
147 va_start (arg_ptr, format);
148 rc = gpgrt_vasprintf (&buf, format, arg_ptr);
150 mb->out_of_core = errno ? errno : ENOMEM;
154 put_membuf (mb, buf, strlen (buf));
161 get_membuf (membuf_t *mb, size_t *len)
169 wipememory (mb->buf, mb->len);
173 gpg_err_set_errno (mb->out_of_core);
181 mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */
186 /* Same as get_membuf but shrinks the reallocated space to the
189 get_membuf_shrink (membuf_t *mb, size_t *len)
197 p = get_membuf (mb, len);
202 pp = xtryrealloc (p, *len);
211 /* Peek at the membuf MB. On success a pointer to the buffer is
212 returned which is valid until the next operation on MB. If LEN is
213 not NULL the current LEN of the buffer is stored there. On error
214 NULL is returned and ERRNO is set. */
216 peek_membuf (membuf_t *mb, size_t *len)
222 gpg_err_set_errno (mb->out_of_core);