Author: brane Date: Sun May 18 11:36:06 2025 New Revision: 1925664 URL: http://svn.apache.org/viewvc?rev=1925664&view=rev Log: When wrapping streams, set only those handlers on the wrapper that are supported by the source stream, otherwise the svn_stream_supports_*() predicates do not work as expected. And for consistency, expose the "stream supports seek" predicate explicitly in the streams API instead of hiding it behind "supports reset".
* subversion/include/svn_io.h (svn_stream_supports_seek): New function. * subversion/libsvn_subr/stream.c (svn_stream_supports_seek): Implemented here. (svn_stream_supports_reset): This is now just a wrapper for the above. (svn_stream_disown): Add the partial read, mark and seek handlers only if the original wrapped stream supports them. (svn_stream_checksummed2): Likewise. * subversion/libsvn_subr/subst.c (stream_translated): Use separate checks to decide when to add the mark and seek stream handlers. * subversion/libsvn_client/blame.c (file_rev_handler): Let's just agree to not disown NULL streams, shall we? We have a perfectly good empty stream that can be disowned without dereferencing a null pointer. Modified: subversion/trunk/subversion/include/svn_io.h subversion/trunk/subversion/libsvn_client/blame.c subversion/trunk/subversion/libsvn_subr/stream.c subversion/trunk/subversion/libsvn_subr/subst.c Modified: subversion/trunk/subversion/include/svn_io.h URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_io.h?rev=1925664&r1=1925663&r2=1925664&view=diff ============================================================================== --- subversion/trunk/subversion/include/svn_io.h (original) +++ subversion/trunk/subversion/include/svn_io.h Sun May 18 11:36:06 2025 @@ -1385,6 +1385,14 @@ svn_stream_reset(svn_stream_t *stream); svn_boolean_t svn_stream_supports_mark(svn_stream_t *stream); +/** Returns @c TRUE if the generic @a stream supports svn_stream_seek(). + * + * @see svn_stream_seek() + * @since New in 1.15. + */ +svn_boolean_t +svn_stream_supports_seek(svn_stream_t *stream); + /** Returns @c TRUE if the generic @a stream supports svn_stream_reset(). * * @see svn_stream_reset() Modified: subversion/trunk/subversion/libsvn_client/blame.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/blame.c?rev=1925664&r1=1925663&r2=1925664&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_client/blame.c (original) +++ subversion/trunk/subversion/libsvn_client/blame.c Sun May 18 11:36:06 2025 @@ -499,8 +499,7 @@ file_rev_handler(void *baton, const char SVN_ERR(svn_stream_open_readonly(&delta_baton->source_stream, frb->last_filename, frb->currpool, pool)); else - /* Means empty stream below. */ - delta_baton->source_stream = NULL; + delta_baton->source_stream = svn_stream_empty(pool); last_stream = svn_stream_disown(delta_baton->source_stream, pool); if (frb->include_merged_revisions && !merged_revision) Modified: subversion/trunk/subversion/libsvn_subr/stream.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/stream.c?rev=1925664&r1=1925663&r2=1925664&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_subr/stream.c (original) +++ subversion/trunk/subversion/libsvn_subr/stream.c Sun May 18 11:36:06 2025 @@ -236,11 +236,17 @@ svn_stream_supports_mark(svn_stream_t *s } svn_boolean_t -svn_stream_supports_reset(svn_stream_t *stream) +svn_stream_supports_seek(svn_stream_t *stream) { return stream->seek_fn != NULL; } +svn_boolean_t +svn_stream_supports_reset(svn_stream_t *stream) +{ + return svn_stream_supports_seek(stream); +} + svn_error_t * svn_stream_mark(svn_stream_t *stream, svn_stream_mark_t **mark, apr_pool_t *pool) @@ -658,12 +664,16 @@ svn_stream_t * svn_stream_disown(svn_stream_t *stream, apr_pool_t *pool) { svn_stream_t *s = svn_stream_create(stream, pool); + const svn_read_fn_t read_handler = + svn_stream_supports_partial_read(stream) ? read_handler_disown : NULL; - svn_stream_set_read2(s, read_handler_disown, read_full_handler_disown); + svn_stream_set_read2(s, read_handler, read_full_handler_disown); svn_stream_set_skip(s, skip_handler_disown); svn_stream_set_write(s, write_handler_disown); - svn_stream_set_mark(s, mark_handler_disown); - svn_stream_set_seek(s, seek_handler_disown); + if (svn_stream_supports_mark(stream)) + svn_stream_set_mark(s, mark_handler_disown); + if (svn_stream_supports_seek(stream)) + svn_stream_set_seek(s, seek_handler_disown); svn_stream_set_data_available(s, data_available_disown); svn_stream_set_readline(s, readline_handler_disown); @@ -1490,6 +1500,8 @@ svn_stream_checksummed2(svn_stream_t *st { svn_stream_t *s; struct checksum_stream_baton *baton; + const svn_read_fn_t read_handler = + svn_stream_supports_partial_read(stream) ? read_handler_checksum : NULL; if (read_checksum == NULL && write_checksum == NULL) return stream; @@ -1512,7 +1524,7 @@ svn_stream_checksummed2(svn_stream_t *st baton->pool = pool; s = svn_stream_create(baton, pool); - svn_stream_set_read2(s, read_handler_checksum, read_full_handler_checksum); + svn_stream_set_read2(s, read_handler, read_full_handler_checksum); svn_stream_set_write(s, write_handler_checksum); svn_stream_set_data_available(s, data_available_handler_checksum); svn_stream_set_close(s, close_handler_checksum); Modified: subversion/trunk/subversion/libsvn_subr/subst.c URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/subst.c?rev=1925664&r1=1925663&r2=1925664&view=diff ============================================================================== --- subversion/trunk/subversion/libsvn_subr/subst.c (original) +++ subversion/trunk/subversion/libsvn_subr/subst.c Sun May 18 11:36:06 2025 @@ -1542,10 +1542,9 @@ stream_translated(svn_stream_t *stream, svn_stream_set_write(s, translated_stream_write); svn_stream_set_close(s, translated_stream_close); if (svn_stream_supports_mark(stream)) - { - svn_stream_set_mark(s, translated_stream_mark); - svn_stream_set_seek(s, translated_stream_seek); - } + svn_stream_set_mark(s, translated_stream_mark); + if (svn_stream_supports_seek(stream)) + svn_stream_set_seek(s, translated_stream_seek); return s; }