"Fossies" - the Fresh Open Source Software Archive

Member "gnupg-2.2.17/common/membuf.c" (28 Aug 2017, 5371 Bytes) of package /linux/misc/gnupg-2.2.17.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "membuf.c" see the Fossies "Dox" file reference documentation.

    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
    4  *
    5  * This file is part of GnuPG.
    6  *
    7  * This file is free software; you can redistribute it and/or modify
    8  * it under the terms of either
    9  *
   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.
   13  *
   14  * or
   15  *
   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.
   19  *
   20  * or both in parallel, as here.
   21  *
   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.
   26  *
   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/>.
   29  */
   30 
   31 #include <config.h>
   32 #include <stdlib.h>
   33 #include <errno.h>
   34 #include <stdarg.h>
   35 
   36 #include "util.h"
   37 #include "membuf.h"
   38 
   39 
   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.  */
   45 
   46 void
   47 init_membuf (membuf_t *mb, int initiallen)
   48 {
   49   mb->len = 0;
   50   mb->size = initiallen;
   51   mb->out_of_core = 0;
   52   mb->buf = xtrymalloc (initiallen);
   53   if (!mb->buf)
   54     mb->out_of_core = errno;
   55 }
   56 
   57 /* Same as init_membuf but allocates the buffer in secure memory.  */
   58 void
   59 init_membuf_secure (membuf_t *mb, int initiallen)
   60 {
   61   mb->len = 0;
   62   mb->size = initiallen;
   63   mb->out_of_core = 0;
   64   mb->buf = xtrymalloc_secure (initiallen);
   65   if (!mb->buf)
   66     mb->out_of_core = errno;
   67 }
   68 
   69 
   70 /* Shift 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.  */
   74 void
   75 clear_membuf (membuf_t *mb, size_t amount)
   76 {
   77   /* No need to clear if we are already out of core.  */
   78   if (mb->out_of_core)
   79     return;
   80   if (amount >= mb->len)
   81     mb->len = 0;
   82   else
   83     {
   84       mb->len -= amount;
   85       memmove (mb->buf, mb->buf+amount, mb->len);
   86     }
   87 }
   88 
   89 
   90 void
   91 put_membuf (membuf_t *mb, const void *buf, size_t len)
   92 {
   93   if (mb->out_of_core || !len)
   94     return;
   95 
   96   if (mb->len + len >= mb->size)
   97     {
   98       char *p;
   99 
  100       mb->size += len + 1024;
  101       p = xtryrealloc (mb->buf, mb->size);
  102       if (!p)
  103         {
  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
  108              error. */
  109           wipememory (mb->buf, mb->len);
  110           return;
  111         }
  112       mb->buf = p;
  113     }
  114   memcpy (mb->buf + mb->len, buf, len);
  115   mb->len += len;
  116 }
  117 
  118 
  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.  */
  122 gpg_error_t
  123 put_membuf_cb (void *opaque, const void *buf, size_t len)
  124 {
  125   membuf_t *data = opaque;
  126 
  127   if (buf)
  128     put_membuf (data, buf, len);
  129   return 0;
  130 }
  131 
  132 
  133 void
  134 put_membuf_str (membuf_t *mb, const char *string)
  135 {
  136   put_membuf (mb, string, strlen (string));
  137 }
  138 
  139 
  140 void
  141 put_membuf_printf (membuf_t *mb, const char *format, ...)
  142 {
  143   int rc;
  144   va_list arg_ptr;
  145   char *buf;
  146 
  147   va_start (arg_ptr, format);
  148   rc = gpgrt_vasprintf (&buf, format, arg_ptr);
  149   if (rc < 0)
  150     mb->out_of_core = errno ? errno : ENOMEM;
  151   va_end (arg_ptr);
  152   if (rc >= 0)
  153     {
  154       put_membuf (mb, buf, strlen (buf));
  155       xfree (buf);
  156     }
  157 }
  158 
  159 
  160 void *
  161 get_membuf (membuf_t *mb, size_t *len)
  162 {
  163   char *p;
  164 
  165   if (mb->out_of_core)
  166     {
  167       if (mb->buf)
  168         {
  169           wipememory (mb->buf, mb->len);
  170           xfree (mb->buf);
  171           mb->buf = NULL;
  172         }
  173       gpg_err_set_errno (mb->out_of_core);
  174       return NULL;
  175     }
  176 
  177   p = mb->buf;
  178   if (len)
  179     *len = mb->len;
  180   mb->buf = NULL;
  181   mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */
  182   return p;
  183 }
  184 
  185 
  186 /* Same as get_membuf but shrinks the reallocated space to the
  187    required size.  */
  188 void *
  189 get_membuf_shrink (membuf_t *mb, size_t *len)
  190 {
  191   void *p, *pp;
  192   size_t dummylen;
  193 
  194   if (!len)
  195     len = &dummylen;
  196 
  197   p = get_membuf (mb, len);
  198   if (!p)
  199     return NULL;
  200   if (*len)
  201     {
  202       pp = xtryrealloc (p, *len);
  203       if (pp)
  204         p = pp;
  205     }
  206 
  207   return p;
  208 }
  209 
  210 
  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.  */
  215 const void *
  216 peek_membuf (membuf_t *mb, size_t *len)
  217 {
  218   const char *p;
  219 
  220   if (mb->out_of_core)
  221     {
  222       gpg_err_set_errno (mb->out_of_core);
  223       return NULL;
  224     }
  225 
  226   p = mb->buf;
  227   if (len)
  228     *len = mb->len;
  229   return p;
  230 }