2
* stream.c: svn_stream operations
4
* ====================================================================
5
* Copyright (c) 2000-2004 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>
34
#include "svn_pools.h"
36
#include "svn_error.h"
37
#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_readline (svn_stream_t *stream,
139
svn_stringbuf_t **stringbuf,
147
svn_stringbuf_t *str = svn_stringbuf_create ("", pool);
149
/* Since we're reading one character at a time, let's at least
150
optimize for the 90% case. 90% of the time, we can avoid the
151
stringbuf ever having to realloc() itself if we start it out at
153
svn_stringbuf_ensure (str, 80);
159
SVN_ERR (svn_stream_read (stream, &c, &numbytes));
162
/* a 'short' read means the stream has run out. */
173
svn_stringbuf_appendbytes (str, &c, 1);
177
svn_stringbuf_chop (str, match - eol);
183
svn_error_t *svn_stream_copy (svn_stream_t *from, svn_stream_t *to,
186
char *buf = apr_palloc (pool, SVN_STREAM_CHUNK_SIZE);
189
/* Read and write chunks until we get a short read, indicating the
190
end of the stream. (We can't get a short write without an
191
associated error.) */
194
len = SVN_STREAM_CHUNK_SIZE;
195
SVN_ERR (svn_stream_read (from, buf, &len));
197
SVN_ERR (svn_stream_write (to, buf, &len));
198
if (len != SVN_STREAM_CHUNK_SIZE)
207
/*** Generic readable empty stream ***/
210
read_handler_empty (void *baton, char *buffer, apr_size_t *len)
218
write_handler_empty (void *baton, const char *data, apr_size_t *len)
225
svn_stream_empty (apr_pool_t *pool)
227
svn_stream_t *stream;
229
stream = svn_stream_create (NULL, pool);
230
svn_stream_set_read (stream, read_handler_empty);
231
svn_stream_set_write (stream, write_handler_empty);
237
/*** Generic stream for APR files ***/
245
read_handler_apr (void *baton, char *buffer, apr_size_t *len)
247
struct baton_apr *btn = baton;
250
err = svn_io_file_read_full (btn->file, buffer, *len, len, btn->pool);
251
if (err && APR_STATUS_IS_EOF(err->apr_err))
253
svn_error_clear (err);
262
write_handler_apr (void *baton, const char *data, apr_size_t *len)
264
struct baton_apr *btn = baton;
266
return svn_io_file_write_full (btn->file, data, *len, len, btn->pool);
271
svn_stream_from_aprfile (apr_file_t *file, apr_pool_t *pool)
273
struct baton_apr *baton;
274
svn_stream_t *stream;
277
return svn_stream_empty(pool);
278
baton = apr_palloc (pool, sizeof (*baton));
281
stream = svn_stream_create (baton, pool);
282
svn_stream_set_read (stream, read_handler_apr);
283
svn_stream_set_write (stream, write_handler_apr);
288
/* Compressed stream support */
292
#define ZBUFFER_SIZE 4096 /* The size of the buffer the
293
compressed stream uses to read from
294
the substream. Basically an
295
arbitrary value, picked to be about
299
z_stream *in; /* compressed stream for reading */
300
z_stream *out; /* compressed stream for writing */
301
svn_read_fn_t read; /* substream's read function */
302
svn_write_fn_t write; /* substream's write function */
303
svn_close_fn_t close; /* substream's close function */
304
void *read_buffer; /* buffer used for reading from
306
int read_flush; /* what flush mode to use while
308
apr_pool_t *pool; /* The pool this baton is allocated
310
void *subbaton; /* The substream's baton */
313
/* zlib alloc function. opaque is the pool we need. */
315
zalloc(voidpf opaque, uInt items, uInt size)
317
apr_pool_t *pool = opaque;
319
return apr_palloc(pool, items * size);
322
/* zlib free function */
324
zfree(voidpf opaque, voidpf address)
326
/* Empty, since we allocate on the pool */
329
/* Converts a zlib error to an svn_error_t. zerr is the error code,
330
function is the function name, and stream is the z_stream we are
333
zerr_to_svn_error (int zerr, const char *function, z_stream *stream)
344
status = SVN_ERR_STREAM_MALFORMED_DATA;
345
message = "stream error";
350
message = "out of memory";
355
message = "buffer error";
358
case Z_VERSION_ERROR:
359
status = SVN_ERR_STREAM_UNRECOGNIZED_DATA;
360
message = "version error";
364
status = SVN_ERR_STREAM_MALFORMED_DATA;
365
message = "corrupted data";
369
status = SVN_ERR_STREAM_UNRECOGNIZED_DATA;
374
if (stream->msg != NULL)
375
return svn_error_createf (status, NULL, "zlib (%s): %s: %s", function,
376
message, stream->msg);
378
return svn_error_createf (status, NULL, "zlib (%s): %s", function,
382
/* Helper function to figure out the sync mode */
384
read_helper_gz (svn_read_fn_t read_fn,
387
uInt *len, int *zflush)
389
uInt orig_len = *len;
391
/* There's no reason this value should grow bigger than the range of
392
uInt, but Subversion's API requires apr_size_t. */
393
apr_size_t apr_len = (apr_size_t) *len;
395
SVN_ERR ((*read_fn) (baton, buffer, &apr_len));
397
/* Type cast back to uInt type that zlib uses. On LP64 platforms
398
apr_size_t will be bigger than uInt. */
399
*len = (uInt) apr_len;
401
/* I wanted to use Z_FINISH here, but we need to know our buffer is
403
*zflush = (*len) < orig_len ? Z_SYNC_FLUSH : Z_SYNC_FLUSH;
408
/* Handle reading from a compressed stream */
410
read_handler_gz (void *baton, char *buffer, apr_size_t *len)
412
struct zbaton *btn = baton;
417
btn->in = apr_palloc (btn->pool, sizeof (z_stream));
418
btn->in->zalloc = zalloc;
419
btn->in->zfree = zfree;
420
btn->in->opaque = btn->pool;
421
btn->read_buffer = apr_palloc(btn->pool, ZBUFFER_SIZE);
422
btn->in->next_in = btn->read_buffer;
423
btn->in->avail_in = ZBUFFER_SIZE;
425
SVN_ERR (read_helper_gz (btn->read, btn->subbaton, btn->read_buffer,
426
&btn->in->avail_in, &btn->read_flush));
428
zerr = inflateInit (btn->in);
429
SVN_ERR (zerr_to_svn_error (zerr, "inflateInit", btn->in));
432
btn->in->next_out = (Bytef *) buffer;
433
btn->in->avail_out = *len;
435
while (btn->in->avail_out > 0)
437
if (btn->in->avail_in <= 0)
439
btn->in->avail_in = ZBUFFER_SIZE;
440
btn->in->next_in = btn->read_buffer;
441
SVN_ERR (read_helper_gz (btn->read, btn->subbaton, btn->read_buffer,
442
&btn->in->avail_in, &btn->read_flush));
445
zerr = inflate (btn->in, btn->read_flush);
446
if (zerr == Z_STREAM_END)
448
else if (zerr != Z_OK)
449
return zerr_to_svn_error(zerr, "inflate", btn->in);
452
*len -= btn->in->avail_out;
456
/* Compress data and write it to the substream */
458
write_handler_gz (void *baton, const char *buffer, apr_size_t *len)
460
struct zbaton *btn = baton;
463
apr_size_t buf_size, write_len;
466
if (btn->out == NULL)
468
btn->out = apr_palloc (btn->pool, sizeof (z_stream));
469
btn->out->zalloc = zalloc;
470
btn->out->zfree = zfree;
471
btn->out->opaque = btn->pool;
473
zerr = deflateInit (btn->out, Z_DEFAULT_COMPRESSION);
474
SVN_ERR (zerr_to_svn_error (zerr, "deflateInit", btn->out));
477
/* The largest buffer we should need is 0.1% larger than the
478
compressed data, + 12 bytes. This info comes from zlib.h. */
479
buf_size = *len + (*len / 1000) + 13;
480
subpool = svn_pool_create (btn->pool);
481
write_buf = apr_palloc (subpool, buf_size);
483
btn->out->next_in = (Bytef *) buffer; /* Casting away const! */
484
btn->out->avail_in = *len;
486
while (btn->out->avail_in > 0)
488
btn->out->next_out = write_buf;
489
btn->out->avail_out = buf_size;
491
zerr = deflate (btn->out, Z_NO_FLUSH);
492
SVN_ERR (zerr_to_svn_error (zerr, "deflate", btn->out));
493
write_len = buf_size - btn->out->avail_out;
495
SVN_ERR (btn->write (btn->subbaton, write_buf, &write_len));
498
svn_pool_destroy (subpool);
503
/* Handle flushing and closing the stream */
505
close_handler_gz (void *baton)
507
struct zbaton *btn = baton;
512
zerr = inflateEnd(btn->in);
513
SVN_ERR (zerr_to_svn_error (zerr, "inflateEnd", btn->in));
516
if (btn->out != NULL)
519
apr_size_t write_len;
521
buf = apr_palloc (btn->pool, ZBUFFER_SIZE);
525
btn->out->next_out = buf;
526
btn->out->avail_out = ZBUFFER_SIZE;
528
zerr = deflate (btn->out, Z_FINISH);
529
if (zerr != Z_STREAM_END && zerr != Z_OK)
530
return zerr_to_svn_error (zerr, "deflate", btn->out);
531
write_len = ZBUFFER_SIZE - btn->out->avail_out;
533
SVN_ERR (btn->write (btn->subbaton, buf, &write_len));
534
if (zerr == Z_STREAM_END)
538
zerr = deflateEnd(btn->out);
539
SVN_ERR (zerr_to_svn_error (zerr, "deflateEnd", btn->out));
542
if (btn->close != NULL)
543
return btn->close (btn->subbaton);
548
#endif /* SVN_HAVE_ZLIB */
551
svn_stream_compressed (svn_stream_t *stream, apr_pool_t *pool)
555
struct svn_stream_t *zstream;
556
struct zbaton *baton;
558
assert(stream != NULL);
560
baton = apr_palloc (pool, sizeof (*baton));
561
baton->in = baton->out = NULL;
562
baton->read = stream->read_fn;
563
baton->write = stream->write_fn;
564
baton->close = stream->close_fn;
565
baton->subbaton = stream->baton;
567
baton->read_buffer = NULL;
568
baton->read_flush = Z_SYNC_FLUSH;
570
zstream = svn_stream_create(baton, pool);
571
svn_stream_set_read(zstream, read_handler_gz);
572
svn_stream_set_write(zstream, write_handler_gz);
573
svn_stream_set_close(zstream, close_handler_gz);
581
#endif /* SVN_HAVE_ZLIB */
585
/* Miscellaneous stream functions. */
586
struct string_stream_baton
588
svn_stringbuf_t *str;
593
read_handler_string (void *baton, char *buffer, apr_size_t *len)
595
struct string_stream_baton *btn = baton;
596
apr_size_t left_to_read = btn->str->len - btn->amt_read;
598
*len = (*len > left_to_read) ? left_to_read : *len;
599
memcpy (buffer, btn->str->data + btn->amt_read, *len);
600
btn->amt_read += *len;
605
write_handler_string (void *baton, const char *data, apr_size_t *len)
607
struct string_stream_baton *btn = baton;
609
svn_stringbuf_appendbytes (btn->str, data, *len);
614
svn_stream_from_stringbuf (svn_stringbuf_t *str,
617
svn_stream_t *stream;
618
struct string_stream_baton *baton;
621
return svn_stream_empty (pool);
623
baton = apr_palloc (pool, sizeof (*baton));
626
stream = svn_stream_create (baton, pool);
627
svn_stream_set_read (stream, read_handler_string);
628
svn_stream_set_write (stream, write_handler_string);
634
svn_stream_for_stdout (svn_stream_t **out, apr_pool_t *pool)
636
apr_file_t *stdout_file;
637
apr_status_t apr_err;
639
apr_err = apr_file_open_stdout (&stdout_file, pool);
641
return svn_error_wrap_apr (apr_err, "Can't open stdout");
643
*out = svn_stream_from_aprfile (stdout_file, pool);