LCOV - code coverage report
Current view: top level - contrib/pgcrypto - mbuf.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 266 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 24 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*
       2              :  * mbuf.c
       3              :  *              Memory buffer operations.
       4              :  *
       5              :  * Copyright (c) 2005 Marko Kreen
       6              :  * All rights reserved.
       7              :  *
       8              :  * Redistribution and use in source and binary forms, with or without
       9              :  * modification, are permitted provided that the following conditions
      10              :  * are met:
      11              :  * 1. Redistributions of source code must retain the above copyright
      12              :  *        notice, this list of conditions and the following disclaimer.
      13              :  * 2. Redistributions in binary form must reproduce the above copyright
      14              :  *        notice, this list of conditions and the following disclaimer in the
      15              :  *        documentation and/or other materials provided with the distribution.
      16              :  *
      17              :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      18              :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      19              :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      20              :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      21              :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      22              :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      23              :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      24              :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      25              :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      26              :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      27              :  * SUCH DAMAGE.
      28              :  *
      29              :  * contrib/pgcrypto/mbuf.c
      30              :  */
      31              : 
      32              : #include "postgres.h"
      33              : 
      34              : #include "mbuf.h"
      35              : #include "px.h"
      36              : 
      37              : #define STEP  (16*1024)
      38              : 
      39              : struct MBuf
      40              : {
      41              :         uint8      *data;
      42              :         uint8      *data_end;
      43              :         uint8      *read_pos;
      44              :         uint8      *buf_end;
      45              :         bool            no_write;
      46              :         bool            own_data;
      47              : };
      48              : 
      49              : int
      50            0 : mbuf_avail(MBuf *mbuf)
      51              : {
      52            0 :         return mbuf->data_end - mbuf->read_pos;
      53              : }
      54              : 
      55              : int
      56            0 : mbuf_size(MBuf *mbuf)
      57              : {
      58            0 :         return mbuf->data_end - mbuf->data;
      59              : }
      60              : 
      61              : int
      62            0 : mbuf_free(MBuf *mbuf)
      63              : {
      64            0 :         if (mbuf->own_data)
      65              :         {
      66            0 :                 px_memset(mbuf->data, 0, mbuf->buf_end - mbuf->data);
      67            0 :                 pfree(mbuf->data);
      68            0 :         }
      69            0 :         pfree(mbuf);
      70            0 :         return 0;
      71              : }
      72              : 
      73              : static void
      74            0 : prepare_room(MBuf *mbuf, int block_len)
      75              : {
      76            0 :         uint8      *newbuf;
      77            0 :         unsigned        newlen;
      78              : 
      79            0 :         if (mbuf->data_end + block_len <= mbuf->buf_end)
      80            0 :                 return;
      81              : 
      82            0 :         newlen = (mbuf->buf_end - mbuf->data)
      83            0 :                 + ((block_len + STEP + STEP - 1) & -STEP);
      84              : 
      85            0 :         newbuf = repalloc(mbuf->data, newlen);
      86              : 
      87            0 :         mbuf->buf_end = newbuf + newlen;
      88            0 :         mbuf->data_end = newbuf + (mbuf->data_end - mbuf->data);
      89            0 :         mbuf->read_pos = newbuf + (mbuf->read_pos - mbuf->data);
      90            0 :         mbuf->data = newbuf;
      91            0 : }
      92              : 
      93              : int
      94            0 : mbuf_append(MBuf *dst, const uint8 *buf, int len)
      95              : {
      96            0 :         if (dst->no_write)
      97              :         {
      98            0 :                 px_debug("mbuf_append: no_write");
      99            0 :                 return PXE_BUG;
     100              :         }
     101              : 
     102            0 :         prepare_room(dst, len);
     103              : 
     104            0 :         memcpy(dst->data_end, buf, len);
     105            0 :         dst->data_end += len;
     106              : 
     107            0 :         return 0;
     108            0 : }
     109              : 
     110              : MBuf *
     111            0 : mbuf_create(int len)
     112              : {
     113            0 :         MBuf       *mbuf;
     114              : 
     115            0 :         if (!len)
     116            0 :                 len = 8192;
     117              : 
     118            0 :         mbuf = palloc_object(MBuf);
     119            0 :         mbuf->data = palloc(len);
     120            0 :         mbuf->buf_end = mbuf->data + len;
     121            0 :         mbuf->data_end = mbuf->data;
     122            0 :         mbuf->read_pos = mbuf->data;
     123              : 
     124            0 :         mbuf->no_write = false;
     125            0 :         mbuf->own_data = true;
     126              : 
     127            0 :         return mbuf;
     128            0 : }
     129              : 
     130              : MBuf *
     131            0 : mbuf_create_from_data(uint8 *data, int len)
     132              : {
     133            0 :         MBuf       *mbuf;
     134              : 
     135            0 :         mbuf = palloc_object(MBuf);
     136            0 :         mbuf->data = data;
     137            0 :         mbuf->buf_end = mbuf->data + len;
     138            0 :         mbuf->data_end = mbuf->data + len;
     139            0 :         mbuf->read_pos = mbuf->data;
     140              : 
     141            0 :         mbuf->no_write = true;
     142            0 :         mbuf->own_data = false;
     143              : 
     144            0 :         return mbuf;
     145            0 : }
     146              : 
     147              : 
     148              : int
     149            0 : mbuf_grab(MBuf *mbuf, int len, uint8 **data_p)
     150              : {
     151            0 :         if (len > mbuf_avail(mbuf))
     152            0 :                 len = mbuf_avail(mbuf);
     153              : 
     154            0 :         mbuf->no_write = true;
     155              : 
     156            0 :         *data_p = mbuf->read_pos;
     157            0 :         mbuf->read_pos += len;
     158            0 :         return len;
     159              : }
     160              : 
     161              : int
     162            0 : mbuf_steal_data(MBuf *mbuf, uint8 **data_p)
     163              : {
     164            0 :         int                     len = mbuf_size(mbuf);
     165              : 
     166            0 :         mbuf->no_write = true;
     167            0 :         mbuf->own_data = false;
     168              : 
     169            0 :         *data_p = mbuf->data;
     170              : 
     171            0 :         mbuf->data = mbuf->data_end = mbuf->read_pos = mbuf->buf_end = NULL;
     172              : 
     173            0 :         return len;
     174            0 : }
     175              : 
     176              : /*
     177              :  * PullFilter
     178              :  */
     179              : 
     180              : struct PullFilter
     181              : {
     182              :         PullFilter *src;
     183              :         const PullFilterOps *op;
     184              :         int                     buflen;
     185              :         uint8      *buf;
     186              :         int                     pos;
     187              :         void       *priv;
     188              : };
     189              : 
     190              : int
     191            0 : pullf_create(PullFilter **pf_p, const PullFilterOps *op, void *init_arg, PullFilter *src)
     192              : {
     193            0 :         PullFilter *pf;
     194            0 :         void       *priv;
     195            0 :         int                     res;
     196              : 
     197            0 :         if (op->init != NULL)
     198              :         {
     199            0 :                 res = op->init(&priv, init_arg, src);
     200            0 :                 if (res < 0)
     201            0 :                         return res;
     202            0 :         }
     203              :         else
     204              :         {
     205            0 :                 priv = init_arg;
     206            0 :                 res = 0;
     207              :         }
     208              : 
     209            0 :         pf = palloc0_object(PullFilter);
     210            0 :         pf->buflen = res;
     211            0 :         pf->op = op;
     212            0 :         pf->priv = priv;
     213            0 :         pf->src = src;
     214            0 :         if (pf->buflen > 0)
     215              :         {
     216            0 :                 pf->buf = palloc(pf->buflen);
     217            0 :                 pf->pos = 0;
     218            0 :         }
     219              :         else
     220              :         {
     221            0 :                 pf->buf = NULL;
     222            0 :                 pf->pos = 0;
     223              :         }
     224            0 :         *pf_p = pf;
     225            0 :         return 0;
     226            0 : }
     227              : 
     228              : void
     229            0 : pullf_free(PullFilter *pf)
     230              : {
     231            0 :         if (pf->op->free)
     232            0 :                 pf->op->free(pf->priv);
     233              : 
     234            0 :         if (pf->buf)
     235              :         {
     236            0 :                 px_memset(pf->buf, 0, pf->buflen);
     237            0 :                 pfree(pf->buf);
     238            0 :         }
     239              : 
     240            0 :         px_memset(pf, 0, sizeof(*pf));
     241            0 :         pfree(pf);
     242            0 : }
     243              : 
     244              : /* may return less data than asked, 0 means eof */
     245              : int
     246            0 : pullf_read(PullFilter *pf, int len, uint8 **data_p)
     247              : {
     248            0 :         int                     res;
     249              : 
     250            0 :         if (pf->op->pull)
     251              :         {
     252            0 :                 if (pf->buflen && len > pf->buflen)
     253            0 :                         len = pf->buflen;
     254            0 :                 res = pf->op->pull(pf->priv, pf->src, len, data_p,
     255            0 :                                                    pf->buf, pf->buflen);
     256            0 :         }
     257              :         else
     258            0 :                 res = pullf_read(pf->src, len, data_p);
     259            0 :         return res;
     260            0 : }
     261              : 
     262              : int
     263            0 : pullf_read_max(PullFilter *pf, int len, uint8 **data_p, uint8 *tmpbuf)
     264              : {
     265            0 :         int                     res,
     266              :                                 total;
     267            0 :         uint8      *tmp;
     268              : 
     269            0 :         res = pullf_read(pf, len, data_p);
     270            0 :         if (res <= 0 || res == len)
     271            0 :                 return res;
     272              : 
     273              :         /* read was shorter, use tmpbuf */
     274            0 :         memcpy(tmpbuf, *data_p, res);
     275            0 :         *data_p = tmpbuf;
     276            0 :         len -= res;
     277            0 :         total = res;
     278              : 
     279            0 :         while (len > 0)
     280              :         {
     281            0 :                 res = pullf_read(pf, len, &tmp);
     282            0 :                 if (res < 0)
     283              :                 {
     284              :                         /* so the caller must clear only on success */
     285            0 :                         px_memset(tmpbuf, 0, total);
     286            0 :                         return res;
     287              :                 }
     288            0 :                 if (res == 0)
     289            0 :                         break;
     290            0 :                 memcpy(tmpbuf + total, tmp, res);
     291            0 :                 total += res;
     292            0 :                 len -= res;
     293              :         }
     294            0 :         return total;
     295            0 : }
     296              : 
     297              : /*
     298              :  * caller wants exactly len bytes and don't bother with references
     299              :  */
     300              : int
     301            0 : pullf_read_fixed(PullFilter *src, int len, uint8 *dst)
     302              : {
     303            0 :         int                     res;
     304            0 :         uint8      *p;
     305              : 
     306            0 :         res = pullf_read_max(src, len, &p, dst);
     307            0 :         if (res < 0)
     308            0 :                 return res;
     309            0 :         if (res != len)
     310              :         {
     311            0 :                 px_debug("pullf_read_fixed: need=%d got=%d", len, res);
     312            0 :                 return PXE_PGP_CORRUPT_DATA;
     313              :         }
     314            0 :         if (p != dst)
     315            0 :                 memcpy(dst, p, len);
     316            0 :         return 0;
     317            0 : }
     318              : 
     319              : /*
     320              :  * read from MBuf
     321              :  */
     322              : static int
     323            0 : pull_from_mbuf(void *arg, PullFilter *src, int len,
     324              :                            uint8 **data_p, uint8 *buf, int buflen)
     325              : {
     326            0 :         MBuf       *mbuf = arg;
     327              : 
     328            0 :         return mbuf_grab(mbuf, len, data_p);
     329            0 : }
     330              : 
     331              : static const struct PullFilterOps mbuf_reader = {
     332              :         NULL, pull_from_mbuf, NULL
     333              : };
     334              : 
     335              : int
     336            0 : pullf_create_mbuf_reader(PullFilter **mp_p, MBuf *src)
     337              : {
     338            0 :         return pullf_create(mp_p, &mbuf_reader, src, NULL);
     339              : }
     340              : 
     341              : 
     342              : /*
     343              :  * PushFilter
     344              :  */
     345              : 
     346              : struct PushFilter
     347              : {
     348              :         PushFilter *next;
     349              :         const PushFilterOps *op;
     350              :         int                     block_size;
     351              :         uint8      *buf;
     352              :         int                     pos;
     353              :         void       *priv;
     354              : };
     355              : 
     356              : int
     357            0 : pushf_create(PushFilter **mp_p, const PushFilterOps *op, void *init_arg, PushFilter *next)
     358              : {
     359            0 :         PushFilter *mp;
     360            0 :         void       *priv;
     361            0 :         int                     res;
     362              : 
     363            0 :         if (op->init != NULL)
     364              :         {
     365            0 :                 res = op->init(next, init_arg, &priv);
     366            0 :                 if (res < 0)
     367            0 :                         return res;
     368            0 :         }
     369              :         else
     370              :         {
     371            0 :                 priv = init_arg;
     372            0 :                 res = 0;
     373              :         }
     374              : 
     375            0 :         mp = palloc0_object(PushFilter);
     376            0 :         mp->block_size = res;
     377            0 :         mp->op = op;
     378            0 :         mp->priv = priv;
     379            0 :         mp->next = next;
     380            0 :         if (mp->block_size > 0)
     381              :         {
     382            0 :                 mp->buf = palloc(mp->block_size);
     383            0 :                 mp->pos = 0;
     384            0 :         }
     385              :         else
     386              :         {
     387            0 :                 mp->buf = NULL;
     388            0 :                 mp->pos = 0;
     389              :         }
     390            0 :         *mp_p = mp;
     391            0 :         return 0;
     392            0 : }
     393              : 
     394              : void
     395            0 : pushf_free(PushFilter *mp)
     396              : {
     397            0 :         if (mp->op->free)
     398            0 :                 mp->op->free(mp->priv);
     399              : 
     400            0 :         if (mp->buf)
     401              :         {
     402            0 :                 px_memset(mp->buf, 0, mp->block_size);
     403            0 :                 pfree(mp->buf);
     404            0 :         }
     405              : 
     406            0 :         px_memset(mp, 0, sizeof(*mp));
     407            0 :         pfree(mp);
     408            0 : }
     409              : 
     410              : void
     411            0 : pushf_free_all(PushFilter *mp)
     412              : {
     413            0 :         PushFilter *tmp;
     414              : 
     415            0 :         while (mp)
     416              :         {
     417            0 :                 tmp = mp->next;
     418            0 :                 pushf_free(mp);
     419            0 :                 mp = tmp;
     420              :         }
     421            0 : }
     422              : 
     423              : static int
     424            0 : wrap_process(PushFilter *mp, const uint8 *data, int len)
     425              : {
     426            0 :         int                     res;
     427              : 
     428            0 :         if (mp->op->push != NULL)
     429            0 :                 res = mp->op->push(mp->next, mp->priv, data, len);
     430              :         else
     431            0 :                 res = pushf_write(mp->next, data, len);
     432            0 :         if (res > 0)
     433            0 :                 return PXE_BUG;
     434            0 :         return res;
     435            0 : }
     436              : 
     437              : /* consumes all data, returns len on success */
     438              : int
     439            0 : pushf_write(PushFilter *mp, const uint8 *data, int len)
     440              : {
     441            0 :         int                     need,
     442              :                                 res;
     443              : 
     444              :         /*
     445              :          * no buffering
     446              :          */
     447            0 :         if (mp->block_size <= 0)
     448            0 :                 return wrap_process(mp, data, len);
     449              : 
     450              :         /*
     451              :          * try to empty buffer
     452              :          */
     453            0 :         need = mp->block_size - mp->pos;
     454            0 :         if (need > 0)
     455              :         {
     456            0 :                 if (len < need)
     457              :                 {
     458            0 :                         memcpy(mp->buf + mp->pos, data, len);
     459            0 :                         mp->pos += len;
     460            0 :                         return 0;
     461              :                 }
     462            0 :                 memcpy(mp->buf + mp->pos, data, need);
     463            0 :                 len -= need;
     464            0 :                 data += need;
     465            0 :         }
     466              : 
     467              :         /*
     468              :          * buffer full, process
     469              :          */
     470            0 :         res = wrap_process(mp, mp->buf, mp->block_size);
     471            0 :         if (res < 0)
     472            0 :                 return res;
     473            0 :         mp->pos = 0;
     474              : 
     475              :         /*
     476              :          * now process directly from data
     477              :          */
     478            0 :         while (len > 0)
     479              :         {
     480            0 :                 if (len > mp->block_size)
     481              :                 {
     482            0 :                         res = wrap_process(mp, data, mp->block_size);
     483            0 :                         if (res < 0)
     484            0 :                                 return res;
     485            0 :                         data += mp->block_size;
     486            0 :                         len -= mp->block_size;
     487            0 :                 }
     488              :                 else
     489              :                 {
     490            0 :                         memcpy(mp->buf, data, len);
     491            0 :                         mp->pos += len;
     492            0 :                         break;
     493              :                 }
     494              :         }
     495            0 :         return 0;
     496            0 : }
     497              : 
     498              : int
     499            0 : pushf_flush(PushFilter *mp)
     500              : {
     501            0 :         int                     res;
     502              : 
     503            0 :         while (mp)
     504              :         {
     505            0 :                 if (mp->block_size > 0)
     506              :                 {
     507            0 :                         res = wrap_process(mp, mp->buf, mp->pos);
     508            0 :                         if (res < 0)
     509            0 :                                 return res;
     510            0 :                 }
     511              : 
     512            0 :                 if (mp->op->flush)
     513              :                 {
     514            0 :                         res = mp->op->flush(mp->next, mp->priv);
     515            0 :                         if (res < 0)
     516            0 :                                 return res;
     517            0 :                 }
     518              : 
     519            0 :                 mp = mp->next;
     520              :         }
     521            0 :         return 0;
     522            0 : }
     523              : 
     524              : 
     525              : /*
     526              :  * write to MBuf
     527              :  */
     528              : static int
     529            0 : push_into_mbuf(PushFilter *next, void *arg, const uint8 *data, int len)
     530              : {
     531            0 :         int                     res = 0;
     532            0 :         MBuf       *mbuf = arg;
     533              : 
     534            0 :         if (len > 0)
     535            0 :                 res = mbuf_append(mbuf, data, len);
     536            0 :         return res < 0 ? res : 0;
     537            0 : }
     538              : 
     539              : static const struct PushFilterOps mbuf_filter = {
     540              :         NULL, push_into_mbuf, NULL, NULL
     541              : };
     542              : 
     543              : int
     544            0 : pushf_create_mbuf_writer(PushFilter **res, MBuf *dst)
     545              : {
     546            0 :         return pushf_create(res, &mbuf_filter, dst, NULL);
     547              : }
        

Generated by: LCOV version 2.3.2-1