istream-zlib.c revision 9511a40d933181045343110c8101b75887062aae
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2005-2007 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "istream-internal.h"
dfa2201c6ac8ddb2d2798dee15662cfe774e644eMartti Rannanjärvi#include "istream-zlib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen#include <zlib.h>
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen/* Default maximum buffer size. Seeking backwards is very expensive, so keep
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen this pretty large */
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen#define DEFAULT_MAX_BUFFER_SIZE (1024*1024)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainenstruct zlib_istream {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen struct istream_private istream;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen int fd;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen gzFile *file;
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen uoff_t cached_size;
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen uoff_t seek_offset;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen unsigned int marked:1;
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen};
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void i_stream_zlib_close(struct iostream_private *stream)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen struct zlib_istream *zstream = (struct zlib_istream *)stream;
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (zstream->file != NULL) {
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen gzclose(zstream->file);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen zstream->file = NULL;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen }
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen}
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainenstatic void i_stream_zlib_destroy(struct iostream_private *stream ATTR_UNUSED)
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen{
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen struct istream_private *_stream = (struct istream_private *)stream;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen i_free(_stream->w_buffer);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen}
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainenstatic ssize_t i_stream_zlib_read(struct istream_private *stream)
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen{
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen struct zlib_istream *zstream = (struct zlib_istream *)stream;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen size_t size;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen int ret;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (stream->istream.closed)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return -1;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen stream->istream.stream_errno = 0;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (stream->pos == stream->buffer_size) {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (!zstream->marked && stream->skip > 0) {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen /* don't try to keep anything cached if we don't
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen have a seek mark. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_stream_compress(stream);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (stream->max_buffer_size == 0 ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen stream->buffer_size < stream->max_buffer_size) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* buffer is full - grow it */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (stream->pos == stream->buffer_size) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (stream->skip > 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* lose our buffer cache */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_stream_compress(stream);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (stream->pos == stream->buffer_size)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return -2; /* buffer full */
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen }
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen }
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen size = stream->buffer_size - stream->pos;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ret = -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_assert(zstream->seek_offset == stream->istream.v_offset +
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (stream->pos - stream->skip));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen do {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ret = gzread(zstream->file, stream->w_buffer + stream->pos,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen size);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } while (ret < 0 && errno == EINTR && stream->istream.blocking);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (ret == 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* EOF */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen stream->istream.eof = TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (ret < 0) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (errno == EAGAIN) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen i_assert(!stream->istream.blocking);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen ret = 0;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen } else {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen stream->istream.eof = TRUE;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen stream->istream.stream_errno = errno;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return -1;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen zstream->seek_offset += ret;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen stream->pos += ret;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(ret != 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return ret;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen}
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipeki_stream_zlib_seek(struct istream_private *stream, uoff_t v_offset, bool mark)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct zlib_istream *zstream = (struct zlib_istream *) stream;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen uoff_t start_offset = stream->istream.v_offset - stream->skip;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen stream->istream.stream_errno = 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (v_offset < start_offset) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* have to seek backwards */
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek gzseek(zstream->file, v_offset, SEEK_SET);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen zstream->seek_offset = v_offset;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen stream->skip = stream->pos = 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen stream->istream.v_offset = v_offset;
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek } else if (v_offset <= start_offset + stream->pos) {
63e207529879438e9f4412d97cdc34bdc82a3702Timo Sirainen /* seeking backwards within what's already cached */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen stream->skip = v_offset - start_offset;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen stream->istream.v_offset = v_offset;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen } else {
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek /* read and cache forward */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen do {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen size_t avail = stream->pos - stream->skip;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (stream->istream.v_offset + avail >= v_offset) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen i_stream_skip(&stream->istream,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen v_offset -
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen stream->istream.v_offset);
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek break;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen i_stream_skip(&stream->istream, avail);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen } while (i_stream_zlib_read(stream) >= 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (stream->istream.v_offset != v_offset) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* some failure, we've broken it */
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen if (stream->istream.stream_errno != 0) {
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen i_error("zlib_istream.seek() failed: %s",
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen strerror(stream->istream.stream_errno));
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen i_stream_close(&stream->istream);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen } else {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* unexpected EOF. allow it since we may just
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen want to check if there's anything.. */
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen i_assert(stream->istream.eof);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen }
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen }
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen }
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (mark) {
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen i_stream_compress(stream);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen zstream->marked = TRUE;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen }
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen}
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic const struct stat *
2615df45a8027948a474abe5e817b34b0499c171Timo Siraineni_stream_zlib_stat(struct istream_private *stream, bool exact)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct zlib_istream *zstream = (struct zlib_istream *) stream;
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen size_t size;
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen if (fstat(zstream->fd, &stream->statbuf) < 0) {
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen i_error("zlib_istream.fstat() failed: %m");
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen return NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (!exact)
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen return &stream->statbuf;
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen if (zstream->cached_size == (uoff_t)-1) {
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen uoff_t old_offset = stream->istream.v_offset;
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen do {
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen (void)i_stream_get_data(&stream->istream, &size);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_stream_skip(&stream->istream, size);
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen } while (i_stream_zlib_read(stream) > 0);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen zstream->cached_size = stream->istream.v_offset;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_stream_seek(&stream->istream, old_offset);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen stream->statbuf.st_size = zstream->cached_size;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return &stream->statbuf;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
f0d09be40bd0c4423873128ae2f88a4020075dc4Timo Sirainenstatic void i_stream_zlib_sync(struct istream_private *stream)
f0d09be40bd0c4423873128ae2f88a4020075dc4Timo Sirainen{
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen struct zlib_istream *zstream = (struct zlib_istream *) stream;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen zstream->cached_size = (uoff_t)-1;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen}
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainenstruct istream *i_stream_create_zlib(int fd)
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen{
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen struct zlib_istream *zstream;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen struct stat st;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen zstream = i_new(struct zlib_istream, 1);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk zstream->fd = fd;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk zstream->file = gzdopen(fd, "r");
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk zstream->cached_size = (uoff_t)-1;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk zstream->istream.iostream.close = i_stream_zlib_close;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk zstream->istream.iostream.destroy = i_stream_zlib_destroy;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen zstream->istream.max_buffer_size = DEFAULT_MAX_BUFFER_SIZE;
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen zstream->istream.read = i_stream_zlib_read;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen zstream->istream.seek = i_stream_zlib_seek;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen zstream->istream.stat = i_stream_zlib_stat;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen zstream->istream.sync = i_stream_zlib_sync;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen /* if it's a file, set the flags properly */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) {
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen zstream->istream.istream.blocking = TRUE;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen zstream->istream.istream.seekable = TRUE;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen }
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return i_stream_create(&zstream->istream, NULL, fd);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen