📄 stream.c
字号:
return SVN_NO_ERROR; switch (zerr) { case Z_STREAM_ERROR: status = SVN_ERR_STREAM_MALFORMED_DATA; message = "stream error"; break; case Z_MEM_ERROR: status = APR_ENOMEM; message = "out of memory"; break; case Z_BUF_ERROR: status = APR_ENOMEM; message = "buffer error"; break; case Z_VERSION_ERROR: status = SVN_ERR_STREAM_UNRECOGNIZED_DATA; message = "version error"; break; case Z_DATA_ERROR: status = SVN_ERR_STREAM_MALFORMED_DATA; message = "corrupted data"; break; default: status = SVN_ERR_STREAM_UNRECOGNIZED_DATA; message = "error"; break; } if (stream->msg != NULL) return svn_error_createf(status, NULL, "zlib (%s): %s: %s", function, message, stream->msg); else return svn_error_createf(status, NULL, "zlib (%s): %s", function, message);}/* Helper function to figure out the sync mode */static svn_error_t *read_helper_gz(svn_read_fn_t read_fn, void *baton, char *buffer, uInt *len, int *zflush){ uInt orig_len = *len; /* There's no reason this value should grow bigger than the range of uInt, but Subversion's API requires apr_size_t. */ apr_size_t apr_len = (apr_size_t) *len; SVN_ERR((*read_fn)(baton, buffer, &apr_len)); /* Type cast back to uInt type that zlib uses. On LP64 platforms apr_size_t will be bigger than uInt. */ *len = (uInt) apr_len; /* I wanted to use Z_FINISH here, but we need to know our buffer is big enough */ *zflush = (*len) < orig_len ? Z_SYNC_FLUSH : Z_SYNC_FLUSH; return SVN_NO_ERROR;}/* Handle reading from a compressed stream */static svn_error_t *read_handler_gz(void *baton, char *buffer, apr_size_t *len){ struct zbaton *btn = baton; int zerr; if (btn->in == NULL) { btn->in = apr_palloc(btn->pool, sizeof(z_stream)); btn->in->zalloc = zalloc; btn->in->zfree = zfree; btn->in->opaque = btn->pool; btn->read_buffer = apr_palloc(btn->pool, ZBUFFER_SIZE); btn->in->next_in = btn->read_buffer; btn->in->avail_in = ZBUFFER_SIZE; SVN_ERR(read_helper_gz(btn->read, btn->subbaton, btn->read_buffer, &btn->in->avail_in, &btn->read_flush)); zerr = inflateInit(btn->in); SVN_ERR(zerr_to_svn_error(zerr, "inflateInit", btn->in)); } btn->in->next_out = (Bytef *) buffer; btn->in->avail_out = *len; while (btn->in->avail_out > 0) { if (btn->in->avail_in <= 0) { btn->in->avail_in = ZBUFFER_SIZE; btn->in->next_in = btn->read_buffer; SVN_ERR(read_helper_gz(btn->read, btn->subbaton, btn->read_buffer, &btn->in->avail_in, &btn->read_flush)); } zerr = inflate(btn->in, btn->read_flush); if (zerr == Z_STREAM_END) break; else if (zerr != Z_OK) return zerr_to_svn_error(zerr, "inflate", btn->in); } *len -= btn->in->avail_out; return SVN_NO_ERROR;}/* Compress data and write it to the substream */static svn_error_t *write_handler_gz(void *baton, const char *buffer, apr_size_t *len){ struct zbaton *btn = baton; apr_pool_t *subpool; void *write_buf; apr_size_t buf_size, write_len; int zerr; if (btn->out == NULL) { btn->out = apr_palloc(btn->pool, sizeof(z_stream)); btn->out->zalloc = zalloc; btn->out->zfree = zfree; btn->out->opaque = btn->pool; zerr = deflateInit(btn->out, Z_DEFAULT_COMPRESSION); SVN_ERR(zerr_to_svn_error(zerr, "deflateInit", btn->out)); } /* The largest buffer we should need is 0.1% larger than the compressed data, + 12 bytes. This info comes from zlib.h. */ buf_size = *len + (*len / 1000) + 13; subpool = svn_pool_create(btn->pool); write_buf = apr_palloc(subpool, buf_size); btn->out->next_in = (Bytef *) buffer; /* Casting away const! */ btn->out->avail_in = *len; while (btn->out->avail_in > 0) { btn->out->next_out = write_buf; btn->out->avail_out = buf_size; zerr = deflate(btn->out, Z_NO_FLUSH); SVN_ERR(zerr_to_svn_error(zerr, "deflate", btn->out)); write_len = buf_size - btn->out->avail_out; if (write_len > 0) SVN_ERR(btn->write(btn->subbaton, write_buf, &write_len)); } svn_pool_destroy(subpool); return SVN_NO_ERROR;}/* Handle flushing and closing the stream */static svn_error_t *close_handler_gz(void *baton){ struct zbaton *btn = baton; int zerr; if (btn->in != NULL) { zerr = inflateEnd(btn->in); SVN_ERR(zerr_to_svn_error(zerr, "inflateEnd", btn->in)); } if (btn->out != NULL) { void *buf; apr_size_t write_len; buf = apr_palloc(btn->pool, ZBUFFER_SIZE); while (TRUE) { btn->out->next_out = buf; btn->out->avail_out = ZBUFFER_SIZE; zerr = deflate(btn->out, Z_FINISH); if (zerr != Z_STREAM_END && zerr != Z_OK) return zerr_to_svn_error(zerr, "deflate", btn->out); write_len = ZBUFFER_SIZE - btn->out->avail_out; if (write_len > 0) SVN_ERR(btn->write(btn->subbaton, buf, &write_len)); if (zerr == Z_STREAM_END) break; } zerr = deflateEnd(btn->out); SVN_ERR(zerr_to_svn_error(zerr, "deflateEnd", btn->out)); } if (btn->close != NULL) return btn->close(btn->subbaton); else return SVN_NO_ERROR;}#endif /* SVN_HAVE_ZLIB */svn_stream_t *svn_stream_compressed(svn_stream_t *stream, apr_pool_t *pool){#ifdef SVN_HAVE_ZLIB struct svn_stream_t *zstream; struct zbaton *baton; assert(stream != NULL); baton = apr_palloc(pool, sizeof(*baton)); baton->in = baton->out = NULL; baton->read = stream->read_fn; baton->write = stream->write_fn; baton->close = stream->close_fn; baton->subbaton = stream->baton; baton->pool = pool; baton->read_buffer = NULL; baton->read_flush = Z_SYNC_FLUSH; zstream = svn_stream_create(baton, pool); svn_stream_set_read(zstream, read_handler_gz); svn_stream_set_write(zstream, write_handler_gz); svn_stream_set_close(zstream, close_handler_gz); return zstream;#else return stream;#endif /* SVN_HAVE_ZLIB */}/* MD5 checked stream support */struct md5_stream_baton{ apr_md5_ctx_t read_ctx, write_ctx; const unsigned char **read_digest; const unsigned char **write_digest; unsigned char read_digest_buf[APR_MD5_DIGESTSIZE]; unsigned char write_digest_buf[APR_MD5_DIGESTSIZE]; svn_stream_t *proxy; /* True if more data should be read when closing the stream. */ svn_boolean_t read_more; /* Pool to allocate read buffer from. */ apr_pool_t *pool;};static svn_error_t *read_handler_md5(void *baton, char *buffer, apr_size_t *len){ struct md5_stream_baton *btn = baton; apr_size_t saved_len = *len; SVN_ERR(svn_stream_read(btn->proxy, buffer, len)); if (btn->read_digest) { apr_status_t apr_err = apr_md5_update(&btn->read_ctx, buffer, *len); if (apr_err) return svn_error_create(apr_err, NULL, NULL); } if (saved_len != *len) btn->read_more = FALSE; return SVN_NO_ERROR;}static svn_error_t *write_handler_md5(void *baton, const char *buffer, apr_size_t *len){ struct md5_stream_baton *btn = baton; if (btn->write_digest && *len > 0) { apr_status_t apr_err = apr_md5_update(&btn->write_ctx, buffer, *len); if (apr_err) return svn_error_create(apr_err, NULL, NULL); } return svn_stream_write(btn->proxy, buffer, len);}static svn_error_t *close_handler_md5(void *baton){ struct md5_stream_baton *btn = baton; /* If we're supposed to drain the stream, do so before finalizing the checksum. */ if (btn->read_more) { char *buf = apr_palloc(btn->pool, SVN__STREAM_CHUNK_SIZE); apr_size_t len = SVN__STREAM_CHUNK_SIZE; do { SVN_ERR(read_handler_md5(baton, buf, &len)); } while (btn->read_more); } if (btn->read_digest) { apr_status_t apr_err = apr_md5_final(btn->read_digest_buf, &btn->read_ctx); if (apr_err) return svn_error_create(apr_err, NULL, NULL); *btn->read_digest = btn->read_digest_buf; } if (btn->write_digest) { apr_status_t apr_err = apr_md5_final(btn->write_digest_buf, &btn->write_ctx); if (apr_err) return svn_error_create(apr_err, NULL, NULL); *btn->write_digest = btn->write_digest_buf; } return svn_stream_close(btn->proxy);}svn_stream_t *svn_stream_checksummed(svn_stream_t *stream, const unsigned char **read_digest, const unsigned char **write_digest, svn_boolean_t read_all, apr_pool_t *pool){ svn_stream_t *s; struct md5_stream_baton *baton; if (! read_digest && ! write_digest) return stream; baton = apr_palloc(pool, sizeof(*baton)); apr_md5_init(&baton->read_ctx); apr_md5_init(&baton->write_ctx); baton->read_digest = read_digest; baton->write_digest = write_digest; baton->proxy = stream; baton->read_more = read_all; baton->pool = pool; s = svn_stream_create(baton, pool); svn_stream_set_read(s, read_handler_md5); svn_stream_set_write(s, write_handler_md5); svn_stream_set_close(s, close_handler_md5); return s;}/* Miscellaneous stream functions. */struct string_stream_baton{ svn_stringbuf_t *str; apr_size_t amt_read;};static svn_error_t *read_handler_string(void *baton, char *buffer, apr_size_t *len){ struct string_stream_baton *btn = baton; apr_size_t left_to_read = btn->str->len - btn->amt_read; *len = (*len > left_to_read) ? left_to_read : *len; memcpy(buffer, btn->str->data + btn->amt_read, *len); btn->amt_read += *len; return SVN_NO_ERROR;}static svn_error_t *write_handler_string(void *baton, const char *data, apr_size_t *len){ struct string_stream_baton *btn = baton; svn_stringbuf_appendbytes(btn->str, data, *len); return SVN_NO_ERROR;}svn_stream_t *svn_stream_from_stringbuf(svn_stringbuf_t *str, apr_pool_t *pool){ svn_stream_t *stream; struct string_stream_baton *baton; if (! str) return svn_stream_empty(pool); baton = apr_palloc(pool, sizeof(*baton)); baton->str = str; baton->amt_read = 0; stream = svn_stream_create(baton, pool); svn_stream_set_read(stream, read_handler_string); svn_stream_set_write(stream, write_handler_string); return stream;}svn_error_t *svn_stream_for_stdout(svn_stream_t **out, apr_pool_t *pool){ apr_file_t *stdout_file; apr_status_t apr_err; apr_err = apr_file_open_stdout(&stdout_file, pool); if (apr_err) return svn_error_wrap_apr(apr_err, "Can't open stdout"); *out = svn_stream_from_aprfile(stdout_file, pool); return SVN_NO_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -