]> dgit.raspbian.org Git - dovecot.git/commitdiff
[PATCH 3/5] lib-compression: Add o_stream_deflate_reset_dict()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 16 Apr 2026 15:38:41 +0000 (17:38 +0200)
committerNoah Meyerhans <noahm@debian.org>
Wed, 16 Sep 2026 19:06:35 +0000 (15:06 -0400)
New public function that locates the deflate ostream in the parent chain
(transparently handles rawlog wrappers) and schedules a Z_FULL_FLUSH on
the next uncork/flush.  Z_FULL_FLUSH emits all buffered data and then
resets the deflate dictionary, so subsequent compressed output cannot
reference data from before the call.

Adds a pending_dict_reset flag to struct zlib_ostream.  The flag persists
through partial flush retries and is cleared only once the full flush
loop completes.

Gbp-Pq: Name 0003-lib-compression-Add-o_stream_deflate_reset_dict.patch

src/lib-compression/ostream-zlib.c
src/lib-compression/ostream-zlib.h

index 6aeccbf35dca58343c64c0cd7268d8a52d6dfc88..5bc41d0b2c2dee4acdeda0f15bb8899cb3eaeb2f 100644 (file)
@@ -23,6 +23,7 @@ struct zlib_ostream {
 
        bool gz:1;
        bool flushed:1;
+       bool pending_dict_reset:1;
 };
 
 struct zlib_settings {
@@ -252,8 +253,14 @@ o_stream_zlib_send_flush(struct zlib_ostream *zstream, bool final)
        if ((ret = o_stream_zlib_send_outbuf(zstream)) <= 0)
                return ret;
 
-       flush = final ? Z_FINISH :
-               (!zstream->gz ? Z_SYNC_FLUSH : Z_NO_FLUSH);
+       if (final)
+               flush = Z_FINISH;
+       else if (zstream->gz)
+               flush = Z_NO_FLUSH;
+       else if (zstream->pending_dict_reset)
+               flush = Z_FULL_FLUSH;
+       else
+               flush = Z_SYNC_FLUSH;
 
        i_assert(zstream->outbuf_used == 0);
        do {
@@ -283,6 +290,10 @@ o_stream_zlib_send_flush(struct zlib_ostream *zstream, bool final)
                }
        } while (zs->avail_out != sizeof(zstream->outbuf));
 
+       /* Z_FULL_FLUSH completes here; clear the request so subsequent flushes
+          use the normal Z_SYNC_FLUSH again. */
+       zstream->pending_dict_reset = FALSE;
+
        if (final) {
                if (o_stream_zlib_send_gz_trailer(zstream) < 0)
                        return -1;
@@ -443,3 +454,25 @@ struct ostream *o_stream_create_deflate_auto(struct ostream *output, struct even
 {
        return o_stream_create_zlib_auto(output, event, FALSE);
 }
+void o_stream_deflate_reset_dict(struct ostream *_output)
+{
+       struct ostream_private *stream = _output->real_stream;
+
+       /* Traverse the ostream parent chain to find the deflate ostream.
+          The caller may pass a rawlog-wrapped stream or the deflate stream
+          itself; either way we find it by its sendv function pointer. */
+       while (stream != NULL) {
+               if (stream->sendv == o_stream_zlib_sendv) {
+                       struct zlib_ostream *zstream =
+                               container_of(stream, struct zlib_ostream, ostream);
+                       i_assert(!zstream->gz);
+                       zstream->pending_dict_reset = TRUE;
+                       o_stream_set_flush_pending(
+                               &zstream->ostream.ostream, TRUE);
+                       return;
+               }
+               stream = (stream->parent != NULL) ?
+                       stream->parent->real_stream : NULL;
+       }
+       /* No deflate ostream found in the chain – nothing to reset. */
+}
index 9738e36cc0e7872810293657889e4baa628e9414..4db62fda81ee2364031950a7772dea5697469481 100644 (file)
@@ -7,4 +7,11 @@ struct ostream *o_stream_create_bz2_auto(struct ostream *output, struct event *e
 struct ostream *o_stream_create_lz4_auto(struct ostream *output, struct event *event);
 struct ostream *o_stream_create_zstd_auto(struct ostream *output, struct event *event);
 
+/* Reset the deflate compression dictionary so that subsequent compressed
+   output cannot reference data from before this call.  Pass any ostream in
+   the chain (e.g. a rawlog wrapper); the function locates the deflate stream
+   internally.  Safe to call when compression is not active – it is a no-op
+   in that case. */
+void o_stream_deflate_reset_dict(struct ostream *output);
+
 #endif