1/*- 2 * Copyright (c) 2003-2006, Maxime Henrion <mux@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29#include <sys/types.h> 30#include <sys/stat.h> 31 32#include <assert.h> 33#include <zlib.h> 34#include <err.h> 35#include <errno.h> 36#include <fcntl.h> 37#include <stdarg.h> 38#include <stdio.h> 39#include <stdlib.h> 40#include <string.h> 41#include <unistd.h> 42 43#include "misc.h" 44#include "stream.h" 45 46/* 47 * Simple stream API to make my life easier. If the fgetln() and 48 * funopen() functions were standard and if funopen() wasn't using 49 * wrong types for the function pointers, I could have just used 50 * stdio, but life sucks. 51 * 52 * For now, streams are always block-buffered. 53 */ 54 55/* 56 * Try to quiet warnings as much as possible with GCC while staying 57 * compatible with other compilers. 58 */ 59#ifndef __unused 60#if defined(__GNUC__) && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7) 61#define __unused __attribute__((__unused__)) 62#else 63#define __unused 64#endif 65#endif 66 67/* 68 * Flags passed to the flush methods. 69 * 70 * STREAM_FLUSH_CLOSING is passed during the last flush call before 71 * closing a stream. This allows the zlib filter to emit the EOF 72 * marker as appropriate. In all other cases, STREAM_FLUSH_NORMAL 73 * should be passed. 74 * 75 * These flags are completely unused in the default flush method, 76 * but they are very important for the flush method of the zlib 77 * filter. 78 */ 79typedef enum { 80 STREAM_FLUSH_NORMAL, 81 STREAM_FLUSH_CLOSING 82} stream_flush_t; 83 84/* 85 * This is because buf_new() will always allocate size + 1 bytes, 86 * so our buffer sizes will still be power of 2 values. 87 */ 88#define STREAM_BUFSIZ 1023 89 90struct buf { 91 char *buf; 92 size_t size; 93 size_t in; 94 size_t off; 95}; 96 97struct stream { 98 void *cookie; 99 int fd; 100 int buf; 101 struct buf *rdbuf; 102 struct buf *wrbuf; 103 stream_readfn_t *readfn; 104 stream_writefn_t *writefn; 105 stream_closefn_t *closefn; 106 int eof; 107 struct stream_filter *filter; 108 void *fdata; 109}; 110 111typedef int stream_filter_initfn_t(struct stream *, void *); 112typedef void stream_filter_finifn_t(struct stream *); 113typedef int stream_filter_flushfn_t(struct stream *, struct buf *, 114 stream_flush_t); 115typedef ssize_t stream_filter_fillfn_t(struct stream *, struct buf *); 116 117struct stream_filter { 118 stream_filter_t id; 119 stream_filter_initfn_t *initfn; 120 stream_filter_finifn_t *finifn; 121 stream_filter_fillfn_t *fillfn; 122 stream_filter_flushfn_t *flushfn; 123}; 124 125/* Low-level buffer API. */ 126#define buf_avail(buf) ((buf)->size - (buf)->off - (buf)->in) 127#define buf_count(buf) ((buf)->in) 128#define buf_size(buf) ((buf)->size) 129 130static void buf_more(struct buf *, size_t); 131static void buf_less(struct buf *, size_t); 132static void buf_grow(struct buf *, size_t); 133 134/* Internal stream functions. */ 135static ssize_t stream_fill(struct stream *); 136static ssize_t stream_fill_default(struct stream *, struct buf *); 137static int stream_flush_int(struct stream *, stream_flush_t); 138static int stream_flush_default(struct stream *, struct buf *, 139 stream_flush_t); 140 141/* Filters specific functions. */ 142static struct stream_filter *stream_filter_lookup(stream_filter_t); 143static int stream_filter_init(struct stream *, void *); 144static void stream_filter_fini(struct stream *); 145 146/* The zlib stream filter declarations. */ 147#define ZFILTER_EOF 1 /* Got Z_STREAM_END. */ 148 149struct zfilter { 150 int flags; 151 struct buf *rdbuf; 152 struct buf *wrbuf; 153 z_stream *rdstate; 154 z_stream *wrstate; 155}; 156 157static int zfilter_init(struct stream *, void *); 158static void zfilter_fini(struct stream *); 159static ssize_t zfilter_fill(struct stream *, struct buf *); 160static int zfilter_flush(struct stream *, struct buf *, 161 stream_flush_t); 162 163/* The MD5 stream filter. */ 164struct md5filter { 165 MD5_CTX ctx; 166 char *md5; 167 char lastc; 168#define PRINT 1 169#define WS 2 170#define STRING 3 171#define SEEN 4 172 int state; 173}; 174 175static int md5filter_init(struct stream *, void *); 176static void md5filter_fini(struct stream *); 177static ssize_t md5filter_fill(struct stream *, struct buf *); 178static int md5filter_flush(struct stream *, struct buf *, 179 stream_flush_t); 180static int md5rcsfilter_flush(struct stream *, struct buf *, 181 stream_flush_t); 182 183/* The available stream filters. */ 184struct stream_filter stream_filters[] = { 185 { 186 STREAM_FILTER_NULL, 187 NULL, 188 NULL, 189 stream_fill_default, 190 stream_flush_default 191 }, 192 { 193 STREAM_FILTER_ZLIB, 194 zfilter_init, 195 zfilter_fini, 196 zfilter_fill, 197 zfilter_flush 198 }, 199 { 200 STREAM_FILTER_MD5, 201 md5filter_init, 202 md5filter_fini, 203 md5filter_fill, 204 md5filter_flush 205 }, 206 { 207 STREAM_FILTER_MD5RCS, 208 md5filter_init, 209 md5filter_fini, 210 md5filter_fill, 211 md5rcsfilter_flush 212 } 213 214}; 215 216 217/* Create a new buffer. */ 218struct buf * 219buf_new(size_t size) 220{ 221 struct buf *buf; 222 223 buf = xmalloc(sizeof(struct buf)); 224 /* 225 * We keep one spare byte so that stream_getln() can put a '\0' 226 * there in case the stream doesn't have an ending newline. 227 */ 228 buf->buf = xmalloc(size + 1); 229 memset(buf->buf, 0, size + 1); 230 buf->size = size; 231 buf->in = 0; 232 buf->off = 0; 233 return (buf); 234} 235 236/* 237 * Grow the size of the buffer. If "need" is 0, bump its size to the 238 * next power of 2 value. Otherwise, bump it to the next power of 2 239 * value bigger than "need". 240 */ 241static void 242buf_grow(struct buf *buf, size_t need) 243{ 244 245 if (need == 0) 246 buf->size = buf->size * 2 + 1; /* Account for the spare byte. */ 247 else { 248 assert(need > buf->size); 249 while (buf->size < need) 250 buf->size = buf->size * 2 + 1; 251 } 252 buf->buf = xrealloc(buf->buf, buf->size + 1); 253} 254 255/* Make more room in the buffer if needed. */ 256static void 257buf_prewrite(struct buf *buf) 258{ 259 260 if (buf_count(buf) == buf_size(buf)) 261 buf_grow(buf, 0); 262 if (buf_count(buf) > 0 && buf_avail(buf) == 0) { 263 memmove(buf->buf, buf->buf + buf->off, buf_count(buf)); 264 buf->off = 0; 265 } 266} 267 268/* Account for "n" bytes being added in the buffer. */ 269static void 270buf_more(struct buf *buf, size_t n) 271{ 272 273 assert(n <= buf_avail(buf)); 274 buf->in += n; 275} 276 277/* Account for "n" bytes having been read in the buffer. */ 278static void 279buf_less(struct buf *buf, size_t n) 280{ 281 282 assert(n <= buf_count(buf)); 283 buf->in -= n; 284 if (buf->in == 0) 285 buf->off = 0; 286 else 287 buf->off += n; 288} 289 290/* Free a buffer. */ 291void 292buf_free(struct buf *buf) 293{ 294 295 free(buf->buf); 296 free(buf); 297} 298 299static struct stream * 300stream_new(stream_readfn_t *readfn, stream_writefn_t *writefn, 301 stream_closefn_t *closefn) 302{ 303 struct stream *stream; 304 305 stream = xmalloc(sizeof(struct stream)); 306 if (readfn == NULL && writefn == NULL) { 307 errno = EINVAL; 308 return (NULL); 309 } 310 if (readfn != NULL) 311 stream->rdbuf = buf_new(STREAM_BUFSIZ); 312 else 313 stream->rdbuf = NULL; 314 if (writefn != NULL) 315 stream->wrbuf = buf_new(STREAM_BUFSIZ); 316 else 317 stream->wrbuf = NULL; 318 stream->cookie = NULL; 319 stream->fd = -1; 320 stream->buf = 0; 321 stream->readfn = readfn; 322 stream->writefn = writefn; 323 stream->closefn = closefn; 324 stream->filter = stream_filter_lookup(STREAM_FILTER_NULL); 325 stream->fdata = NULL; 326 stream->eof = 0; 327 return (stream); 328} 329 330/* Create a new stream associated with a void *. */ 331struct stream * 332stream_open(void *cookie, stream_readfn_t *readfn, stream_writefn_t *writefn, 333 stream_closefn_t *closefn) 334{ 335 struct stream *stream; 336 337 stream = stream_new(readfn, writefn, closefn); 338 stream->cookie = cookie; 339 return (stream); 340} 341 342/* Associate a file descriptor with a stream. */ 343struct stream * 344stream_open_fd(int fd, stream_readfn_t *readfn, stream_writefn_t *writefn, 345 stream_closefn_t *closefn) 346{ 347 struct stream *stream; 348 349 stream = stream_new(readfn, writefn, closefn); 350 stream->cookie = &stream->fd; 351 stream->fd = fd; 352 return (stream); 353} 354 355/* Associate a buf with a stream. */ 356struct stream * 357stream_open_buf(struct buf *b) 358{ 359 struct stream *stream; 360 361 stream = stream_new(stream_read_buf, stream_append_buf, stream_close_buf); 362 stream->cookie = b; 363 stream->buf = 1; 364 b->in = 0; 365 return (stream); 366} 367 368/* 369 * Truncate a buffer, just decrease offset pointer. 370 * XXX: this can be dangerous if not used correctly. 371 */ 372void 373stream_truncate_buf(struct buf *b, off_t off) 374{ 375 b->off += off; 376} 377 378/* Like open() but returns a stream. */ 379struct stream * 380stream_open_file(const char *path, int flags, ...) 381{ 382 struct stream *stream; 383 stream_readfn_t *readfn; 384 stream_writefn_t *writefn; 385 va_list ap; 386 mode_t mode; 387 int fd; 388 389 va_start(ap, flags); 390 if (flags & O_CREAT) { 391 /* 392 * GCC says I should not be using mode_t here since it's 393 * promoted to an int when passed through `...'. 394 */ 395 mode = va_arg(ap, int); 396 fd = open(path, flags, mode); 397 } else 398 fd = open(path, flags); 399 va_end(ap); 400 if (fd == -1) 401 return (NULL); 402 403 flags &= O_ACCMODE; 404 if (flags == O_RDONLY) { 405 readfn = stream_read_fd; 406 writefn = NULL; 407 } else if (flags == O_WRONLY) { 408 readfn = NULL; 409 writefn = stream_write_fd; 410 } else if (flags == O_RDWR) { 411 assert(flags == O_RDWR); 412 readfn = stream_read_fd; 413 writefn = stream_write_fd; 414 } else { 415 errno = EINVAL; 416 close(fd); 417 return (NULL); 418 } 419 420 stream = stream_open_fd(fd, readfn, writefn, stream_close_fd); 421 if (stream == NULL) 422 close(fd); 423 return (stream); 424} 425 426/* Return the file descriptor associated with this stream, or -1. */ 427int 428stream_fileno(struct stream *stream) 429{ 430 431 return (stream->fd); 432} 433 434/* Convenience read function for character buffers. */ 435ssize_t 436stream_read_buf(void *cookie, void *buf, size_t size) 437{ 438 struct buf *b; 439 size_t avail; 440 441 /* Use in to be read offset. */ 442 b = (struct buf *)cookie; 443 /* Just return what we have if the request is to large. */ 444 avail = b->off - b->in; 445 if (avail < size) { 446 memcpy(buf, (b->buf + b->in), avail); 447 b->in += avail; 448 return (avail); 449 } 450 memcpy(buf, (b->buf + b->in), size); 451 b->in += size; 452 return (size); 453} 454 455/* Convenience write function for appending character buffers. */ 456ssize_t 457stream_append_buf(void *cookie, const void *buf, size_t size) 458{ 459 struct buf *b; 460 size_t avail; 461 462 /* Use off to be write offset. */ 463 b = (struct buf *)cookie; 464 465 avail = b->size - b->off; 466 if (size > avail) 467 buf_grow(b, b->size + size); 468 memcpy((b->buf + b->off), buf, size); 469 b->off += size; 470 b->buf[b->off] = '\0'; 471 return (size); 472} 473 474/* Convenience close function for freeing character buffers. */ 475int 476stream_close_buf(void *cookie) 477{ 478 void *data; 479 480 data = cookie; 481 /* Basically a NOP. */ 482 return (0); 483} 484 485/* Convenience read function for file descriptors. */ 486ssize_t 487stream_read_fd(void *cookie, void *buf, size_t size) 488{ 489 ssize_t nbytes; 490 int fd; 491 492 fd = *(int *)cookie; 493 nbytes = read(fd, buf, size); 494 return (nbytes); 495} 496 497/* Convenience write function for file descriptors. */ 498ssize_t 499stream_write_fd(void *cookie, const void *buf, size_t size) 500{ 501 ssize_t nbytes; 502 int fd; 503 504 fd = *(int *)cookie; 505 nbytes = write(fd, buf, size); 506 return (nbytes); 507} 508 509/* Convenience close function for file descriptors. */ 510int 511stream_close_fd(void *cookie) 512{ 513 int fd, ret; 514 515 fd = *(int *)cookie; 516 ret = close(fd); 517 return (ret); 518} 519 520/* Read some bytes from the stream. */ 521ssize_t 522stream_read(struct stream *stream, void *buf, size_t size) 523{ 524 struct buf *rdbuf; 525 ssize_t ret; 526 size_t n; 527 528 rdbuf = stream->rdbuf; 529 if (buf_count(rdbuf) == 0) { 530 ret = stream_fill(stream); 531 if (ret <= 0) 532 return (-1); 533 } 534 n = min(size, buf_count(rdbuf)); 535 memcpy(buf, rdbuf->buf + rdbuf->off, n); 536 buf_less(rdbuf, n); 537 return (n); 538} 539 540/* A blocking stream_read call. */ 541ssize_t 542stream_read_blocking(struct stream *stream, void *buf, size_t size) 543{ 544 struct buf *rdbuf; 545 ssize_t ret; 546 size_t n; 547 548 rdbuf = stream->rdbuf; 549 while (buf_count(rdbuf) <= size) { 550 ret = stream_fill(stream); 551 if (ret <= 0) 552 return (-1); 553 } 554 /* XXX: Should be at least size bytes in the buffer, right? */ 555 /* Just do this to make sure. */ 556 n = min(size, buf_count(rdbuf)); 557 memcpy(buf, rdbuf->buf + rdbuf->off, n); 558 buf_less(rdbuf, n); 559 return (n); 560} 561 562/* 563 * Read a line from the stream and return a pointer to it. 564 * 565 * If "len" is non-NULL, the length of the string will be put into it. 566 * The pointer is only valid until the next stream API call. The line 567 * can be modified by the caller, provided he doesn't write before or 568 * after it. 569 * 570 * This is somewhat similar to the BSD fgetln() function, except that 571 * "len" can be NULL here. In that case the string is terminated by 572 * overwriting the '\n' character with a NUL character. If it's the 573 * last line in the stream and it has no ending newline, we can still 574 * add '\0' after it, because we keep one spare byte in the buffers. 575 * 576 * However, be warned that one can't handle binary lines properly 577 * without knowing the size of the string since those can contain 578 * NUL characters. 579 */ 580char * 581stream_getln(struct stream *stream, size_t *len) 582{ 583 struct buf *buf; 584 char *cp, *line; 585 ssize_t n; 586 size_t done, size; 587 588 buf = stream->rdbuf; 589 if (buf_count(buf) == 0) { 590 n = stream_fill(stream); 591 if (n <= 0) 592 return (NULL); 593 } 594 cp = memchr(buf->buf + buf->off, '\n', buf_count(buf)); 595 for (done = buf_count(buf); cp == NULL; done += n) { 596 n = stream_fill(stream); 597 if (n < 0) 598 return (NULL); 599 if (n == 0) 600 /* Last line of the stream. */ 601 cp = buf->buf + buf->off + buf->in - 1; 602 else 603 cp = memchr(buf->buf + buf->off + done, '\n', 604 buf_count(buf) - done); 605 } 606 line = buf->buf + buf->off; 607 assert(cp >= line); 608 size = cp - line + 1; 609 buf_less(buf, size); 610 if (len != NULL) { 611 *len = size; 612 } else { 613 /* Terminate the string when len == NULL. */ 614 if (line[size - 1] == '\n') 615 line[size - 1] = '\0'; 616 else 617 line[size] = '\0'; 618 } 619 return (line); 620} 621 622/* Write some bytes to a stream. */ 623ssize_t 624stream_write(struct stream *stream, const void *src, size_t nbytes) 625{ 626 struct buf *buf; 627 int error; 628 629 buf = stream->wrbuf; 630 if (nbytes > buf_size(buf)) 631 buf_grow(buf, nbytes); 632 if (nbytes > buf_avail(buf)) { 633 error = stream_flush_int(stream, STREAM_FLUSH_NORMAL); 634 if (error) 635 return (-1); 636 } 637 memcpy(buf->buf + buf->off + buf->in, src, nbytes); 638 buf_more(buf, nbytes); 639 return (nbytes); 640} 641 642/* Formatted output to a stream. */ 643int 644stream_printf(struct stream *stream, const char *fmt, ...) 645{ 646 struct buf *buf; 647 va_list ap; 648 int error, ret; 649 650 buf = stream->wrbuf; 651again: 652 va_start(ap, fmt); 653 ret = vsnprintf(buf->buf + buf->off + buf->in, buf_avail(buf), fmt, ap); 654 va_end(ap); 655 if (ret < 0) 656 return (ret); 657 if ((unsigned)ret >= buf_avail(buf)) { 658 if ((unsigned)ret >= buf_size(buf)) 659 buf_grow(buf, ret + 1); 660 if ((unsigned)ret >= buf_avail(buf)) { 661 error = stream_flush_int(stream, STREAM_FLUSH_NORMAL); 662 if (error) 663 return (-1); 664 } 665 goto again; 666 } 667 buf_more(buf, ret); 668 return (ret); 669} 670 671/* Flush the entire write buffer of the stream. */ 672int 673stream_flush(struct stream *stream) 674{ 675 int error; 676 677 error = stream_flush_int(stream, STREAM_FLUSH_NORMAL); 678 return (error); 679} 680 681/* Internal flush API. */ 682static int 683stream_flush_int(struct stream *stream, stream_flush_t how) 684{ 685 struct buf *buf; 686 int error; 687 688 buf = stream->wrbuf; 689 error = (*stream->filter->flushfn)(stream, buf, how); 690 assert(buf_count(buf) == 0); 691 return (error); 692} 693 694/* The default flush method. */ 695static int 696stream_flush_default(struct stream *stream, struct buf *buf, 697 stream_flush_t __unused how) 698{ 699 ssize_t n; 700 701 while (buf_count(buf) > 0) { 702 do { 703 n = (*stream->writefn)(stream->cookie, 704 buf->buf + buf->off, buf_count(buf)); 705 } while (n == -1 && errno == EINTR); 706 if (n <= 0) 707 return (-1); 708 buf_less(buf, n); 709 } 710 return (0); 711} 712 713/* Flush the write buffer and call fsync() on the file descriptor. */ 714int 715stream_sync(struct stream *stream) 716{ 717 int error; 718 719 if (stream->fd == -1) { 720 errno = EINVAL; 721 return (-1); 722 } 723 error = stream_flush_int(stream, STREAM_FLUSH_NORMAL); 724 if (error) 725 return (-1); 726 error = fsync(stream->fd); 727 return (error); 728} 729 730/* Like truncate() but on a stream. */ 731int 732stream_truncate(struct stream *stream, off_t size) 733{ 734 int error; 735 736 if (stream->fd == -1) { 737 errno = EINVAL; 738 return (-1); 739 } 740 error = stream_flush_int(stream, STREAM_FLUSH_NORMAL); 741 if (error) 742 return (-1); 743 error = ftruncate(stream->fd, size); 744 return (error); 745} 746 747/* Like stream_truncate() except the off_t parameter is an offset. */ 748int 749stream_truncate_rel(struct stream *stream, off_t off) 750{ 751 struct stat sb; 752 int error; 753 754 if (stream->buf) { 755 stream_truncate_buf(stream->cookie, off); 756 return (0); 757 } 758 if (stream->fd == -1) { 759 errno = EINVAL; 760 return (-1); 761 } 762 error = stream_flush_int(stream, STREAM_FLUSH_NORMAL); 763 if (error) 764 return (-1); 765 error = fstat(stream->fd, &sb); 766 if (error) 767 return (-1); 768 error = stream_truncate(stream, sb.st_size + off); 769 return (error); 770} 771 772/* Rewind the stream. */ 773int 774stream_rewind(struct stream *stream) 775{ 776 int error; 777 778 if (stream->fd == -1) { 779 errno = EINVAL; 780 return (-1); 781 } 782 if (stream->rdbuf != NULL) 783 buf_less(stream->rdbuf, buf_count(stream->rdbuf)); 784 if (stream->wrbuf != NULL) { 785 error = stream_flush_int(stream, STREAM_FLUSH_NORMAL); 786 if (error) 787 return (error); 788 } 789 error = lseek(stream->fd, 0, SEEK_SET); 790 return (error); 791} 792 793/* Return EOF status. */ 794int 795stream_eof(struct stream *stream) 796{ 797 798 return (stream->eof); 799} 800 801/* Close a stream and free any resources held by it. */ 802int 803stream_close(struct stream *stream) 804{ 805 int error; 806 807 if (stream == NULL) 808 return (0); 809 810 error = 0; 811 if (stream->wrbuf != NULL) 812 error = stream_flush_int(stream, STREAM_FLUSH_CLOSING); 813 stream_filter_fini(stream); 814 if (stream->closefn != NULL) 815 /* 816 * We might overwrite a previous error from stream_flush(), 817 * but we have no choice, because wether it had worked or 818 * not, we need to close the file descriptor. 819 */ 820 error = (*stream->closefn)(stream->cookie); 821 if (stream->rdbuf != NULL) 822 buf_free(stream->rdbuf); 823 if (stream->wrbuf != NULL) 824 buf_free(stream->wrbuf); 825 free(stream); 826 return (error); 827} 828 829/* The default fill method. */ 830static ssize_t 831stream_fill_default(struct stream *stream, struct buf *buf) 832{ 833 ssize_t n; 834 835 if (stream->eof) 836 return (0); 837 assert(buf_avail(buf) > 0); 838 n = (*stream->readfn)(stream->cookie, buf->buf + buf->off + buf->in, 839 buf_avail(buf)); 840 if (n < 0) 841 return (-1); 842 if (n == 0) { 843 stream->eof = 1; 844 return (0); 845 } 846 buf_more(buf, n); 847 return (n); 848} 849 850/* 851 * Refill the read buffer. This function is not permitted to return 852 * without having made more bytes available, unless there was an error. 853 * Moreover, stream_fill() returns the number of bytes added. 854 */ 855static ssize_t 856stream_fill(struct stream *stream) 857{ 858 struct stream_filter *filter; 859 struct buf *buf; 860#ifndef NDEBUG 861 size_t oldcount; 862#endif 863 ssize_t n; 864 865 filter = stream->filter; 866 buf = stream->rdbuf; 867 buf_prewrite(buf); 868#ifndef NDEBUG 869 oldcount = buf_count(buf); 870#endif 871 n = (*filter->fillfn)(stream, buf); 872 assert((n > 0 && n == (signed)(buf_count(buf) - oldcount)) || 873 (n <= 0 && buf_count(buf) == oldcount)); 874 return (n); 875} 876 877/* 878 * Lookup a stream filter. 879 * 880 * We are not supposed to get passed an invalid filter id, since 881 * filter ids are an enum type and we don't have invalid filter 882 * ids in the enum :-). Thus, we are not checking for out of 883 * bounds access here. If it happens, it's the caller's fault 884 * anyway. 885 */ 886static struct stream_filter * 887stream_filter_lookup(stream_filter_t id) 888{ 889 struct stream_filter *filter; 890 891 filter = stream_filters; 892 while (filter->id != id) 893 filter++; 894 return (filter); 895} 896 897static int 898stream_filter_init(struct stream *stream, void *data) 899{ 900 struct stream_filter *filter; 901 int error; 902 903 filter = stream->filter; 904 if (filter->initfn == NULL) 905 return (0); 906 error = (*filter->initfn)(stream, data); 907 return (error); 908} 909 910static void 911stream_filter_fini(struct stream *stream) 912{ 913 struct stream_filter *filter; 914 915 filter = stream->filter; 916 if (filter->finifn != NULL) 917 (*filter->finifn)(stream); 918} 919 920/* 921 * Start a filter on a stream. 922 */ 923int 924stream_filter_start(struct stream *stream, stream_filter_t id, void *data) 925{ 926 struct stream_filter *filter; 927 int error; 928 929 filter = stream->filter; 930 if (id == filter->id) 931 return (0); 932 stream_filter_fini(stream); 933 stream->filter = stream_filter_lookup(id); 934 stream->fdata = NULL; 935 error = stream_filter_init(stream, data); 936 return (error); 937} 938 939 940/* Stop a filter, this is equivalent to setting the null filter. */ 941void 942stream_filter_stop(struct stream *stream) 943{ 944 945 stream_filter_start(stream, STREAM_FILTER_NULL, NULL); 946} 947 948/* The zlib stream filter implementation. */ 949 950/* Take no chances with zlib... */ 951static void * 952zfilter_alloc(void __unused *opaque, unsigned int items, unsigned int size) 953{ 954 955 return (xmalloc(items * size)); 956} 957 958static void 959zfilter_free(void __unused *opaque, void *ptr) 960{ 961 962 free(ptr); 963} 964 965static int 966zfilter_init(struct stream *stream, void __unused *data) 967{ 968 struct zfilter *zf; 969 struct buf *buf; 970 z_stream *state; 971 int rv; 972 973 zf = xmalloc(sizeof(struct zfilter)); 974 memset(zf, 0, sizeof(struct zfilter)); 975 if (stream->rdbuf != NULL) { 976 state = xmalloc(sizeof(z_stream)); 977 state->zalloc = zfilter_alloc; 978 state->zfree = zfilter_free; 979 state->opaque = Z_NULL; 980 rv = inflateInit(state); 981 if (rv != Z_OK) 982 errx(1, "inflateInit: %s", state->msg); 983 buf = buf_new(buf_size(stream->rdbuf)); 984 zf->rdbuf = stream->rdbuf; 985 stream->rdbuf = buf; 986 zf->rdstate = state; 987 } 988 if (stream->wrbuf != NULL) { 989 state = xmalloc(sizeof(z_stream)); 990 state->zalloc = zfilter_alloc; 991 state->zfree = zfilter_free; 992 state->opaque = Z_NULL; 993 rv = deflateInit(state, Z_DEFAULT_COMPRESSION); 994 if (rv != Z_OK) 995 errx(1, "deflateInit: %s", state->msg); 996 buf = buf_new(buf_size(stream->wrbuf)); 997 zf->wrbuf = stream->wrbuf; 998 stream->wrbuf = buf; 999 zf->wrstate = state; 1000 } 1001 stream->fdata = zf; 1002 return (0); 1003} 1004 1005static void 1006zfilter_fini(struct stream *stream) 1007{ 1008 struct zfilter *zf; 1009 struct buf *zbuf; 1010 z_stream *state; 1011 ssize_t n; 1012 1013 zf = stream->fdata; 1014 if (zf->rdbuf != NULL) { 1015 state = zf->rdstate; 1016 zbuf = zf->rdbuf; 1017 /* 1018 * Even if it has produced all the bytes, zlib sometimes 1019 * hasn't seen the EOF marker, so we need to call inflate() 1020 * again to make sure we have eaten all the zlib'ed bytes. 1021 */ 1022 if ((zf->flags & ZFILTER_EOF) == 0) { 1023 n = zfilter_fill(stream, stream->rdbuf); 1024 assert(n == 0 && zf->flags & ZFILTER_EOF); 1025 } 1026 inflateEnd(state); 1027 free(state); 1028 buf_free(stream->rdbuf); 1029 stream->rdbuf = zbuf; 1030 } 1031 if (zf->wrbuf != NULL) { 1032 state = zf->wrstate; 1033 zbuf = zf->wrbuf; 1034 /* 1035 * Compress the remaining bytes in the buffer, if any, 1036 * and emit an EOF marker as appropriate. We ignore 1037 * the error because we can't do anything about it at 1038 * this point, and it can happen if we're getting 1039 * disconnected. 1040 */ 1041 (void)zfilter_flush(stream, stream->wrbuf, 1042 STREAM_FLUSH_CLOSING); 1043 deflateEnd(state); 1044 free(state); 1045 buf_free(stream->wrbuf); 1046 stream->wrbuf = zbuf; 1047 } 1048 free(zf); 1049} 1050 1051static int 1052zfilter_flush(struct stream *stream, struct buf *buf, stream_flush_t how) 1053{ 1054 struct zfilter *zf; 1055 struct buf *zbuf; 1056 z_stream *state; 1057 size_t lastin, lastout, ate, prod; 1058 int done, error, flags, rv; 1059 1060 zf = stream->fdata; 1061 state = zf->wrstate; 1062 zbuf = zf->wrbuf; 1063 1064 if (how == STREAM_FLUSH_NORMAL) 1065 flags = Z_SYNC_FLUSH; 1066 else 1067 flags = Z_FINISH; 1068 1069 done = 0; 1070 rv = Z_OK; 1071 1072again: 1073 /* 1074 * According to zlib.h, we should have at least 6 bytes 1075 * available when using deflate() with Z_SYNC_FLUSH. 1076 */ 1077 if ((buf_avail(zbuf) < 6 && flags == Z_SYNC_FLUSH) || 1078 rv == Z_BUF_ERROR || buf_avail(buf) == 0) { 1079 error = stream_flush_default(stream, zbuf, how); 1080 if (error) 1081 return (error); 1082 } 1083 1084 state->next_in = (Bytef *)(buf->buf + buf->off); 1085 state->avail_in = buf_count(buf); 1086 state->next_out = (Bytef *)(zbuf->buf + zbuf->off + zbuf->in); 1087 state->avail_out = buf_avail(zbuf); 1088 lastin = state->avail_in; 1089 lastout = state->avail_out; 1090 rv = deflate(state, flags); 1091 if (rv != Z_BUF_ERROR && rv != Z_OK && rv != Z_STREAM_END) 1092 errx(1, "deflate: %s", state->msg); 1093 ate = lastin - state->avail_in; 1094 prod = lastout - state->avail_out; 1095 buf_less(buf, ate); 1096 buf_more(zbuf, prod); 1097 if ((flags == Z_SYNC_FLUSH && buf_count(buf) > 0) || 1098 (flags == Z_FINISH && rv != Z_STREAM_END) || 1099 (rv == Z_BUF_ERROR)) 1100 goto again; 1101 1102 assert(rv == Z_OK || (rv == Z_STREAM_END && flags == Z_FINISH)); 1103 error = stream_flush_default(stream, zbuf, how); 1104 return (error); 1105} 1106 1107static ssize_t 1108zfilter_fill(struct stream *stream, struct buf *buf) 1109{ 1110 struct zfilter *zf; 1111 struct buf *zbuf; 1112 z_stream *state; 1113 size_t lastin, lastout, new; 1114 ssize_t n; 1115 int rv; 1116 1117 zf = stream->fdata; 1118 state = zf->rdstate; 1119 zbuf = zf->rdbuf; 1120 1121 assert(buf_avail(buf) > 0); 1122 if (buf_count(zbuf) == 0) { 1123 n = stream_fill_default(stream, zbuf); 1124 if (n <= 0) 1125 return (n); 1126 } 1127again: 1128 assert(buf_count(zbuf) > 0); 1129 state->next_in = (Bytef *)(zbuf->buf + zbuf->off); 1130 state->avail_in = buf_count(zbuf); 1131 state->next_out = (Bytef *)(buf->buf + buf->off + buf->in); 1132 state->avail_out = buf_avail(buf); 1133 lastin = state->avail_in; 1134 lastout = state->avail_out; 1135 rv = inflate(state, Z_SYNC_FLUSH); 1136 buf_less(zbuf, lastin - state->avail_in); 1137 new = lastout - state->avail_out; 1138 if (new == 0 && rv != Z_STREAM_END) { 1139 n = stream_fill_default(stream, zbuf); 1140 if (n == -1) 1141 return (-1); 1142 if (n == 0) 1143 return (0); 1144 goto again; 1145 } 1146 if (rv != Z_STREAM_END && rv != Z_OK) 1147 errx(1, "inflate: %s", state->msg); 1148 if (rv == Z_STREAM_END) 1149 zf->flags |= ZFILTER_EOF; 1150 buf_more(buf, new); 1151 return (new); 1152} 1153 1154/* The MD5 stream filter implementation. */ 1155static int 1156md5filter_init(struct stream *stream, void *data) 1157{ 1158 struct md5filter *mf; 1159 1160 mf = xmalloc(sizeof(struct md5filter)); 1161 MD5_Init(&mf->ctx); 1162 mf->md5 = data; 1163 mf->lastc = ';'; 1164 mf->state = PRINT; 1165 stream->fdata = mf; 1166 return (0); 1167} 1168 1169static void 1170md5filter_fini(struct stream *stream) 1171{ 1172 struct md5filter *mf; 1173 1174 mf = stream->fdata; 1175 MD5_End(mf->md5, &mf->ctx); 1176 free(stream->fdata); 1177} 1178 1179static ssize_t 1180md5filter_fill(struct stream *stream, struct buf *buf) 1181{ 1182 ssize_t n; 1183 1184 assert(buf_avail(buf) > 0); 1185 n = stream_fill_default(stream, buf); 1186 return (n); 1187} 1188 1189static int 1190md5filter_flush(struct stream *stream, struct buf *buf, stream_flush_t how) 1191{ 1192 struct md5filter *mf; 1193 int error; 1194 1195 mf = stream->fdata; 1196 MD5_Update(&mf->ctx, buf->buf + buf->off, buf->in); 1197 error = stream_flush_default(stream, buf, how); 1198 return (error); 1199} 1200 1201/* MD5 flush for RCS, where whitespaces are omitted. */ 1202static int 1203md5rcsfilter_flush(struct stream *stream, struct buf *buf, stream_flush_t how) 1204{ 1205 struct md5filter *mf; 1206 char *ptr, *end; 1207 char *start; 1208 char space[2]; 1209 int error; 1210 1211 mf = stream->fdata; 1212 space[0] = ' '; 1213 space[1] = '\0'; 1214 ptr = buf->buf + buf->off; 1215 end = buf->buf + buf->off + buf->in; 1216 1217#define IS_WS(var) ((var) == ' ' || (var) == '\n' || (var) == '\t' || \ 1218 (var) == '\010' || (var) == '\013' || (var) == '\f' || \ 1219 (var) == '\r') 1220 1221#define IS_SPECIAL(var) ((var) == '$' || (var) == ',' || (var) == ':' || \ 1222 (var) == ';' || (var) == '@') 1223 1224#define IS_PRINT(var) (!IS_WS(var) && (var) != '@') 1225 1226 /* XXX: We can do better than this state machine. */ 1227 while (ptr < end) { 1228 switch (mf->state) { 1229 /* Outside RCS statements. */ 1230 case PRINT: 1231 start = ptr; 1232 while (ptr < end && IS_PRINT(*ptr)) { 1233 mf->lastc = *ptr; 1234 ptr++; 1235 } 1236 MD5_Update(&mf->ctx, start, (ptr - start)); 1237 if (ptr < end) { 1238 if (*ptr == '@') { 1239 MD5_Update(&mf->ctx, ptr, 1); 1240 ptr++; 1241 mf->state = STRING; 1242 } else { 1243 mf->state = WS; 1244 } 1245 } 1246 break; 1247 case WS: 1248 while (ptr < end && IS_WS(*ptr)) { 1249 ptr++; 1250 } 1251 if (ptr < end) { 1252 if (*ptr == '@') { 1253 if (mf->lastc == '@') { 1254 MD5_Update(&mf->ctx, 1255 space, 1); 1256 } 1257 MD5_Update(&mf->ctx, ptr, 1); 1258 ptr++; 1259 mf->state = STRING; 1260 } else { 1261 if (!IS_SPECIAL(*ptr) && 1262 !IS_SPECIAL(mf->lastc)) { 1263 MD5_Update(&mf->ctx, 1264 space, 1); 1265 } 1266 mf->state = PRINT; 1267 } 1268 } 1269 break; 1270 case STRING: 1271 start = ptr; 1272 while (ptr < end && *ptr != '@') { 1273 ptr++; 1274 } 1275 MD5_Update(&mf->ctx, start, (ptr - start)); 1276 if (ptr < end) { 1277 MD5_Update(&mf->ctx, ptr, 1); 1278 ptr++; 1279 mf->state = SEEN; 1280 } 1281 break; 1282 case SEEN: 1283 if (*ptr == '@') { 1284 MD5_Update(&mf->ctx, ptr, 1); 1285 ptr++; 1286 mf->state = STRING; 1287 } else if(IS_WS(*ptr)) { 1288 mf->lastc = '@'; 1289 mf->state = WS; 1290 } else { 1291 mf->state = PRINT; 1292 } 1293 break; 1294 default: 1295 err(1, "Invalid state"); 1296 break; 1297 } 1298 } 1299 1300 error = stream_flush_default(stream, buf, how); 1301 return (error); 1302} 1303 1304