mixmaster

mixmaster 3.0 patched for libressl
git clone git://parazyd.org/mixmaster.git
Log | Files | Refs | README

buffers.c (15279B)


      1 /* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
      2 
      3    Mixmaster may be redistributed and modified under certain conditions.
      4    This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
      5    ANY KIND, either express or implied. See the file COPYRIGHT for
      6    details.
      7 
      8    Dynamically allocated buffers
      9    $Id: buffers.c 934 2006-06-24 13:40:39Z rabbi $ */
     10 
     11 
     12 #include "mix3.h"
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <string.h>
     16 #include <ctype.h>
     17 #include <stdarg.h>
     18 #ifdef WIN32
     19 #include <io.h>
     20 #endif /* WIN32 */
     21 #include <assert.h>
     22 #ifdef POSIX
     23 #include <unistd.h>
     24 #endif /* POSIX */
     25 
     26 static void fail(void)
     27 {
     28   errlog(ERRORMSG, "Out of memory!\n");
     29   abort();
     30 }
     31 
     32 #define space 128		/* allocate some additional space */
     33 
     34 static void alloc(BUFFER *b)
     35 {
     36   b->data = malloc(space);
     37   if (b->data == NULL)
     38     fail();
     39   b->data[0] = 0;
     40   b->size = space;
     41 }
     42 
     43 #undef buf_new /* DEBUG */
     44 BUFFER *buf_new(void)
     45 {
     46   BUFFER *b;
     47 
     48   b = malloc(sizeof(BUFFER));
     49   if (b == NULL)
     50     fail();
     51   alloc(b);
     52   b->length = 0;
     53   b->ptr = 0;
     54   b->sensitive = 0;
     55 
     56   return (b);
     57 }
     58 
     59 #ifdef DEBUG
     60 static void sanity_check(BUFFER *b)
     61 {
     62   assert(b != NULL);
     63   assert(b->size > 0);
     64   assert(b->data != NULL);
     65   assert(b->length >= 0 && b->length < b->size);
     66   assert(b->ptr >= 0 && b->ptr <= b->length);
     67 }
     68 #else /* not DEBUG */
     69 #define sanity_check(arg)
     70 #endif /* else not DEBUG */
     71 
     72 int buf_reset(BUFFER *buffer)
     73 {
     74   sanity_check(buffer);
     75 
     76   buffer->length = 0;
     77   buffer->ptr = 0;
     78   if (buffer->sensitive)
     79     memset(buffer->data, 0, buffer->size);
     80   free(buffer->data);
     81   alloc(buffer);
     82   return (0);
     83 }
     84 
     85 int buf_free(BUFFER *buffer)
     86 {
     87   int err = 0;
     88 
     89   if (buffer->sensitive)
     90     memset(buffer->data, 0, buffer->size);
     91   free(buffer->data);
     92   free(buffer);
     93   return (err);
     94 }
     95 
     96 int buf_clear(BUFFER *buffer)
     97 {
     98   sanity_check(buffer);
     99   buffer->data[0] = '\0';
    100   buffer->length = 0;
    101   buffer->ptr = 0;
    102   return (0);
    103 }
    104 
    105 int buf_append(BUFFER *buffer, byte *msg, int len)
    106 {
    107   assert(len >= 0);
    108   sanity_check(buffer);
    109 
    110   if (buffer->length + len >= buffer->size) {
    111     register byte *new;
    112     register long newsize;
    113 
    114     newsize = 2 * buffer->length;	/* double buffer size */
    115     if (newsize < buffer->length + len + space)
    116       newsize = buffer->length + len + space;
    117     new = malloc(newsize);
    118     if (new == NULL)
    119       fail();
    120     memcpy(new, buffer->data, buffer->length);
    121     if (buffer->sensitive)
    122       memset(buffer->data, 0, buffer->size);
    123     free(buffer->data);
    124     buffer->data = new;
    125     buffer->size = newsize;
    126   }
    127   if (msg != NULL)
    128     memcpy(buffer->data + buffer->length, msg, len);
    129   buffer->length += len;
    130 
    131   buffer->data[buffer->length] = 0;
    132   return (0);
    133 }
    134 
    135 int buf_appendrnd(BUFFER *to, int n)
    136 {
    137   buf_append(to, NULL, n);
    138   rnd_bytes(to->data + to->length - n, n);
    139   return (0);
    140 }
    141 
    142 int buf_appendzero(BUFFER *to, int n)
    143 {
    144   buf_append(to, NULL, n);
    145   memset(to->data + to->length - n, 0, n);
    146   return (0);
    147 }
    148 
    149 int buf_setrnd(BUFFER *b, int n)
    150 {
    151   buf_prepare(b, n);
    152   rnd_bytes(b->data, n);
    153   return (0);
    154 }
    155 
    156 int buf_cat(BUFFER *to, BUFFER *from)
    157 {
    158   return (buf_append(to, from->data, from->length));
    159 }
    160 
    161 int buf_set(BUFFER *to, BUFFER *from)
    162 {
    163   buf_reset(to);
    164   return (buf_cat(to, from));
    165 }
    166 
    167 int buf_appendc(BUFFER *to, byte b)
    168 {
    169   return (buf_append(to, &b, 1));
    170 }
    171 
    172 int buf_rest(BUFFER *to, BUFFER *from)
    173 {
    174   assert(from != to);
    175   return (buf_append(to, from->data + from->ptr, from->length - from->ptr));
    176 }
    177 
    178 int buf_appends(BUFFER *buffer, char *s)
    179 {
    180   return (buf_append(buffer, s, strlen(s)));
    181 }
    182 
    183 int buf_sets(BUFFER *buffer, char *s)
    184 {
    185   buf_clear(buffer);
    186   return (buf_appends(buffer, s));
    187 }
    188 
    189 int buf_setc(BUFFER *buffer, byte c)
    190 {
    191   buf_clear(buffer);
    192   return (buf_appendc(buffer, c));
    193 }
    194 
    195 int buf_nl(BUFFER *b)
    196 {
    197   return (buf_append(b, "\n", 1));
    198 }
    199 
    200 int buf_vappendf(BUFFER *b, char *fmt, va_list args)
    201 {
    202   for (; *fmt != '\0'; fmt++)
    203     if (*fmt == '%') {
    204       int lzero = 0;
    205       int longvar = 0;
    206       int len = 0;
    207 
    208       for (;;) {
    209 	if (*++fmt == '\0')
    210 	  return (-1);
    211 	if (*fmt == '%') {
    212 	  buf_appendc(b, '%');
    213 	  break;
    214 	} else if (*fmt == 'b') {	/* extension of printf */
    215 	  buf_cat(b, va_arg(args, BUFFER *));
    216 
    217 	  break;
    218 	} else if (*fmt == 'c') {
    219 	  buf_appendc(b, va_arg(args, int));
    220 
    221 	  break;
    222 	} else if (*fmt == 's') {
    223 	  buf_appends(b, va_arg(args, char *));
    224 
    225 	  break;
    226 	} else if (*fmt == 'd' || *fmt == 'X') {
    227 	  int base, val, sign = 0;
    228 	  BUFFER *out;
    229 
    230 	  out = buf_new();
    231 	  base = *fmt == 'd' ? 10 : 16;
    232 	  if (longvar)
    233 	    val = va_arg(args, long);
    234 
    235 	  else
    236 	    val = va_arg(args, int);
    237 
    238 	  if (val < 0)
    239 	    sign = 1, val = -val;
    240 	  do {
    241 	    if (val % base > 9)
    242 	      buf_appendc(out, val % base - 10 + 'A');
    243 	    else
    244 	      buf_appendc(out, val % base + '0');
    245 	    val /= base;
    246 	  } while (val > 0);
    247 	  if (sign)
    248 	    len--;
    249 	  while (len-- > out->length)
    250 	    buf_appendc(b, lzero ? '0' : ' ');
    251 	  if (sign)
    252 	    buf_appendc(b, '-');
    253 	  for (len = out->length - 1; len >= 0; len--)
    254 	    buf_appendc(b, out->data[len]);
    255 	  buf_free(out);
    256 	  break;
    257 	} else if (*fmt == 'l')
    258 	  longvar = 1;
    259 	else if (*fmt == '0' && len == 0)
    260 	  lzero = 1;
    261 	else if (isdigit(*fmt))
    262 	  len = len * 10 + *fmt - '0';
    263 	else
    264 	  assert(0);
    265       }
    266     } else
    267       buf_appendc(b, *fmt);
    268   return (0);
    269 }
    270 
    271 int buf_setf(BUFFER *b, char *fmt, ...)
    272 {
    273   va_list args;
    274   int ret;
    275 
    276   va_start(args, fmt);
    277   buf_clear(b);
    278   ret = buf_vappendf(b, fmt, args);
    279   va_end(args);
    280   return (ret);
    281 }
    282 
    283 int buf_appendf(BUFFER *b, char *fmt, ...)
    284 {
    285   va_list args;
    286   int ret;
    287 
    288   va_start(args, fmt);
    289   ret = buf_vappendf(b, fmt, args);
    290   va_end(args);
    291   return (ret);
    292 }
    293 
    294 int buf_pad(BUFFER *buffer, int size)
    295 {
    296   assert(size - buffer->length >= 0);
    297   buf_appendrnd(buffer, size - buffer->length);
    298   return (0);
    299 }
    300 
    301 int buf_prepare(BUFFER *buffer, int size)
    302 {
    303   buf_clear(buffer);
    304   buf_append(buffer, NULL, size);
    305   return (0);
    306 }
    307 
    308 int buf_read(BUFFER *outmsg, FILE *infile)
    309 {
    310   char buf[BUFSIZE];
    311   int n;
    312   int err = -1;
    313 
    314   assert(infile != NULL);
    315   sanity_check(outmsg);
    316 
    317   for (;;) {
    318     n = fread(buf, 1, BUFSIZE, infile);
    319     if (n > 0)
    320       err = 0;
    321     buf_append(outmsg, buf, n);
    322     if (n < BUFSIZE)
    323       break;
    324 #ifdef BUFFER_MAX
    325     if (outmsg->length > BUFFER_MAX) {
    326       errlog(ERRORMSG, "Message file too large. Giving up.\n");
    327       return (1);
    328     }
    329 #endif /* BUFFER_MAX */
    330   }
    331 
    332 #ifdef WIN32
    333   if (isatty(fileno(infile)) && isatty(fileno(stdout)))
    334     printf("\n");
    335 #endif /* WIN32 */
    336 
    337   return (err);
    338 }
    339 
    340 int buf_write(BUFFER *buffer, FILE *out)
    341 {
    342   assert(out != NULL);
    343   sanity_check(buffer);
    344 
    345   return (fwrite(buffer->data, 1, buffer->length, out) == buffer->length
    346 	  ? 0 : -1);
    347 }
    348 
    349 int buf_write_sync(BUFFER *buffer, FILE *out)
    350 {
    351     int ret = 0;
    352 
    353     if (buf_write(buffer, out) == -1) {
    354       fclose(out);
    355       return -1;
    356     }
    357 
    358     if (fflush(out) != 0)
    359       ret = -1;
    360 
    361 #ifdef POSIX
    362     /* dir entry not synced */
    363     if (fsync(fileno(out)) != 0)
    364       ret = -1;
    365 #endif /* POSIX */
    366 
    367     if (fclose(out) != 0)
    368       ret = -1;
    369 
    370     return ret;
    371 }
    372 
    373 int buf_rewind(BUFFER *buffer)
    374 {
    375   sanity_check(buffer);
    376 
    377   buffer->ptr = 0;
    378   return (0);
    379 }
    380 
    381 int buf_get(BUFFER *buffer, BUFFER *to, int n)
    382 {
    383   sanity_check(buffer);
    384   sanity_check(to);
    385   assert(n > 0);
    386   assert(buffer != to);
    387 
    388   buf_clear(to);
    389   if (buffer->length - buffer->ptr < n)
    390     return (-1);
    391   buf_append(to, buffer->data + buffer->ptr, n);
    392   buffer->ptr += n;
    393   return (0);
    394 }
    395 
    396 int buf_getc(BUFFER *buffer)
    397 {
    398   sanity_check(buffer);
    399   if (buffer->ptr == buffer->length)
    400     return (-1);
    401   else
    402     return (buffer->data[buffer->ptr++]);
    403 }
    404 
    405 void buf_ungetc(BUFFER *buffer)
    406 {
    407   sanity_check(buffer);
    408   if (buffer->ptr > 0)
    409     buffer->ptr--;
    410 }
    411 
    412 int buf_getline(BUFFER *buffer, BUFFER *line)
    413 {
    414   register int i;
    415   int ret = 0;
    416   int nl = 0;
    417 
    418   sanity_check(buffer);
    419 
    420   if (line != NULL)
    421     buf_clear(line);
    422   if (buffer->ptr == buffer->length)
    423     return (-1);
    424 
    425   for (i = buffer->ptr; i < buffer->length; i++) {
    426     if (buffer->data[i] > '\r')
    427       continue;
    428     if (buffer->data[i] == '\0' || buffer->data[i] == '\n') {
    429       nl = 1;
    430       break;
    431     }
    432     if (buffer->data[i] == '\r' &&
    433 	i + 1 <= buffer->length && buffer->data[i + 1] == '\n') {
    434       nl = 2;
    435       break;
    436     }
    437   }
    438 
    439   if (line != NULL)
    440     buf_append(line, buffer->data + buffer->ptr, i - buffer->ptr);
    441   if (i == buffer->ptr)
    442     ret = 1;
    443   buffer->ptr = i + nl;
    444 
    445   return (ret);
    446 }
    447 
    448 int buf_chop(BUFFER *b)
    449 {
    450   int i;
    451 
    452   sanity_check(b);
    453 
    454   for (i = 0; i < b->length; i++)
    455     if (b->data[i] == '\0' || b->data[i] == '\n' ||
    456 	(b->data[i] == '\r' && i + 1 < b->length &&
    457 	 b->data[i + 1] == '\n'))
    458       b->length = i;
    459   b->data[b->length] = 0;
    460   return (0);
    461 }
    462 
    463 int buf_isheader(BUFFER *buffer)
    464 {
    465   BUFFER *line;
    466   long p;
    467   int i;
    468   int err;
    469   int ret;
    470 
    471   line = buf_new();
    472   p = buffer->ptr;
    473   ret = 0;
    474   err = buf_getline(buffer, line);
    475   if (err != 0)
    476     goto end;
    477 
    478   for (i = 0; i < line->length; i++) {
    479     if (line->data[i] == ' ' || line->data[i] == '\t')
    480       break;
    481     if (line->data[i] == ':') {
    482       ret = 1;
    483       break;
    484     }
    485   }
    486 
    487 end:
    488   buffer->ptr = p;
    489   buf_free(line);
    490   return(ret);
    491 }
    492 
    493 int buf_getheader(BUFFER *buffer, BUFFER *field, BUFFER *content)
    494 {
    495   BUFFER *line;
    496   long p;
    497   int i;
    498   int err;
    499 
    500   line = buf_new();
    501   buf_reset(field);
    502   buf_reset(content);
    503 
    504   err = buf_getline(buffer, line);
    505   if (err != 0)
    506     goto end;
    507 
    508   err = -1;
    509   for (i = 0; i < line->length; i++) {
    510     if (line->data[i] == ' ' || line->data[i] == '\t')
    511       break;
    512     if (line->data[i] == ':') {
    513       err = 0;
    514       break;
    515     }
    516   }
    517   if (err == -1 && bufileft(line, "From ")) {
    518     buf_set(field, line);
    519     err = 0;
    520   }
    521   if (err == -1) {
    522     /* badly formatted message -- try to process anyway */
    523     buf_sets(field, "X-Invalid");
    524     buf_set(content, line);
    525     err = 0;
    526     goto end;
    527   }
    528   buf_append(field, line->data, i);
    529   if (i < line->length)
    530     i++;
    531   else
    532     err = 1;
    533   while (i < line->length &&
    534 	 (line->data[i] == ' ' || line->data[i] == '\t'))
    535     i++;
    536   buf_append(content, line->data + i, line->length - i);
    537 
    538   for (;;) {
    539     p = buffer->ptr;
    540     if (buf_getline(buffer, line) != 0)
    541       break;
    542     if (line->data[0] != ' ' && line->data[0] != '\t')
    543       break;
    544 #if 1
    545     buf_nl(content);
    546     buf_cat(content, line);
    547 #else /* end of 1 */
    548     buf_appendc(content, ' ');
    549     buf_appends(content, line->data + 1);
    550 #endif /* else if not 1 */
    551   }
    552   buffer->ptr = p;
    553 end:
    554   buf_free(line);
    555   return (err);
    556 }
    557 
    558 int buf_appendheader(BUFFER *buffer, BUFFER *field, BUFFER *content)
    559 {
    560   return buf_appendf(buffer, "%b: %b\n", field, content);
    561 }
    562 
    563 int buf_lookahead(BUFFER *buffer, BUFFER *line)
    564 {
    565   long p;
    566   int e;
    567 
    568   p = buffer->ptr;
    569   e = buf_getline(buffer, line);
    570   buffer->ptr = p;
    571   return (e);
    572 }
    573 
    574 int buf_eq(BUFFER *b1, BUFFER *b2)
    575 {
    576   sanity_check(b1);
    577   sanity_check(b2);
    578 
    579   if (b1->length != b2->length)
    580     return (0);
    581   if (b1->length > 0 && memcmp(b1->data, b2->data, b1->length) != 0)
    582     return (0);
    583   return (1);
    584 }
    585 
    586 int buf_ieq(BUFFER *b1, BUFFER *b2)
    587 {
    588   int i;
    589   sanity_check(b1);
    590   sanity_check(b2);
    591 
    592   if (b1->length != b2->length)
    593     return (0);
    594   for (i = 0; i < b1->length; i++)
    595     if (tolower(b1->data[i]) != tolower(b2->data[i]))
    596       return (0);
    597   return (1);
    598 }
    599 
    600 void buf_move(BUFFER *dest, BUFFER *src)
    601      /* equivalent to buf_set(dest, src); buf_reset(src); */
    602 {
    603   BUFFER temp;
    604   sanity_check(src);
    605   buf_reset(dest);
    606   temp.data = dest->data, temp.size = dest->size;
    607   dest->data = src->data, dest->size = src->size, dest->length = src->length;
    608   src->data = temp.data, src->size = temp.size, src->length = 0;
    609   dest->ptr = 0, src->ptr = 0;
    610 }
    611 
    612 int buf_appendl(BUFFER *b, long l)
    613 {
    614   buf_appendc(b, (l >> 24) & 255);
    615   buf_appendc(b, (l >> 16) & 255);
    616   buf_appendc(b, (l >> 8) & 255);
    617   buf_appendc(b, l & 255);
    618   return (0);
    619 }
    620 
    621 int buf_appendl_lo(BUFFER *b, long l)
    622 {
    623   buf_appendc(b, l & 255);
    624   buf_appendc(b, (l >> 8) & 255);
    625   buf_appendc(b, (l >> 16) & 255);
    626   buf_appendc(b, (l >> 24) & 255);
    627   return (0);
    628 }
    629 
    630 long buf_getl(BUFFER *b)
    631 {
    632   long l;
    633 
    634   if (b->ptr + 4 > b->length)
    635     return (-1);
    636   l = buf_getc(b) << 24;
    637   l += buf_getc(b) << 16;
    638   l += buf_getc(b) << 8;
    639   l += buf_getc(b);
    640   return (l);
    641 }
    642 
    643 long buf_getl_lo(BUFFER *b)
    644 {
    645   long l;
    646 
    647   if (b->ptr + 4 > b->length)
    648     return (-1);
    649   l = buf_getc(b);
    650   l += buf_getc(b) << 8;
    651   l += buf_getc(b) << 16;
    652   l += buf_getc(b) << 24;
    653 
    654   return (l);
    655 }
    656 
    657 int buf_appendi(BUFFER *b, int i)
    658 {
    659   buf_appendc(b, (i >> 8) & 255);
    660   buf_appendc(b, i & 255);
    661   return (0);
    662 }
    663 
    664 int buf_appendi_lo(BUFFER *b, int i)
    665 {
    666   buf_appendc(b, i & 255);
    667   buf_appendc(b, (i >> 8) & 255);
    668   return (0);
    669 }
    670 
    671 int buf_geti(BUFFER *b)
    672 {
    673   int i;
    674 
    675   if (b->ptr + 2 > b->length)
    676     return (-1);
    677   i = buf_getc(b) << 8;
    678   i += buf_getc(b);
    679   return (i);
    680 }
    681 
    682 int buf_geti_lo(BUFFER *b)
    683 {
    684   int i;
    685 
    686   if (b->ptr + 2 > b->length)
    687     return (-1);
    688   i = buf_getc(b);
    689   i += buf_getc(b) << 8;
    690   return (i);
    691 }
    692 
    693 int buf_getb(BUFFER *b, BUFFER *p)
    694 {
    695   long l;
    696 
    697   l = buf_getl(b);
    698   return (buf_get(b, p, l));
    699 }
    700 
    701 int buf_appendb(BUFFER *b, BUFFER *p)
    702 {
    703   long l;
    704 
    705   l = p->length;
    706   buf_appendl(b, l);
    707   return (buf_cat(b, p));
    708 }
    709 
    710 int bufleft(BUFFER *b, char *k) {
    711   return(strleft(b->data, k));
    712 }
    713 
    714 int bufileft(BUFFER *b, char *k) {
    715   return(strileft(b->data, k));
    716 }
    717 
    718 int buffind(BUFFER *b, char *k) {
    719   return(strfind(b->data, k));
    720 }
    721 
    722 int bufifind(BUFFER *b, char *k) {
    723   return(strifind(b->data, k));
    724 }
    725 
    726 int bufiright(BUFFER *b, char *k) {
    727   int l = strlen(k);
    728   if (l <= b->length)
    729     return (strieq(b->data + b->length - l, k));
    730   return(0);
    731 }
    732 
    733 int bufeq(BUFFER *b, char *k) {
    734   return(streq(b->data, k));
    735 }
    736 
    737 int bufieq(BUFFER *b, char *k) {
    738   return(strieq(b->data, k));
    739 }
    740 
    741 /* void buf_cut_out(BUFFER *buffer, BUFFER *cut_out, BUFFER *rest,
    742  *                  int from, int len);
    743  *
    744  * Cut a chunk out of the buffer.
    745  *
    746  * Starting with from, len bytes are cut out of buffer. The chunk
    747  * of text that has been cut out is returned in cut_out, the
    748  * remainings of buffer are returned in rest.
    749  *
    750  * This function was added by Gerd Beuster. (gb@uni-koblenz.de)
    751  */
    752 
    753 void buf_cut_out(BUFFER *buffer, BUFFER *cut_out, BUFFER *rest,
    754 		 int from, int len){
    755 
    756   assert((len >= 0) && (from >= 0));
    757   assert(from+len <= buffer->length);
    758   assert(cut_out != rest);
    759 
    760   buffer->ptr = 0;
    761   if(from > 0)
    762     buf_get(buffer, rest, from);
    763   buf_get(buffer, cut_out, len);
    764   buf_rest(rest, buffer);
    765 }
    766 
    767 
    768 #ifdef DEBUG
    769 /* check for memory leaks */
    770 #undef malloc
    771 #undef free
    772 void *malloc(size_t size);
    773 void free(void *ptr);
    774 #define max 100000
    775 static int n=0;
    776 static void *m[max];
    777 static char *mm[max];
    778 
    779 void mix3_leaks(void) {
    780   int i, ok=1;
    781   for (i = 0; i < n; i++)
    782     if (m[i]) {
    783       fprintf(stderr, "Leak [%d] %s\n", i, mm[i]);
    784       ok = 0;
    785     }
    786   if (ok)
    787     fprintf(stderr, "No memory leaks.\n");
    788 }
    789 
    790 void *mix3_malloc(size_t size) {
    791   void *ptr;
    792   if (n == 0)
    793     atexit(mix3_leaks);
    794   ptr = malloc(size);
    795   if (n >= max) abort();
    796   m[n++] = ptr;
    797   mm[n] = "?";
    798   return(ptr);
    799 }
    800 
    801 void mix3_free(void *ptr) {
    802   int i;
    803   for (i = 0; i < n; i++)
    804     if (m[i] == ptr) {
    805       m[i] = 0;
    806       break;
    807     }
    808   free(ptr);
    809 }
    810 
    811 BUFFER *mix3_bufnew(char *file, int line, char *func) {
    812   mm[n] = malloc(strlen(file) + strlen(func) + 15);
    813   sprintf(mm[n], "in %s %s:%d", func, file, line);
    814   return(buf_new());
    815 }
    816 #endif /* DEBUG */