static svn_error_t * close_handler_checksum(void *baton) { struct checksum_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_checksum(baton, buf, &len)); } while (btn->read_more); } if (btn->read_ctx) SVN_ERR(svn_checksum_final(btn->read_checksum, btn->read_ctx, btn->pool)); if (btn->write_ctx) SVN_ERR(svn_checksum_final(btn->write_checksum, btn->write_ctx, btn->pool)); return svn_error_trace(svn_stream_close(btn->proxy)); }
svn_error_t *svn_txdelta_send_stream(svn_stream_t *stream, svn_txdelta_window_handler_t handler, void *handler_baton, unsigned char *digest, apr_pool_t *pool) { svn_txdelta_window_t delta_window = { 0 }; svn_txdelta_op_t delta_op; svn_string_t window_data; char read_buf[SVN__STREAM_CHUNK_SIZE + 1]; svn_checksum_ctx_t *md5_checksum_ctx; if (digest) md5_checksum_ctx = svn_checksum_ctx_create(svn_checksum_md5, pool); while (1) { apr_size_t read_len = SVN__STREAM_CHUNK_SIZE; SVN_ERR(svn_stream_read_full(stream, read_buf, &read_len)); if (read_len == 0) break; window_data.data = read_buf; window_data.len = read_len; delta_op.action_code = svn_txdelta_new; delta_op.offset = 0; delta_op.length = read_len; delta_window.tview_len = read_len; delta_window.num_ops = 1; delta_window.ops = &delta_op; delta_window.new_data = &window_data; SVN_ERR(handler(&delta_window, handler_baton)); if (digest) SVN_ERR(svn_checksum_update(md5_checksum_ctx, read_buf, read_len)); if (read_len < SVN__STREAM_CHUNK_SIZE) break; } SVN_ERR(handler(NULL, handler_baton)); if (digest) { svn_checksum_t *md5_checksum; SVN_ERR(svn_checksum_final(&md5_checksum, md5_checksum_ctx, pool)); memcpy(digest, md5_checksum->digest, APR_MD5_DIGESTSIZE); } return SVN_NO_ERROR; }
static svn_error_t * txdelta_next_window(svn_txdelta_window_t **window, void *baton, apr_pool_t *pool) { struct txdelta_baton *b = baton; apr_size_t source_len = SVN_DELTA_WINDOW_SIZE; apr_size_t target_len = SVN_DELTA_WINDOW_SIZE; /* Read the source stream. */ if (b->more_source) { SVN_ERR(svn_stream_read(b->source, b->buf, &source_len)); b->more_source = (source_len == SVN_DELTA_WINDOW_SIZE); } else source_len = 0; /* Read the target stream. */ SVN_ERR(svn_stream_read(b->target, b->buf + source_len, &target_len)); b->pos += source_len; if (target_len == 0) { /* No target data? We're done; return the final window. */ if (b->context != NULL) SVN_ERR(svn_checksum_final(&b->checksum, b->context, b->result_pool)); *window = NULL; b->more = FALSE; return SVN_NO_ERROR; } else if (b->context != NULL) SVN_ERR(svn_checksum_update(b->context, b->buf + source_len, target_len)); *window = compute_window(b->buf, source_len, target_len, b->pos - source_len, pool); /* That's it. */ return SVN_NO_ERROR; }