tbuffers.c - mixmaster - mixmaster 3.0 patched for libressl
HTML git clone git://parazyd.org/mixmaster.git
DIR Log
DIR Files
DIR Refs
DIR README
---
tbuffers.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 */