2 * stream.c: svn_stream operations
4 * ====================================================================
5 * Copyright (c) 2000-2004, 2006 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
19 #include "svn_private_config.h"
25 #include <apr_pools.h>
26 #include <apr_strings.h>
27 #include <apr_file_io.h>
28 #include <apr_errno.h>
33 #include "svn_pools.h"
35 #include "svn_error.h"
36 #include "svn_string.h"
42 svn_read_fn_t read_fn
;
43 svn_write_fn_t write_fn
;
44 svn_close_fn_t close_fn
;
49 /*** Generic streams. ***/
52 svn_stream_create(void *baton
, apr_pool_t
*pool
)
56 stream
= apr_palloc(pool
, sizeof(*stream
));
57 stream
->baton
= baton
;
58 stream
->read_fn
= NULL
;
59 stream
->write_fn
= NULL
;
60 stream
->close_fn
= NULL
;
66 svn_stream_set_baton(svn_stream_t
*stream
, void *baton
)
68 stream
->baton
= baton
;
73 svn_stream_set_read(svn_stream_t
*stream
, svn_read_fn_t read_fn
)
75 stream
->read_fn
= read_fn
;
80 svn_stream_set_write(svn_stream_t
*stream
, svn_write_fn_t write_fn
)
82 stream
->write_fn
= write_fn
;
87 svn_stream_set_close(svn_stream_t
*stream
, svn_close_fn_t close_fn
)
89 stream
->close_fn
= close_fn
;
94 svn_stream_read(svn_stream_t
*stream
, char *buffer
, apr_size_t
*len
)
96 assert(stream
->read_fn
!= NULL
);
97 return stream
->read_fn(stream
->baton
, buffer
, len
);
102 svn_stream_write(svn_stream_t
*stream
, const char *data
, apr_size_t
*len
)
104 assert(stream
->write_fn
!= NULL
);
105 return stream
->write_fn(stream
->baton
, data
, len
);
110 svn_stream_close(svn_stream_t
*stream
)
112 if (stream
->close_fn
== NULL
)
114 return stream
->close_fn(stream
->baton
);
119 svn_stream_printf(svn_stream_t
*stream
,
129 message
= apr_pvsprintf(pool
, fmt
, ap
);
132 len
= strlen(message
);
133 return svn_stream_write(stream
, message
, &len
);
138 svn_stream_printf_from_utf8(svn_stream_t
*stream
,
139 const char *encoding
,
144 const char *message
, *translated
;
149 message
= apr_pvsprintf(pool
, fmt
, ap
);
152 SVN_ERR(svn_utf_cstring_from_utf8_ex2(&translated
, message
, encoding
,
155 len
= strlen(translated
);
157 return svn_stream_write(stream
, translated
, &len
);
162 svn_stream_readline(svn_stream_t
*stream
,
163 svn_stringbuf_t
**stringbuf
,
171 /* Since we're reading one character at a time, let's at least
172 optimize for the 90% case. 90% of the time, we can avoid the
173 stringbuf ever having to realloc() itself if we start it out at
175 svn_stringbuf_t
*str
= svn_stringbuf_create_ensure(80, pool
);
181 SVN_ERR(svn_stream_read(stream
, &c
, &numbytes
));
184 /* a 'short' read means the stream has run out. */
195 svn_stringbuf_appendbytes(str
, &c
, 1);
199 svn_stringbuf_chop(str
, match
- eol
);
205 svn_error_t
*svn_stream_copy2(svn_stream_t
*from
, svn_stream_t
*to
,
206 svn_cancel_func_t cancel_func
,
210 char *buf
= apr_palloc(pool
, SVN__STREAM_CHUNK_SIZE
);
213 /* Read and write chunks until we get a short read, indicating the
214 end of the stream. (We can't get a short write without an
215 associated error.) */
218 len
= SVN__STREAM_CHUNK_SIZE
;
221 SVN_ERR(cancel_func(cancel_baton
));
223 SVN_ERR(svn_stream_read(from
, buf
, &len
));
225 SVN_ERR(svn_stream_write(to
, buf
, &len
));
226 if (len
!= SVN__STREAM_CHUNK_SIZE
)
232 svn_error_t
*svn_stream_copy(svn_stream_t
*from
, svn_stream_t
*to
,
235 return svn_stream_copy2(from
, to
, NULL
, NULL
, pool
);
239 svn_stream_contents_same(svn_boolean_t
*same
,
240 svn_stream_t
*stream1
,
241 svn_stream_t
*stream2
,
244 char *buf1
= apr_palloc(pool
, SVN__STREAM_CHUNK_SIZE
);
245 char *buf2
= apr_palloc(pool
, SVN__STREAM_CHUNK_SIZE
);
246 apr_size_t bytes_read1
= SVN__STREAM_CHUNK_SIZE
;
247 apr_size_t bytes_read2
= SVN__STREAM_CHUNK_SIZE
;
249 *same
= TRUE
; /* assume TRUE, until disproved below */
250 while (bytes_read1
== SVN__STREAM_CHUNK_SIZE
251 && bytes_read2
== SVN__STREAM_CHUNK_SIZE
)
253 SVN_ERR(svn_stream_read(stream1
, buf1
, &bytes_read1
));
254 SVN_ERR(svn_stream_read(stream2
, buf2
, &bytes_read2
));
256 if ((bytes_read1
!= bytes_read2
)
257 || (memcmp(buf1
, buf2
, bytes_read1
)))
269 /*** Generic readable empty stream ***/
272 read_handler_empty(void *baton
, char *buffer
, apr_size_t
*len
)
280 write_handler_empty(void *baton
, const char *data
, apr_size_t
*len
)
287 svn_stream_empty(apr_pool_t
*pool
)
289 svn_stream_t
*stream
;
291 stream
= svn_stream_create(NULL
, pool
);
292 svn_stream_set_read(stream
, read_handler_empty
);
293 svn_stream_set_write(stream
, write_handler_empty
);
300 /*** Ownership detaching stream ***/
303 read_handler_disown(void *baton
, char *buffer
, apr_size_t
*len
)
305 return svn_stream_read((svn_stream_t
*)baton
, buffer
, len
);
309 write_handler_disown(void *baton
, const char *buffer
, apr_size_t
*len
)
311 return svn_stream_write((svn_stream_t
*)baton
, buffer
, len
);
316 svn_stream_disown(svn_stream_t
*stream
, apr_pool_t
*pool
)
318 svn_stream_t
*s
= svn_stream_create(stream
, pool
);
320 svn_stream_set_read(s
, read_handler_disown
);
321 svn_stream_set_write(s
, write_handler_disown
);
328 /*** Generic stream for APR files ***/
336 read_handler_apr(void *baton
, char *buffer
, apr_size_t
*len
)
338 struct baton_apr
*btn
= baton
;
341 err
= svn_io_file_read_full(btn
->file
, buffer
, *len
, len
, btn
->pool
);
342 if (err
&& APR_STATUS_IS_EOF(err
->apr_err
))
344 svn_error_clear(err
);
353 write_handler_apr(void *baton
, const char *data
, apr_size_t
*len
)
355 struct baton_apr
*btn
= baton
;
357 return svn_io_file_write_full(btn
->file
, data
, *len
, len
, btn
->pool
);
361 close_handler_apr(void *baton
)
363 struct baton_apr
*btn
= baton
;
365 return svn_io_file_close(btn
->file
, btn
->pool
);
370 svn_stream_from_aprfile2(apr_file_t
*file
,
371 svn_boolean_t disown
,
374 struct baton_apr
*baton
;
375 svn_stream_t
*stream
;
378 return svn_stream_empty(pool
);
380 baton
= apr_palloc(pool
, sizeof(*baton
));
383 stream
= svn_stream_create(baton
, pool
);
384 svn_stream_set_read(stream
, read_handler_apr
);
385 svn_stream_set_write(stream
, write_handler_apr
);
388 svn_stream_set_close(stream
, close_handler_apr
);
394 svn_stream_from_aprfile(apr_file_t
*file
, apr_pool_t
*pool
)
396 return svn_stream_from_aprfile2(file
, TRUE
, pool
);
401 /* Compressed stream support */
403 #define ZBUFFER_SIZE 4096 /* The size of the buffer the
404 compressed stream uses to read from
405 the substream. Basically an
406 arbitrary value, picked to be about
410 z_stream
*in
; /* compressed stream for reading */
411 z_stream
*out
; /* compressed stream for writing */
412 svn_read_fn_t read
; /* substream's read function */
413 svn_write_fn_t write
; /* substream's write function */
414 svn_close_fn_t close
; /* substream's close function */
415 void *read_buffer
; /* buffer used for reading from
417 int read_flush
; /* what flush mode to use while
419 apr_pool_t
*pool
; /* The pool this baton is allocated
421 void *subbaton
; /* The substream's baton */
424 /* zlib alloc function. opaque is the pool we need. */
426 zalloc(voidpf opaque
, uInt items
, uInt size
)
428 apr_pool_t
*pool
= opaque
;
430 return apr_palloc(pool
, items
* size
);
433 /* zlib free function */
435 zfree(voidpf opaque
, voidpf address
)
437 /* Empty, since we allocate on the pool */
440 /* Converts a zlib error to an svn_error_t. zerr is the error code,
441 function is the function name, and stream is the z_stream we are
444 zerr_to_svn_error(int zerr
, const char *function
, z_stream
*stream
)
455 status
= SVN_ERR_STREAM_MALFORMED_DATA
;
456 message
= "stream error";
461 message
= "out of memory";
466 message
= "buffer error";
469 case Z_VERSION_ERROR
:
470 status
= SVN_ERR_STREAM_UNRECOGNIZED_DATA
;
471 message
= "version error";
475 status
= SVN_ERR_STREAM_MALFORMED_DATA
;
476 message
= "corrupted data";
480 status
= SVN_ERR_STREAM_UNRECOGNIZED_DATA
;
485 if (stream
->msg
!= NULL
)
486 return svn_error_createf(status
, NULL
, "zlib (%s): %s: %s", function
,
487 message
, stream
->msg
);
489 return svn_error_createf(status
, NULL
, "zlib (%s): %s", function
,
493 /* Helper function to figure out the sync mode */
495 read_helper_gz(svn_read_fn_t read_fn
,
498 uInt
*len
, int *zflush
)
500 uInt orig_len
= *len
;
502 /* There's no reason this value should grow bigger than the range of
503 uInt, but Subversion's API requires apr_size_t. */
504 apr_size_t apr_len
= (apr_size_t
) *len
;
506 SVN_ERR((*read_fn
)(baton
, buffer
, &apr_len
));
508 /* Type cast back to uInt type that zlib uses. On LP64 platforms
509 apr_size_t will be bigger than uInt. */
510 *len
= (uInt
) apr_len
;
512 /* I wanted to use Z_FINISH here, but we need to know our buffer is
514 *zflush
= (*len
) < orig_len
? Z_SYNC_FLUSH
: Z_SYNC_FLUSH
;
519 /* Handle reading from a compressed stream */
521 read_handler_gz(void *baton
, char *buffer
, apr_size_t
*len
)
523 struct zbaton
*btn
= baton
;
528 btn
->in
= apr_palloc(btn
->pool
, sizeof(z_stream
));
529 btn
->in
->zalloc
= zalloc
;
530 btn
->in
->zfree
= zfree
;
531 btn
->in
->opaque
= btn
->pool
;
532 btn
->read_buffer
= apr_palloc(btn
->pool
, ZBUFFER_SIZE
);
533 btn
->in
->next_in
= btn
->read_buffer
;
534 btn
->in
->avail_in
= ZBUFFER_SIZE
;
536 SVN_ERR(read_helper_gz(btn
->read
, btn
->subbaton
, btn
->read_buffer
,
537 &btn
->in
->avail_in
, &btn
->read_flush
));
539 zerr
= inflateInit(btn
->in
);
540 SVN_ERR(zerr_to_svn_error(zerr
, "inflateInit", btn
->in
));
543 btn
->in
->next_out
= (Bytef
*) buffer
;
544 btn
->in
->avail_out
= *len
;
546 while (btn
->in
->avail_out
> 0)
548 if (btn
->in
->avail_in
<= 0)
550 btn
->in
->avail_in
= ZBUFFER_SIZE
;
551 btn
->in
->next_in
= btn
->read_buffer
;
552 SVN_ERR(read_helper_gz(btn
->read
, btn
->subbaton
, btn
->read_buffer
,
553 &btn
->in
->avail_in
, &btn
->read_flush
));
556 zerr
= inflate(btn
->in
, btn
->read_flush
);
557 if (zerr
== Z_STREAM_END
)
559 else if (zerr
!= Z_OK
)
560 return zerr_to_svn_error(zerr
, "inflate", btn
->in
);
563 *len
-= btn
->in
->avail_out
;
567 /* Compress data and write it to the substream */
569 write_handler_gz(void *baton
, const char *buffer
, apr_size_t
*len
)
571 struct zbaton
*btn
= baton
;
574 apr_size_t buf_size
, write_len
;
577 if (btn
->out
== NULL
)
579 btn
->out
= apr_palloc(btn
->pool
, sizeof(z_stream
));
580 btn
->out
->zalloc
= zalloc
;
581 btn
->out
->zfree
= zfree
;
582 btn
->out
->opaque
= btn
->pool
;
584 zerr
= deflateInit(btn
->out
, Z_DEFAULT_COMPRESSION
);
585 SVN_ERR(zerr_to_svn_error(zerr
, "deflateInit", btn
->out
));
588 /* The largest buffer we should need is 0.1% larger than the
589 compressed data, + 12 bytes. This info comes from zlib.h. */
590 buf_size
= *len
+ (*len
/ 1000) + 13;
591 subpool
= svn_pool_create(btn
->pool
);
592 write_buf
= apr_palloc(subpool
, buf_size
);
594 btn
->out
->next_in
= (Bytef
*) buffer
; /* Casting away const! */
595 btn
->out
->avail_in
= *len
;
597 while (btn
->out
->avail_in
> 0)
599 btn
->out
->next_out
= write_buf
;
600 btn
->out
->avail_out
= buf_size
;
602 zerr
= deflate(btn
->out
, Z_NO_FLUSH
);
603 SVN_ERR(zerr_to_svn_error(zerr
, "deflate", btn
->out
));
604 write_len
= buf_size
- btn
->out
->avail_out
;
606 SVN_ERR(btn
->write(btn
->subbaton
, write_buf
, &write_len
));
609 svn_pool_destroy(subpool
);
614 /* Handle flushing and closing the stream */
616 close_handler_gz(void *baton
)
618 struct zbaton
*btn
= baton
;
623 zerr
= inflateEnd(btn
->in
);
624 SVN_ERR(zerr_to_svn_error(zerr
, "inflateEnd", btn
->in
));
627 if (btn
->out
!= NULL
)
630 apr_size_t write_len
;
632 buf
= apr_palloc(btn
->pool
, ZBUFFER_SIZE
);
636 btn
->out
->next_out
= buf
;
637 btn
->out
->avail_out
= ZBUFFER_SIZE
;
639 zerr
= deflate(btn
->out
, Z_FINISH
);
640 if (zerr
!= Z_STREAM_END
&& zerr
!= Z_OK
)
641 return zerr_to_svn_error(zerr
, "deflate", btn
->out
);
642 write_len
= ZBUFFER_SIZE
- btn
->out
->avail_out
;
644 SVN_ERR(btn
->write(btn
->subbaton
, buf
, &write_len
));
645 if (zerr
== Z_STREAM_END
)
649 zerr
= deflateEnd(btn
->out
);
650 SVN_ERR(zerr_to_svn_error(zerr
, "deflateEnd", btn
->out
));
653 if (btn
->close
!= NULL
)
654 return btn
->close(btn
->subbaton
);
661 svn_stream_compressed(svn_stream_t
*stream
, apr_pool_t
*pool
)
663 struct svn_stream_t
*zstream
;
664 struct zbaton
*baton
;
666 assert(stream
!= NULL
);
668 baton
= apr_palloc(pool
, sizeof(*baton
));
669 baton
->in
= baton
->out
= NULL
;
670 baton
->read
= stream
->read_fn
;
671 baton
->write
= stream
->write_fn
;
672 baton
->close
= stream
->close_fn
;
673 baton
->subbaton
= stream
->baton
;
675 baton
->read_buffer
= NULL
;
676 baton
->read_flush
= Z_SYNC_FLUSH
;
678 zstream
= svn_stream_create(baton
, pool
);
679 svn_stream_set_read(zstream
, read_handler_gz
);
680 svn_stream_set_write(zstream
, write_handler_gz
);
681 svn_stream_set_close(zstream
, close_handler_gz
);
687 /* MD5 checked stream support */
689 struct md5_stream_baton
691 apr_md5_ctx_t read_ctx
, write_ctx
;
692 const unsigned char **read_digest
;
693 const unsigned char **write_digest
;
694 unsigned char read_digest_buf
[APR_MD5_DIGESTSIZE
];
695 unsigned char write_digest_buf
[APR_MD5_DIGESTSIZE
];
698 /* True if more data should be read when closing the stream. */
699 svn_boolean_t read_more
;
701 /* Pool to allocate read buffer from. */
706 read_handler_md5(void *baton
, char *buffer
, apr_size_t
*len
)
708 struct md5_stream_baton
*btn
= baton
;
709 apr_size_t saved_len
= *len
;
711 SVN_ERR(svn_stream_read(btn
->proxy
, buffer
, len
));
713 if (btn
->read_digest
)
715 apr_status_t apr_err
= apr_md5_update(&btn
->read_ctx
, buffer
, *len
);
718 return svn_error_create(apr_err
, NULL
, NULL
);
721 if (saved_len
!= *len
)
722 btn
->read_more
= FALSE
;
729 write_handler_md5(void *baton
, const char *buffer
, apr_size_t
*len
)
731 struct md5_stream_baton
*btn
= baton
;
733 if (btn
->write_digest
&& *len
> 0)
735 apr_status_t apr_err
= apr_md5_update(&btn
->write_ctx
, buffer
, *len
);
738 return svn_error_create(apr_err
, NULL
, NULL
);
741 return svn_stream_write(btn
->proxy
, buffer
, len
);
746 close_handler_md5(void *baton
)
748 struct md5_stream_baton
*btn
= baton
;
750 /* If we're supposed to drain the stream, do so before finalizing the
754 char *buf
= apr_palloc(btn
->pool
, SVN__STREAM_CHUNK_SIZE
);
755 apr_size_t len
= SVN__STREAM_CHUNK_SIZE
;
759 SVN_ERR(read_handler_md5(baton
, buf
, &len
));
761 while (btn
->read_more
);
764 if (btn
->read_digest
)
767 = apr_md5_final(btn
->read_digest_buf
, &btn
->read_ctx
);
770 return svn_error_create(apr_err
, NULL
, NULL
);
772 *btn
->read_digest
= btn
->read_digest_buf
;
775 if (btn
->write_digest
)
778 = apr_md5_final(btn
->write_digest_buf
, &btn
->write_ctx
);
781 return svn_error_create(apr_err
, NULL
, NULL
);
783 *btn
->write_digest
= btn
->write_digest_buf
;
786 return svn_stream_close(btn
->proxy
);
791 svn_stream_checksummed(svn_stream_t
*stream
,
792 const unsigned char **read_digest
,
793 const unsigned char **write_digest
,
794 svn_boolean_t read_all
,
798 struct md5_stream_baton
*baton
;
800 if (! read_digest
&& ! write_digest
)
803 baton
= apr_palloc(pool
, sizeof(*baton
));
804 apr_md5_init(&baton
->read_ctx
);
805 apr_md5_init(&baton
->write_ctx
);
806 baton
->read_digest
= read_digest
;
807 baton
->write_digest
= write_digest
;
808 baton
->proxy
= stream
;
809 baton
->read_more
= read_all
;
812 s
= svn_stream_create(baton
, pool
);
813 svn_stream_set_read(s
, read_handler_md5
);
814 svn_stream_set_write(s
, write_handler_md5
);
815 svn_stream_set_close(s
, close_handler_md5
);
822 /* Miscellaneous stream functions. */
823 struct string_stream_baton
825 svn_stringbuf_t
*str
;
830 read_handler_string(void *baton
, char *buffer
, apr_size_t
*len
)
832 struct string_stream_baton
*btn
= baton
;
833 apr_size_t left_to_read
= btn
->str
->len
- btn
->amt_read
;
835 *len
= (*len
> left_to_read
) ? left_to_read
: *len
;
836 memcpy(buffer
, btn
->str
->data
+ btn
->amt_read
, *len
);
837 btn
->amt_read
+= *len
;
842 write_handler_string(void *baton
, const char *data
, apr_size_t
*len
)
844 struct string_stream_baton
*btn
= baton
;
846 svn_stringbuf_appendbytes(btn
->str
, data
, *len
);
851 svn_stream_from_stringbuf(svn_stringbuf_t
*str
,
854 svn_stream_t
*stream
;
855 struct string_stream_baton
*baton
;
858 return svn_stream_empty(pool
);
860 baton
= apr_palloc(pool
, sizeof(*baton
));
863 stream
= svn_stream_create(baton
, pool
);
864 svn_stream_set_read(stream
, read_handler_string
);
865 svn_stream_set_write(stream
, write_handler_string
);
871 svn_stream_for_stdout(svn_stream_t
**out
, apr_pool_t
*pool
)
873 apr_file_t
*stdout_file
;
874 apr_status_t apr_err
;
876 apr_err
= apr_file_open_stdout(&stdout_file
, pool
);
878 return svn_error_wrap_apr(apr_err
, "Can't open stdout");
880 *out
= svn_stream_from_aprfile(stdout_file
, pool
);