Exemple #1
0
static void /* gz_decomp */
zlib_read(FILE_F state, unsigned char *buf, unsigned int count)
{
	int ret = 0;	/* XXX */
	guint32 crc, len;
	z_streamp strm = &(state->strm);

	unsigned char *buf2 = buf;
	unsigned int count2 = count;

	strm->avail_out = count;
	strm->next_out = buf;

	/* fill output buffer up to end of deflate stream or error */
	do {
		/* get more input for inflate() */
		if (state->avail_in == 0 && fill_in_buffer(state) == -1)
			break;
		if (state->avail_in == 0) {
			/* EOF */
			state->err = FTAP_ERR_SHORT_READ;
			state->err_info = NULL;
			break;
		}

		strm->avail_in = state->avail_in;
		strm->next_in = state->next_in;
		/* decompress and handle errors */
#ifdef Z_BLOCK
		ret = inflate(strm, Z_BLOCK);
#else
		ret = inflate(strm, Z_NO_FLUSH);
#endif
		state->avail_in = strm->avail_in;
		state->next_in = strm->next_in;
		if (ret == Z_STREAM_ERROR) {
			state->err = FTAP_ERR_DECOMPRESS;
			state->err_info = strm->msg;
			break;
		}
		if (ret == Z_NEED_DICT) {
			state->err = FTAP_ERR_DECOMPRESS;
			state->err_info = "preset dictionary needed";
			break;
		}
		if (ret == Z_MEM_ERROR) {
			/* This means "not enough memory". */
			state->err = ENOMEM;
			state->err_info = NULL;
			break;
		}
		if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
			state->err = FTAP_ERR_DECOMPRESS;
			state->err_info = strm->msg;
			break;
		}
		/*
		 * XXX - Z_BUF_ERROR?
		 */

		strm->adler = crc32(strm->adler, buf2, count2 - strm->avail_out);
#ifdef Z_BLOCK
		if (state->fast_seek_cur) {
			struct zlib_cur_seek_point *cur = (struct zlib_cur_seek_point *) state->fast_seek_cur;
			unsigned int ready = count2 - strm->avail_out;

			if (ready < ZLIB_WINSIZE) {
				guint left = ZLIB_WINSIZE - cur->pos;

				if (ready >= left) {
					memcpy(cur->window + cur->pos, buf2, left);
					if (ready != left)
						memcpy(cur->window, buf2 + left, ready - left);

					cur->pos = ready - left;
					cur->have += ready;
				} else {
					memcpy(cur->window + cur->pos, buf2, ready);
					cur->pos += ready;
					cur->have += ready;
				}

				if (cur->have >= ZLIB_WINSIZE)
					cur->have = ZLIB_WINSIZE;

			} else {
				memcpy(cur->window, buf2 + (ready - ZLIB_WINSIZE), ZLIB_WINSIZE);
				cur->pos = 0;
				cur->have = ZLIB_WINSIZE;
			}

			if (cur->have >= ZLIB_WINSIZE && ret != Z_STREAM_END && (strm->data_type & 128) && !(strm->data_type & 64))
				zlib_fast_seek_add(state, cur, (strm->data_type & 7), state->raw_pos - strm->avail_in, state->pos + (count - strm->avail_out));
		}
#endif
		buf2 = (buf2 + count2 - strm->avail_out);
		count2 = strm->avail_out;

	} while (strm->avail_out && ret != Z_STREAM_END);

	/* update available output and crc check value */
	state->next = buf;
	state->have = count - strm->avail_out;

	/* Check gzip trailer if at end of deflate stream.
	   We don't fail immediately here, we just set an error
	   indication, so that we try to process what data we
	   got before the error.  The next attempt to read
	   something past that data will get the error. */
	if (ret == Z_STREAM_END) {
		if (gz_next4(state, &crc) != -1 &&
		    gz_next4(state, &len) != -1) {
			if (crc != strm->adler && !state->dont_check_crc) {
				state->err = FTAP_ERR_DECOMPRESS;
				state->err_info = "bad CRC";
			} else if (len != (strm->total_out & 0xffffffffL)) {
				state->err = FTAP_ERR_DECOMPRESS;
				state->err_info = "length field wrong";
			}
		}
		state->compression = UNKNOWN;      /* ready for next stream, once have is 0 */
		g_free(state->fast_seek_cur);
		state->fast_seek_cur = NULL;
	}
}
Exemple #2
0
/* Decompress from input to the provided next_out and avail_out in the state.
   If the end of the compressed data is reached, then verify the gzip trailer
   check value and length (modulo 2^32).  state->have and state->next are set
   to point to the just decompressed data, and the crc is updated.  If the
   trailer is verified, state->how is reset to LOOK to look for the next gzip
   stream or raw data, once state->have is depleted.  Returns 0 on success, -1
   on failure.  Failures may include invalid compressed data or a failed gzip
   trailer verification. */
local int gz_decomp(gz_statep state)
{
    int ret;
    unsigned had;
    unsigned long crc, len;
    z_streamp strm = &(state->strm);

    /* fill output buffer up to end of deflate stream */
    had = strm->avail_out;
    do {
        /* get more input for inflate() */
        if (strm->avail_in == 0 && gz_avail(state) == -1)
            return -1;
        if (strm->avail_in == 0) {
            gz_error(state, Z_DATA_ERROR, "unexpected end of file");
            return -1;
        }

        /* decompress and handle errors */
        ret = inflate(strm, Z_NO_FLUSH);
        if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
            gz_error(state, Z_STREAM_ERROR,
                      "internal error: inflate stream corrupt");
            return -1;
        }
        if (ret == Z_MEM_ERROR) {
            gz_error(state, Z_MEM_ERROR, "out of memory");
            return -1;
        }
        if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
            gz_error(state, Z_DATA_ERROR,
                      strm->msg == NULL ? "compressed data error" : strm->msg);
            return -1;
        }
    } while (strm->avail_out && ret != Z_STREAM_END);

    /* update available output and crc check value */
    state->have = had - strm->avail_out;
    state->next = strm->next_out - state->have;
    strm->adler = crc32(strm->adler, state->next, state->have);

    /* check gzip trailer if at end of deflate stream */
    if (ret == Z_STREAM_END) {
        if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) {
            gz_error(state, Z_DATA_ERROR, "unexpected end of file");
            return -1;
        }
        if (crc != strm->adler) {
            gz_error(state, Z_DATA_ERROR, "incorrect data check");
            return -1;
        }
        if (len != (strm->total_out & 0xffffffffL)) {
            gz_error(state, Z_DATA_ERROR, "incorrect length check");
            return -1;
        }
        state->how = LOOK;      /* ready for next stream, once have is 0 (leave
                                   state->direct unchanged to remember how) */
    }

    /* good decompression */
    return 0;
}