istream-zlib.c revision 4334b9b032298defd4d3906f5357698ff016ead0
/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
#include "lib.h"
#ifdef HAVE_ZLIB
#include "crc32.h"
#include "istream-internal.h"
#include "istream-zlib.h"
#include <zlib.h>
#define GZ_HEADER_MIN_SIZE 10
#define GZ_TRAILER_SIZE 8
#define GZ_MAGIC1 0x1f
#define GZ_MAGIC2 0x8b
#define GZ_FLAG_FHCRC 0x02
#define GZ_FLAG_FEXTRA 0x04
#define GZ_FLAG_FNAME 0x08
#define GZ_FLAG_FCOMMENT 0x10
struct zlib_istream {
struct istream_private istream;
unsigned int gz:1;
unsigned int marked:1;
unsigned int header_read:1;
unsigned int trailer_read:1;
unsigned int zs_closed:1;
};
{
}
}
{
const unsigned char *data;
unsigned int pos, fextra_size;
int ret;
if (ret == -1)
return ret;
}
if (size < GZ_HEADER_MIN_SIZE)
return 0;
/* missing gzip magic header */
return -1;
}
return 0;
pos += 2;
return 0;
pos += fextra_size;
}
do {
return 0;
}
do {
return 0;
}
return 0;
pos += 2;
}
return 1;
}
{
}
{
const unsigned char *data;
int ret;
GZ_TRAILER_SIZE-1);
if (ret == -1)
return ret;
}
if (size < GZ_TRAILER_SIZE)
return 0;
return -1;
}
return 1;
}
{
const unsigned char *data;
int ret;
if (!zstream->trailer_read) {
do {
if (ret <= 0)
return ret;
}
return -1;
}
if (!zstream->header_read) {
do {
if (ret <= 0)
return ret;
}
/* try to keep at least CHUNK_SIZE available */
/* don't try to keep anything cached if we don't
have a seek mark. */
}
if (stream->max_buffer_size == 0 ||
/* lose our buffer cache */
}
return -2; /* buffer full */
}
}
/* need to read more data. try to read a full CHUNK_SIZE */
} else {
/* unexpected eof */
}
return -1;
}
if (size == 0) {
/* no more input */
return 0;
}
}
switch (ret) {
case Z_OK:
break;
case Z_NEED_DICT:
case Z_DATA_ERROR:
return -1;
case Z_MEM_ERROR:
case Z_STREAM_END:
if (!zstream->trailer_read) {
/* try to read and verify the trailer, we might not
be called again. */
if (i_stream_zlib_read_trailer(zstream) < 0)
return -1;
}
break;
default:
}
if (size == 0) {
/* read more input */
return i_stream_zlib_read(stream);
}
return size;
}
{
int ret;
switch (ret) {
case Z_OK:
break;
case Z_MEM_ERROR:
case Z_VERSION_ERROR:
i_fatal("Wrong zlib library version (broken compilation)");
case Z_STREAM_ERROR:
i_fatal("zlib: Invalid parameters");
default:
}
}
{
}
static void
{
if (v_offset < start_offset) {
/* have to seek backwards */
start_offset = 0;
}
/* seeking backwards within what's already cached */
} else {
/* read and cache forward */
do {
v_offset -
break;
}
/* some failure, we've broken it */
i_error("zlib_istream.seek() failed: %s",
} else {
/* unexpected EOF. allow it since we may just
want to check if there's anything.. */
}
}
}
if (mark) {
}
}
static const struct stat *
{
return NULL;
return st;
do {
return NULL;
}
}
{
}
{
struct zlib_istream *zstream;
}
{
}
{
}
#endif