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 */
79 typedef 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
90 struct buf {
91 char *buf;
92 size_t size;
93 size_t in;
94 size_t off;
95 };
96
97 struct 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
111 typedef int stream_filter_initfn_t(struct stream *, void *);
112 typedef void stream_filter_finifn_t(struct stream *);
113 typedef int stream_filter_flushfn_t(struct stream *, struct buf *,
114 stream_flush_t);
115 typedef ssize_t stream_filter_fillfn_t(struct stream *, struct buf *);
116
117 struct 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
130 static void buf_more(struct buf *, size_t);
131 static void buf_less(struct buf *, size_t);
132 static void buf_grow(struct buf *, size_t);
133
134 /* Internal stream functions. */
135 static ssize_t stream_fill(struct stream *);
136 static ssize_t stream_fill_default(struct stream *, struct buf *);
137 static int stream_flush_int(struct stream *, stream_flush_t);
138 static int stream_flush_default(struct stream *, struct buf *,
139 stream_flush_t);
140
141 /* Filters specific functions. */
142 static struct stream_filter *stream_filter_lookup(stream_filter_t);
143 static int stream_filter_init(struct stream *, void *);
144 static void stream_filter_fini(struct stream *);
145
146 /* The zlib stream filter declarations. */
147 #define ZFILTER_EOF 1 /* Got Z_STREAM_END. */
148
149 struct zfilter {
150 int flags;
151 struct buf *rdbuf;
152 struct buf *wrbuf;
153 z_stream *rdstate;
154 z_stream *wrstate;
155 };
156
157 static int zfilter_init(struct stream *, void *);
158 static void zfilter_fini(struct stream *);
159 static ssize_t zfilter_fill(struct stream *, struct buf *);
160 static int zfilter_flush(struct stream *, struct buf *,
161 stream_flush_t);
162
163 /* The MD5 stream filter. */
164 struct 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
175 static int md5filter_init(struct stream *, void *);
176 static void md5filter_fini(struct stream *);
177 static ssize_t md5filter_fill(struct stream *, struct buf *);
178 static int md5filter_flush(struct stream *, struct buf *,
179 stream_flush_t);
180 static int md5rcsfilter_flush(struct stream *, struct buf *,
181 stream_flush_t);
182
183 /* The available stream filters. */
184 struct 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. */
218 struct buf *
buf_new(size_t size)219 buf_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 */
241 static void
buf_grow(struct buf * buf,size_t need)242 buf_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. */
256 static void
buf_prewrite(struct buf * buf)257 buf_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. */
269 static void
buf_more(struct buf * buf,size_t n)270 buf_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. */
278 static void
buf_less(struct buf * buf,size_t n)279 buf_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. */
291 void
buf_free(struct buf * buf)292 buf_free(struct buf *buf)
293 {
294
295 free(buf->buf);
296 free(buf);
297 }
298
299 static struct stream *
stream_new(stream_readfn_t * readfn,stream_writefn_t * writefn,stream_closefn_t * closefn)300 stream_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 *. */
331 struct stream *
stream_open(void * cookie,stream_readfn_t * readfn,stream_writefn_t * writefn,stream_closefn_t * closefn)332 stream_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. */
343 struct stream *
stream_open_fd(int fd,stream_readfn_t * readfn,stream_writefn_t * writefn,stream_closefn_t * closefn)344 stream_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. */
356 struct stream *
stream_open_buf(struct buf * b)357 stream_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 */
372 void
stream_truncate_buf(struct buf * b,off_t off)373 stream_truncate_buf(struct buf *b, off_t off)
374 {
375 b->off += off;
376 }
377
378 /* Like open() but returns a stream. */
379 struct stream *
stream_open_file(const char * path,int flags,...)380 stream_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. */
427 int
stream_fileno(struct stream * stream)428 stream_fileno(struct stream *stream)
429 {
430
431 return (stream->fd);
432 }
433
434 /* Convenience read function for character buffers. */
435 ssize_t
stream_read_buf(void * cookie,void * buf,size_t size)436 stream_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. */
456 ssize_t
stream_append_buf(void * cookie,const void * buf,size_t size)457 stream_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. */
475 int
stream_close_buf(void * cookie)476 stream_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. */
486 ssize_t
stream_read_fd(void * cookie,void * buf,size_t size)487 stream_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. */
498 ssize_t
stream_write_fd(void * cookie,const void * buf,size_t size)499 stream_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. */
510 int
stream_close_fd(void * cookie)511 stream_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. */
521 ssize_t
stream_read(struct stream * stream,void * buf,size_t size)522 stream_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. */
541 ssize_t
stream_read_blocking(struct stream * stream,void * buf,size_t size)542 stream_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 */
580 char *
stream_getln(struct stream * stream,size_t * len)581 stream_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. */
623 ssize_t
stream_write(struct stream * stream,const void * src,size_t nbytes)624 stream_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. */
643 int
stream_printf(struct stream * stream,const char * fmt,...)644 stream_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;
651 again:
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. */
672 int
stream_flush(struct stream * stream)673 stream_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. */
682 static int
stream_flush_int(struct stream * stream,stream_flush_t how)683 stream_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. */
695 static int
stream_flush_default(struct stream * stream,struct buf * buf,stream_flush_t __unused how)696 stream_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. */
714 int
stream_sync(struct stream * stream)715 stream_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. */
731 int
stream_truncate(struct stream * stream,off_t size)732 stream_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. */
748 int
stream_truncate_rel(struct stream * stream,off_t off)749 stream_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. */
773 int
stream_rewind(struct stream * stream)774 stream_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. */
794 int
stream_eof(struct stream * stream)795 stream_eof(struct stream *stream)
796 {
797
798 return (stream->eof);
799 }
800
801 /* Close a stream and free any resources held by it. */
802 int
stream_close(struct stream * stream)803 stream_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. */
830 static ssize_t
stream_fill_default(struct stream * stream,struct buf * buf)831 stream_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 */
855 static ssize_t
stream_fill(struct stream * stream)856 stream_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 */
886 static struct stream_filter *
stream_filter_lookup(stream_filter_t id)887 stream_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
897 static int
stream_filter_init(struct stream * stream,void * data)898 stream_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
910 static void
stream_filter_fini(struct stream * stream)911 stream_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 */
923 int
stream_filter_start(struct stream * stream,stream_filter_t id,void * data)924 stream_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. */
941 void
stream_filter_stop(struct stream * stream)942 stream_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... */
951 static void *
zfilter_alloc(void __unused * opaque,unsigned int items,unsigned int size)952 zfilter_alloc(void __unused *opaque, unsigned int items, unsigned int size)
953 {
954
955 return (xmalloc(items * size));
956 }
957
958 static void
zfilter_free(void __unused * opaque,void * ptr)959 zfilter_free(void __unused *opaque, void *ptr)
960 {
961
962 free(ptr);
963 }
964
965 static int
zfilter_init(struct stream * stream,void __unused * data)966 zfilter_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
1005 static void
zfilter_fini(struct stream * stream)1006 zfilter_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
1051 static int
zfilter_flush(struct stream * stream,struct buf * buf,stream_flush_t how)1052 zfilter_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
1072 again:
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
1107 static ssize_t
zfilter_fill(struct stream * stream,struct buf * buf)1108 zfilter_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 }
1127 again:
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. */
1155 static int
md5filter_init(struct stream * stream,void * data)1156 md5filter_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
1169 static void
md5filter_fini(struct stream * stream)1170 md5filter_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
1179 static ssize_t
md5filter_fill(struct stream * stream,struct buf * buf)1180 md5filter_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
1189 static int
md5filter_flush(struct stream * stream,struct buf * buf,stream_flush_t how)1190 md5filter_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. */
1202 static int
md5rcsfilter_flush(struct stream * stream,struct buf * buf,stream_flush_t how)1203 md5rcsfilter_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