LCOV - code coverage report
Current view: top level - source3/lib - cbuf.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 123 172 71.5 %
Date: 2024-04-21 15:09:00 Functions: 15 18 83.3 %

          Line data    Source code
       1             : /*
       2             :  * Samba Unix/Linux SMB client library
       3             :  *
       4             :  * Copyright (C) Gregor Beck 2010
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : /**
      21             :  * @file   cbuf.c
      22             :  * @author Gregor Beck <gb@sernet.de>
      23             :  * @date   Aug 2010
      24             :  *
      25             :  * @brief  A talloced character buffer.
      26             :  *
      27             :  */
      28             : 
      29             : 
      30             : #include "replace.h"
      31             : #include "system/locale.h"
      32             : #include "cbuf.h"
      33             : #include <talloc.h>
      34             : #include <assert.h>
      35             : #include "lib/util/byteorder.h"
      36             : 
      37             : 
      38             : struct cbuf {
      39             :         char*  buf;
      40             :         size_t pos;
      41             :         size_t size;
      42             : };
      43             : 
      44             : 
      45        7830 : cbuf* cbuf_clear(cbuf* b)
      46             : {
      47        7830 :         cbuf_setpos(b, 0);
      48        7830 :         return b;
      49             : }
      50             : 
      51        3138 : cbuf* cbuf_new(const void* ctx)
      52             : {
      53        3138 :         cbuf* s = talloc(ctx, cbuf);
      54        3138 :         if (s == NULL)
      55           0 :                 return NULL;
      56        3138 :         s->size = 32;
      57        3138 :         s->buf  = (char *)talloc_size(s, s->size);
      58        3138 :         if (s->size && (s->buf == NULL)) {
      59           0 :                 talloc_free(s);
      60           0 :                 return NULL;
      61             :         }
      62        3138 :         return cbuf_clear(s);
      63             : }
      64             : 
      65           0 : cbuf* cbuf_copy(const cbuf* b)
      66             : {
      67           0 :         cbuf* s = talloc(talloc_parent(b), cbuf);
      68           0 :         if (s == NULL) {
      69           0 :                 return NULL;
      70             :         }
      71             : 
      72           0 :         s->buf = (char *)talloc_memdup(s, b->buf, b->size); /* only up to pos? */
      73             : 
      74             :         /* XXX shallow did not work, because realloc */
      75             :         /* fails with multiple references */
      76             :         /* s->buf = talloc_reference(s, b->buf); */
      77             : 
      78           0 :         if (s->buf == NULL) {
      79           0 :                 cbuf_delete(s);
      80           0 :                 return NULL;
      81             :         }
      82           0 :         s->size = b->size;
      83           0 :         s->pos  = b->pos;
      84           0 :         return s;
      85             : }
      86             : 
      87           0 : void cbuf_delete(cbuf* b)
      88             : {
      89           0 :         talloc_free(b);
      90           0 : }
      91             : 
      92             : #define SWAP(A,B,T) do {                        \
      93             :                 T tmp = A; A = B; B = tmp;      \
      94             :         } while(0)
      95             : 
      96             : 
      97        2522 : void cbuf_swap(cbuf* b1, cbuf* b2)
      98             : {
      99        2522 :         if (b1 == b2) {
     100           0 :                 return;
     101             :         }
     102        2522 :         talloc_reparent(b1, b2, b1->buf);
     103        2522 :         talloc_reparent(b2, b1, b2->buf);
     104        2522 :         SWAP(b1->buf,  b2->buf, char*);
     105        2522 :         SWAP(b1->pos,  b2->pos, size_t);
     106        2522 :         SWAP(b1->size, b2->size, size_t);
     107             : }
     108             : 
     109             : 
     110             : 
     111           0 : cbuf* cbuf_takeover(cbuf* b1, cbuf* b2)
     112             : {
     113           0 :         talloc_reparent(b2, b1, b2->buf);
     114           0 :         b1->buf = b2->buf;
     115           0 :         b1->pos = b2->pos;
     116           0 :         b1->size = b2->size;
     117           0 :         cbuf_delete(b2);
     118           0 :         return b1;
     119             : }
     120             : 
     121        1144 : cbuf* cbuf_swapptr(cbuf* b, char** ptr, size_t len)
     122             : {
     123        1144 :         void* p = talloc_parent(*ptr);
     124        1144 :         SWAP(b->buf, *ptr, char*);
     125        1144 :         talloc_steal(b, b->buf);
     126        1144 :         talloc_steal(p, *ptr);
     127        1144 :         b->size = talloc_get_size(b->buf);
     128        1144 :         b->pos  = (len == -1) ? strlen(b->buf) : len;
     129             : 
     130        1144 :         assert(b->pos <= b->size);
     131        1144 :         return b;
     132             : }
     133             : 
     134        3651 : cbuf* cbuf_resize(cbuf* b, size_t size)
     135             : {
     136        3651 :         char* save_buf = b->buf;
     137        3651 :         b->buf = talloc_realloc(b, b->buf, char, size);
     138        3651 :         if (b->buf == NULL) {
     139           0 :                 talloc_free(save_buf);
     140           0 :                 b->size = 0;
     141             :         } else {
     142        3651 :                 b->size = size;
     143             :         }
     144        3651 :         b->pos  = MIN(b->pos, b->size);
     145        3651 :         return b->buf ? b : NULL;
     146             : }
     147             : 
     148      258464 : char* cbuf_reserve(cbuf* b, size_t len)
     149             : {
     150      258464 :         if(b->size < b->pos + len)
     151        3651 :                 cbuf_resize(b, MAX(2*b->size, b->pos + len));
     152      258464 :         return b->buf ? b->buf + b->pos : NULL;
     153             : }
     154             : 
     155        6864 : int cbuf_puts(cbuf* b, const char* str, size_t len)
     156             : {
     157           0 :         char* dst;
     158             : 
     159        6864 :         if (b == NULL)
     160           0 :                 return 0;
     161             : 
     162        6864 :         if (len == -1) {
     163        3096 :                 len=strlen(str);
     164             :         }
     165             : 
     166        6864 :         dst = cbuf_reserve(b, len+1);
     167        6864 :         if (dst == NULL)
     168           0 :                 return -1;
     169             : 
     170        6864 :         memcpy(dst, str, len);
     171        6864 :         dst[len] = '\0'; /* just to ease debugging */
     172             : 
     173        6864 :         b->pos += len;
     174        6864 :         assert(b->pos < b->size);
     175             : 
     176        6864 :         return len;
     177             : }
     178             : 
     179      239418 : int cbuf_putc(cbuf* b, char c) {
     180           0 :         char* dst;
     181             : 
     182      239418 :         if (b == NULL)
     183           0 :                 return 0;
     184             : 
     185      239418 :         dst = cbuf_reserve(b, 2);
     186      239418 :         if (dst == NULL) {
     187           0 :                 return -1;
     188             :         }
     189             : 
     190      239418 :         dst[0] = c;
     191      239418 :         dst[1] = '\0'; /* just to ease debugging */
     192             : 
     193      239418 :         b->pos++;
     194      239418 :         assert(b->pos < b->size);
     195             : 
     196      239418 :         return 1;
     197             : }
     198             : 
     199          10 : int cbuf_putdw(cbuf* b, uint32_t u) {
     200           0 :         char* dst;
     201           0 :         static const size_t LEN = sizeof(uint32_t);
     202             : 
     203          10 :         if (b == NULL)
     204           0 :                 return 0;
     205             : 
     206          10 :         dst = cbuf_reserve(b, LEN);
     207          10 :         if (dst == NULL) {
     208           0 :                 return -1;
     209             :         }
     210             : 
     211          10 :         SIVAL(dst, 0, u);
     212             : 
     213          10 :         b->pos += LEN;
     214          10 :         assert(b->pos <= b->size); /* no NULL termination*/
     215             : 
     216          10 :         return LEN;
     217             : }
     218             : 
     219       11031 : size_t cbuf_getpos(const cbuf* b) {
     220       11031 :         assert(b->pos <= b->size);
     221       11031 :         return b->pos;
     222             : }
     223             : 
     224        8149 : void cbuf_setpos(cbuf* b, size_t pos) {
     225        8149 :         assert(pos <= b->size);
     226        8149 :         b->pos = pos;
     227        8149 :         if (pos < b->size)
     228        8149 :                 b->buf[pos] = '\0'; /* just to ease debugging */
     229        8149 : }
     230             : 
     231       12164 : char* cbuf_gets(cbuf* b, size_t idx) {
     232       12164 :         assert(idx <= b->pos);
     233             : 
     234       12164 :         if (cbuf_reserve(b, 1) == NULL)
     235           0 :                 return NULL;
     236             : 
     237       12164 :         b->buf[b->pos] = '\0';
     238       12164 :         return b->buf + idx;
     239             : }
     240             : 
     241          62 : int cbuf_printf(cbuf* b, const char* fmt, ...)
     242             : {
     243           0 :         va_list args, args2;
     244           0 :         int len;
     245          62 :         char* dst = b->buf + b->pos;
     246          62 :         const int avail = b->size - b->pos;
     247          62 :         assert(avail >= 0);
     248             : 
     249          62 :         va_start(args, fmt);
     250          62 :         va_copy(args2, args);
     251             : 
     252          62 :         len = vsnprintf(dst, avail, fmt, args);
     253             : 
     254          62 :         if (len >= avail) {
     255           0 :                 dst = cbuf_reserve(b, len+1);
     256           0 :                 len = (dst != NULL) ? vsnprintf(dst, len+1, fmt, args2) : -1;
     257             :         }
     258             : 
     259          62 :         if (len > 0) {
     260          62 :                 b->pos += len;
     261             :         }
     262             : 
     263          62 :         va_end(args);
     264          62 :         va_end(args2);
     265          62 :         assert(b->pos <= b->size);
     266             : 
     267          62 :         return len;
     268             : }
     269             : 
     270        4570 : int cbuf_print_quoted_string(cbuf* ost, const char* s)
     271             : {
     272        4570 :         int n = 1;
     273        4570 :         cbuf_putc(ost,'"');
     274             : 
     275           0 :         while(true) {
     276      102346 :                 switch (*s) {
     277        4570 :                 case '\0':
     278        4570 :                         cbuf_putc(ost, '"');
     279        4570 :                         return n+1;
     280             : 
     281          56 :                 case '"':
     282             :                 case '\\':
     283          56 :                         cbuf_putc(ost, '\\');
     284          56 :                         n++;
     285             : 
     286           0 :                         FALL_THROUGH;
     287       97776 :                 default:
     288       97776 :                         cbuf_putc(ost, *s);
     289       97776 :                         n++;
     290             :                 }
     291       97776 :                 s++;
     292             :         }
     293             : }
     294             : 
     295             : 
     296           8 : int cbuf_print_quoted(cbuf* ost, const char* s, size_t len)
     297             : {
     298           8 :         int n = 1;
     299           0 :         int ret;
     300           8 :         cbuf_reserve(ost, len+2);
     301             : 
     302           8 :         cbuf_putc(ost,'"');
     303             : 
     304         172 :         while(len--) {
     305         164 :                 switch (*s) {
     306           0 :                 case '"':
     307             :                 case '\\':
     308           0 :                         ret = cbuf_printf(ost, "\\%c", *s);
     309           0 :                         break;
     310         164 :                 default:
     311         164 :                         if (isprint(*s) && ((*s == ' ') || !isspace(*s))) {
     312         116 :                                 ret = cbuf_putc(ost, *s);
     313             :                         } else {
     314          48 :                                 ret = cbuf_printf(ost,
     315             :                                                   "\\%02x",
     316          48 :                                                   (unsigned char)*s);
     317             :                         }
     318             :                 }
     319         164 :                 s++;
     320         164 :                 if (ret == -1) {
     321           0 :                         return -1;
     322             :                 }
     323         164 :                 n += ret;
     324             :         }
     325           8 :         ret = cbuf_putc(ost,'"');
     326             : 
     327           8 :         return (ret == -1) ? -1 : (n + ret);
     328             : }

Generated by: LCOV version 1.14