kusano fc6ab3
/* infback.c -- inflate using a call-back interface
kusano fc6ab3
 * Copyright (C) 1995-2011 Mark Adler
kusano fc6ab3
 * For conditions of distribution and use, see copyright notice in zlib.h
kusano fc6ab3
 */
kusano fc6ab3
kusano fc6ab3
/*
kusano fc6ab3
   This code is largely copied from inflate.c.  Normally either infback.o or
kusano fc6ab3
   inflate.o would be linked into an application--not both.  The interface
kusano fc6ab3
   with inffast.c is retained so that optimized assembler-coded versions of
kusano fc6ab3
   inflate_fast() can be used with either inflate.c or infback.c.
kusano fc6ab3
 */
kusano fc6ab3
kusano fc6ab3
#include "zutil.h"
kusano fc6ab3
#include "inftrees.h"
kusano fc6ab3
#include "inflate.h"
kusano fc6ab3
#include "inffast.h"
kusano fc6ab3
kusano fc6ab3
/* function prototypes */
kusano fc6ab3
local void fixedtables OF((struct inflate_state FAR *state));
kusano fc6ab3
kusano fc6ab3
/*
kusano fc6ab3
   strm provides memory allocation functions in zalloc and zfree, or
kusano fc6ab3
   Z_NULL to use the library memory allocation functions.
kusano fc6ab3
kusano fc6ab3
   windowBits is in the range 8..15, and window is a user-supplied
kusano fc6ab3
   window and output buffer that is 2**windowBits bytes.
kusano fc6ab3
 */
kusano fc6ab3
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
kusano fc6ab3
z_streamp strm;
kusano fc6ab3
int windowBits;
kusano fc6ab3
unsigned char FAR *window;
kusano fc6ab3
const char *version;
kusano fc6ab3
int stream_size;
kusano fc6ab3
{
kusano fc6ab3
    struct inflate_state FAR *state;
kusano fc6ab3
kusano fc6ab3
    if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
kusano fc6ab3
        stream_size != (int)(sizeof(z_stream)))
kusano fc6ab3
        return Z_VERSION_ERROR;
kusano fc6ab3
    if (strm == Z_NULL || window == Z_NULL ||
kusano fc6ab3
        windowBits < 8 || windowBits > 15)
kusano fc6ab3
        return Z_STREAM_ERROR;
kusano fc6ab3
    strm->msg = Z_NULL;                 /* in case we return an error */
kusano fc6ab3
    if (strm->zalloc == (alloc_func)0) {
kusano fc6ab3
#ifdef Z_SOLO
kusano fc6ab3
        return Z_STREAM_ERROR;
kusano fc6ab3
#else
kusano fc6ab3
        strm->zalloc = zcalloc;
kusano fc6ab3
        strm->opaque = (voidpf)0;
kusano fc6ab3
#endif
kusano fc6ab3
    }
kusano fc6ab3
    if (strm->zfree == (free_func)0)
kusano fc6ab3
#ifdef Z_SOLO
kusano fc6ab3
        return Z_STREAM_ERROR;
kusano fc6ab3
#else
kusano fc6ab3
    strm->zfree = zcfree;
kusano fc6ab3
#endif
kusano fc6ab3
    state = (struct inflate_state FAR *)ZALLOC(strm, 1,
kusano fc6ab3
                                               sizeof(struct inflate_state));
kusano fc6ab3
    if (state == Z_NULL) return Z_MEM_ERROR;
kusano fc6ab3
    Tracev((stderr, "inflate: allocated\n"));
kusano fc6ab3
    strm->state = (struct internal_state FAR *)state;
kusano fc6ab3
    state->dmax = 32768U;
kusano fc6ab3
    state->wbits = windowBits;
kusano fc6ab3
    state->wsize = 1U << windowBits;
kusano fc6ab3
    state->window = window;
kusano fc6ab3
    state->wnext = 0;
kusano fc6ab3
    state->whave = 0;
kusano fc6ab3
    return Z_OK;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/*
kusano fc6ab3
   Return state with length and distance decoding tables and index sizes set to
kusano fc6ab3
   fixed code decoding.  Normally this returns fixed tables from inffixed.h.
kusano fc6ab3
   If BUILDFIXED is defined, then instead this routine builds the tables the
kusano fc6ab3
   first time it's called, and returns those tables the first time and
kusano fc6ab3
   thereafter.  This reduces the size of the code by about 2K bytes, in
kusano fc6ab3
   exchange for a little execution time.  However, BUILDFIXED should not be
kusano fc6ab3
   used for threaded applications, since the rewriting of the tables and virgin
kusano fc6ab3
   may not be thread-safe.
kusano fc6ab3
 */
kusano fc6ab3
local void fixedtables(state)
kusano fc6ab3
struct inflate_state FAR *state;
kusano fc6ab3
{
kusano fc6ab3
#ifdef BUILDFIXED
kusano fc6ab3
    static int virgin = 1;
kusano fc6ab3
    static code *lenfix, *distfix;
kusano fc6ab3
    static code fixed[544];
kusano fc6ab3
kusano fc6ab3
    /* build fixed huffman tables if first call (may not be thread safe) */
kusano fc6ab3
    if (virgin) {
kusano fc6ab3
        unsigned sym, bits;
kusano fc6ab3
        static code *next;
kusano fc6ab3
kusano fc6ab3
        /* literal/length table */
kusano fc6ab3
        sym = 0;
kusano fc6ab3
        while (sym < 144) state->lens[sym++] = 8;
kusano fc6ab3
        while (sym < 256) state->lens[sym++] = 9;
kusano fc6ab3
        while (sym < 280) state->lens[sym++] = 7;
kusano fc6ab3
        while (sym < 288) state->lens[sym++] = 8;
kusano fc6ab3
        next = fixed;
kusano fc6ab3
        lenfix = next;
kusano fc6ab3
        bits = 9;
kusano fc6ab3
        inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
kusano fc6ab3
kusano fc6ab3
        /* distance table */
kusano fc6ab3
        sym = 0;
kusano fc6ab3
        while (sym < 32) state->lens[sym++] = 5;
kusano fc6ab3
        distfix = next;
kusano fc6ab3
        bits = 5;
kusano fc6ab3
        inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
kusano fc6ab3
kusano fc6ab3
        /* do this just once */
kusano fc6ab3
        virgin = 0;
kusano fc6ab3
    }
kusano fc6ab3
#else /* !BUILDFIXED */
kusano fc6ab3
#   include "inffixed.h"
kusano fc6ab3
#endif /* BUILDFIXED */
kusano fc6ab3
    state->lencode = lenfix;
kusano fc6ab3
    state->lenbits = 9;
kusano fc6ab3
    state->distcode = distfix;
kusano fc6ab3
    state->distbits = 5;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
/* Macros for inflateBack(): */
kusano fc6ab3
kusano fc6ab3
/* Load returned state from inflate_fast() */
kusano fc6ab3
#define LOAD() \
kusano fc6ab3
    do { \
kusano fc6ab3
        put = strm->next_out; \
kusano fc6ab3
        left = strm->avail_out; \
kusano fc6ab3
        next = strm->next_in; \
kusano fc6ab3
        have = strm->avail_in; \
kusano fc6ab3
        hold = state->hold; \
kusano fc6ab3
        bits = state->bits; \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Set state from registers for inflate_fast() */
kusano fc6ab3
#define RESTORE() \
kusano fc6ab3
    do { \
kusano fc6ab3
        strm->next_out = put; \
kusano fc6ab3
        strm->avail_out = left; \
kusano fc6ab3
        strm->next_in = next; \
kusano fc6ab3
        strm->avail_in = have; \
kusano fc6ab3
        state->hold = hold; \
kusano fc6ab3
        state->bits = bits; \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Clear the input bit accumulator */
kusano fc6ab3
#define INITBITS() \
kusano fc6ab3
    do { \
kusano fc6ab3
        hold = 0; \
kusano fc6ab3
        bits = 0; \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Assure that some input is available.  If input is requested, but denied,
kusano fc6ab3
   then return a Z_BUF_ERROR from inflateBack(). */
kusano fc6ab3
#define PULL() \
kusano fc6ab3
    do { \
kusano fc6ab3
        if (have == 0) { \
kusano fc6ab3
            have = in(in_desc, &next); \
kusano fc6ab3
            if (have == 0) { \
kusano fc6ab3
                next = Z_NULL; \
kusano fc6ab3
                ret = Z_BUF_ERROR; \
kusano fc6ab3
                goto inf_leave; \
kusano fc6ab3
            } \
kusano fc6ab3
        } \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Get a byte of input into the bit accumulator, or return from inflateBack()
kusano fc6ab3
   with an error if there is no input available. */
kusano fc6ab3
#define PULLBYTE() \
kusano fc6ab3
    do { \
kusano fc6ab3
        PULL(); \
kusano fc6ab3
        have--; \
kusano fc6ab3
        hold += (unsigned long)(*next++) << bits; \
kusano fc6ab3
        bits += 8; \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Assure that there are at least n bits in the bit accumulator.  If there is
kusano fc6ab3
   not enough available input to do that, then return from inflateBack() with
kusano fc6ab3
   an error. */
kusano fc6ab3
#define NEEDBITS(n) \
kusano fc6ab3
    do { \
kusano fc6ab3
        while (bits < (unsigned)(n)) \
kusano fc6ab3
            PULLBYTE(); \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Return the low n bits of the bit accumulator (n < 16) */
kusano fc6ab3
#define BITS(n) \
kusano fc6ab3
    ((unsigned)hold & ((1U << (n)) - 1))
kusano fc6ab3
kusano fc6ab3
/* Remove n bits from the bit accumulator */
kusano fc6ab3
#define DROPBITS(n) \
kusano fc6ab3
    do { \
kusano fc6ab3
        hold >>= (n); \
kusano fc6ab3
        bits -= (unsigned)(n); \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Remove zero to seven bits as needed to go to a byte boundary */
kusano fc6ab3
#define BYTEBITS() \
kusano fc6ab3
    do { \
kusano fc6ab3
        hold >>= bits & 7; \
kusano fc6ab3
        bits -= bits & 7; \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/* Assure that some output space is available, by writing out the window
kusano fc6ab3
   if it's full.  If the write fails, return from inflateBack() with a
kusano fc6ab3
   Z_BUF_ERROR. */
kusano fc6ab3
#define ROOM() \
kusano fc6ab3
    do { \
kusano fc6ab3
        if (left == 0) { \
kusano fc6ab3
            put = state->window; \
kusano fc6ab3
            left = state->wsize; \
kusano fc6ab3
            state->whave = left; \
kusano fc6ab3
            if (out(out_desc, put, left)) { \
kusano fc6ab3
                ret = Z_BUF_ERROR; \
kusano fc6ab3
                goto inf_leave; \
kusano fc6ab3
            } \
kusano fc6ab3
        } \
kusano fc6ab3
    } while (0)
kusano fc6ab3
kusano fc6ab3
/*
kusano fc6ab3
   strm provides the memory allocation functions and window buffer on input,
kusano fc6ab3
   and provides information on the unused input on return.  For Z_DATA_ERROR
kusano fc6ab3
   returns, strm will also provide an error message.
kusano fc6ab3
kusano fc6ab3
   in() and out() are the call-back input and output functions.  When
kusano fc6ab3
   inflateBack() needs more input, it calls in().  When inflateBack() has
kusano fc6ab3
   filled the window with output, or when it completes with data in the
kusano fc6ab3
   window, it calls out() to write out the data.  The application must not
kusano fc6ab3
   change the provided input until in() is called again or inflateBack()
kusano fc6ab3
   returns.  The application must not change the window/output buffer until
kusano fc6ab3
   inflateBack() returns.
kusano fc6ab3
kusano fc6ab3
   in() and out() are called with a descriptor parameter provided in the
kusano fc6ab3
   inflateBack() call.  This parameter can be a structure that provides the
kusano fc6ab3
   information required to do the read or write, as well as accumulated
kusano fc6ab3
   information on the input and output such as totals and check values.
kusano fc6ab3
kusano fc6ab3
   in() should return zero on failure.  out() should return non-zero on
kusano fc6ab3
   failure.  If either in() or out() fails, than inflateBack() returns a
kusano fc6ab3
   Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
kusano fc6ab3
   was in() or out() that caused in the error.  Otherwise,  inflateBack()
kusano fc6ab3
   returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
kusano fc6ab3
   error, or Z_MEM_ERROR if it could not allocate memory for the state.
kusano fc6ab3
   inflateBack() can also return Z_STREAM_ERROR if the input parameters
kusano fc6ab3
   are not correct, i.e. strm is Z_NULL or the state was not initialized.
kusano fc6ab3
 */
kusano fc6ab3
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
kusano fc6ab3
z_streamp strm;
kusano fc6ab3
in_func in;
kusano fc6ab3
void FAR *in_desc;
kusano fc6ab3
out_func out;
kusano fc6ab3
void FAR *out_desc;
kusano fc6ab3
{
kusano fc6ab3
    struct inflate_state FAR *state;
kusano fc6ab3
    z_const unsigned char FAR *next;    /* next input */
kusano fc6ab3
    unsigned char FAR *put;     /* next output */
kusano fc6ab3
    unsigned have, left;        /* available input and output */
kusano fc6ab3
    unsigned long hold;         /* bit buffer */
kusano fc6ab3
    unsigned bits;              /* bits in bit buffer */
kusano fc6ab3
    unsigned copy;              /* number of stored or match bytes to copy */
kusano fc6ab3
    unsigned char FAR *from;    /* where to copy match bytes from */
kusano fc6ab3
    code here;                  /* current decoding table entry */
kusano fc6ab3
    code last;                  /* parent table entry */
kusano fc6ab3
    unsigned len;               /* length to copy for repeats, bits to drop */
kusano fc6ab3
    int ret;                    /* return code */
kusano fc6ab3
    static const unsigned short order[19] = /* permutation of code lengths */
kusano fc6ab3
        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
kusano fc6ab3
kusano fc6ab3
    /* Check that the strm exists and that the state was initialized */
kusano fc6ab3
    if (strm == Z_NULL || strm->state == Z_NULL)
kusano fc6ab3
        return Z_STREAM_ERROR;
kusano fc6ab3
    state = (struct inflate_state FAR *)strm->state;
kusano fc6ab3
kusano fc6ab3
    /* Reset the state */
kusano fc6ab3
    strm->msg = Z_NULL;
kusano fc6ab3
    state->mode = TYPE;
kusano fc6ab3
    state->last = 0;
kusano fc6ab3
    state->whave = 0;
kusano fc6ab3
    next = strm->next_in;
kusano fc6ab3
    have = next != Z_NULL ? strm->avail_in : 0;
kusano fc6ab3
    hold = 0;
kusano fc6ab3
    bits = 0;
kusano fc6ab3
    put = state->window;
kusano fc6ab3
    left = state->wsize;
kusano fc6ab3
kusano fc6ab3
    /* Inflate until end of block marked as last */
kusano fc6ab3
    for (;;)
kusano fc6ab3
        switch (state->mode) {
kusano fc6ab3
        case TYPE:
kusano fc6ab3
            /* determine and dispatch block type */
kusano fc6ab3
            if (state->last) {
kusano fc6ab3
                BYTEBITS();
kusano fc6ab3
                state->mode = DONE;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            NEEDBITS(3);
kusano fc6ab3
            state->last = BITS(1);
kusano fc6ab3
            DROPBITS(1);
kusano fc6ab3
            switch (BITS(2)) {
kusano fc6ab3
            case 0:                             /* stored block */
kusano fc6ab3
                Tracev((stderr, "inflate:     stored block%s\n",
kusano fc6ab3
                        state->last ? " (last)" : ""));
kusano fc6ab3
                state->mode = STORED;
kusano fc6ab3
                break;
kusano fc6ab3
            case 1:                             /* fixed block */
kusano fc6ab3
                fixedtables(state);
kusano fc6ab3
                Tracev((stderr, "inflate:     fixed codes block%s\n",
kusano fc6ab3
                        state->last ? " (last)" : ""));
kusano fc6ab3
                state->mode = LEN;              /* decode codes */
kusano fc6ab3
                break;
kusano fc6ab3
            case 2:                             /* dynamic block */
kusano fc6ab3
                Tracev((stderr, "inflate:     dynamic codes block%s\n",
kusano fc6ab3
                        state->last ? " (last)" : ""));
kusano fc6ab3
                state->mode = TABLE;
kusano fc6ab3
                break;
kusano fc6ab3
            case 3:
kusano fc6ab3
                strm->msg = (char *)"invalid block type";
kusano fc6ab3
                state->mode = BAD;
kusano fc6ab3
            }
kusano fc6ab3
            DROPBITS(2);
kusano fc6ab3
            break;
kusano fc6ab3
kusano fc6ab3
        case STORED:
kusano fc6ab3
            /* get and verify stored block length */
kusano fc6ab3
            BYTEBITS();                         /* go to byte boundary */
kusano fc6ab3
            NEEDBITS(32);
kusano fc6ab3
            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
kusano fc6ab3
                strm->msg = (char *)"invalid stored block lengths";
kusano fc6ab3
                state->mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            state->length = (unsigned)hold & 0xffff;
kusano fc6ab3
            Tracev((stderr, "inflate:       stored length %u\n",
kusano fc6ab3
                    state->length));
kusano fc6ab3
            INITBITS();
kusano fc6ab3
kusano fc6ab3
            /* copy stored block from input to output */
kusano fc6ab3
            while (state->length != 0) {
kusano fc6ab3
                copy = state->length;
kusano fc6ab3
                PULL();
kusano fc6ab3
                ROOM();
kusano fc6ab3
                if (copy > have) copy = have;
kusano fc6ab3
                if (copy > left) copy = left;
kusano fc6ab3
                zmemcpy(put, next, copy);
kusano fc6ab3
                have -= copy;
kusano fc6ab3
                next += copy;
kusano fc6ab3
                left -= copy;
kusano fc6ab3
                put += copy;
kusano fc6ab3
                state->length -= copy;
kusano fc6ab3
            }
kusano fc6ab3
            Tracev((stderr, "inflate:       stored end\n"));
kusano fc6ab3
            state->mode = TYPE;
kusano fc6ab3
            break;
kusano fc6ab3
kusano fc6ab3
        case TABLE:
kusano fc6ab3
            /* get dynamic table entries descriptor */
kusano fc6ab3
            NEEDBITS(14);
kusano fc6ab3
            state->nlen = BITS(5) + 257;
kusano fc6ab3
            DROPBITS(5);
kusano fc6ab3
            state->ndist = BITS(5) + 1;
kusano fc6ab3
            DROPBITS(5);
kusano fc6ab3
            state->ncode = BITS(4) + 4;
kusano fc6ab3
            DROPBITS(4);
kusano fc6ab3
#ifndef PKZIP_BUG_WORKAROUND
kusano fc6ab3
            if (state->nlen > 286 || state->ndist > 30) {
kusano fc6ab3
                strm->msg = (char *)"too many length or distance symbols";
kusano fc6ab3
                state->mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
#endif
kusano fc6ab3
            Tracev((stderr, "inflate:       table sizes ok\n"));
kusano fc6ab3
kusano fc6ab3
            /* get code length code lengths (not a typo) */
kusano fc6ab3
            state->have = 0;
kusano fc6ab3
            while (state->have < state->ncode) {
kusano fc6ab3
                NEEDBITS(3);
kusano fc6ab3
                state->lens[order[state->have++]] = (unsigned short)BITS(3);
kusano fc6ab3
                DROPBITS(3);
kusano fc6ab3
            }
kusano fc6ab3
            while (state->have < 19)
kusano fc6ab3
                state->lens[order[state->have++]] = 0;
kusano fc6ab3
            state->next = state->codes;
kusano fc6ab3
            state->lencode = (code const FAR *)(state->next);
kusano fc6ab3
            state->lenbits = 7;
kusano fc6ab3
            ret = inflate_table(CODES, state->lens, 19, &(state->next),
kusano fc6ab3
                                &(state->lenbits), state->work);
kusano fc6ab3
            if (ret) {
kusano fc6ab3
                strm->msg = (char *)"invalid code lengths set";
kusano fc6ab3
                state->mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            Tracev((stderr, "inflate:       code lengths ok\n"));
kusano fc6ab3
kusano fc6ab3
            /* get length and distance code code lengths */
kusano fc6ab3
            state->have = 0;
kusano fc6ab3
            while (state->have < state->nlen + state->ndist) {
kusano fc6ab3
                for (;;) {
kusano fc6ab3
                    here = state->lencode[BITS(state->lenbits)];
kusano fc6ab3
                    if ((unsigned)(here.bits) <= bits) break;
kusano fc6ab3
                    PULLBYTE();
kusano fc6ab3
                }
kusano fc6ab3
                if (here.val < 16) {
kusano fc6ab3
                    DROPBITS(here.bits);
kusano fc6ab3
                    state->lens[state->have++] = here.val;
kusano fc6ab3
                }
kusano fc6ab3
                else {
kusano fc6ab3
                    if (here.val == 16) {
kusano fc6ab3
                        NEEDBITS(here.bits + 2);
kusano fc6ab3
                        DROPBITS(here.bits);
kusano fc6ab3
                        if (state->have == 0) {
kusano fc6ab3
                            strm->msg = (char *)"invalid bit length repeat";
kusano fc6ab3
                            state->mode = BAD;
kusano fc6ab3
                            break;
kusano fc6ab3
                        }
kusano fc6ab3
                        len = (unsigned)(state->lens[state->have - 1]);
kusano fc6ab3
                        copy = 3 + BITS(2);
kusano fc6ab3
                        DROPBITS(2);
kusano fc6ab3
                    }
kusano fc6ab3
                    else if (here.val == 17) {
kusano fc6ab3
                        NEEDBITS(here.bits + 3);
kusano fc6ab3
                        DROPBITS(here.bits);
kusano fc6ab3
                        len = 0;
kusano fc6ab3
                        copy = 3 + BITS(3);
kusano fc6ab3
                        DROPBITS(3);
kusano fc6ab3
                    }
kusano fc6ab3
                    else {
kusano fc6ab3
                        NEEDBITS(here.bits + 7);
kusano fc6ab3
                        DROPBITS(here.bits);
kusano fc6ab3
                        len = 0;
kusano fc6ab3
                        copy = 11 + BITS(7);
kusano fc6ab3
                        DROPBITS(7);
kusano fc6ab3
                    }
kusano fc6ab3
                    if (state->have + copy > state->nlen + state->ndist) {
kusano fc6ab3
                        strm->msg = (char *)"invalid bit length repeat";
kusano fc6ab3
                        state->mode = BAD;
kusano fc6ab3
                        break;
kusano fc6ab3
                    }
kusano fc6ab3
                    while (copy--)
kusano fc6ab3
                        state->lens[state->have++] = (unsigned short)len;
kusano fc6ab3
                }
kusano fc6ab3
            }
kusano fc6ab3
kusano fc6ab3
            /* handle error breaks in while */
kusano fc6ab3
            if (state->mode == BAD) break;
kusano fc6ab3
kusano fc6ab3
            /* check for end-of-block code (better have one) */
kusano fc6ab3
            if (state->lens[256] == 0) {
kusano fc6ab3
                strm->msg = (char *)"invalid code -- missing end-of-block";
kusano fc6ab3
                state->mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
kusano fc6ab3
            /* build code tables -- note: do not change the lenbits or distbits
kusano fc6ab3
               values here (9 and 6) without reading the comments in inftrees.h
kusano fc6ab3
               concerning the ENOUGH constants, which depend on those values */
kusano fc6ab3
            state->next = state->codes;
kusano fc6ab3
            state->lencode = (code const FAR *)(state->next);
kusano fc6ab3
            state->lenbits = 9;
kusano fc6ab3
            ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
kusano fc6ab3
                                &(state->lenbits), state->work);
kusano fc6ab3
            if (ret) {
kusano fc6ab3
                strm->msg = (char *)"invalid literal/lengths set";
kusano fc6ab3
                state->mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            state->distcode = (code const FAR *)(state->next);
kusano fc6ab3
            state->distbits = 6;
kusano fc6ab3
            ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
kusano fc6ab3
                            &(state->next), &(state->distbits), state->work);
kusano fc6ab3
            if (ret) {
kusano fc6ab3
                strm->msg = (char *)"invalid distances set";
kusano fc6ab3
                state->mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            Tracev((stderr, "inflate:       codes ok\n"));
kusano fc6ab3
            state->mode = LEN;
kusano fc6ab3
kusano fc6ab3
        case LEN:
kusano fc6ab3
            /* use inflate_fast() if we have enough input and output */
kusano fc6ab3
            if (have >= 6 && left >= 258) {
kusano fc6ab3
                RESTORE();
kusano fc6ab3
                if (state->whave < state->wsize)
kusano fc6ab3
                    state->whave = state->wsize - left;
kusano fc6ab3
                inflate_fast(strm, state->wsize);
kusano fc6ab3
                LOAD();
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
kusano fc6ab3
            /* get a literal, length, or end-of-block code */
kusano fc6ab3
            for (;;) {
kusano fc6ab3
                here = state->lencode[BITS(state->lenbits)];
kusano fc6ab3
                if ((unsigned)(here.bits) <= bits) break;
kusano fc6ab3
                PULLBYTE();
kusano fc6ab3
            }
kusano fc6ab3
            if (here.op && (here.op & 0xf0) == 0) {
kusano fc6ab3
                last = here;
kusano fc6ab3
                for (;;) {
kusano fc6ab3
                    here = state->lencode[last.val +
kusano fc6ab3
                            (BITS(last.bits + last.op) >> last.bits)];
kusano fc6ab3
                    if ((unsigned)(last.bits + here.bits) <= bits) break;
kusano fc6ab3
                    PULLBYTE();
kusano fc6ab3
                }
kusano fc6ab3
                DROPBITS(last.bits);
kusano fc6ab3
            }
kusano fc6ab3
            DROPBITS(here.bits);
kusano fc6ab3
            state->length = (unsigned)here.val;
kusano fc6ab3
kusano fc6ab3
            /* process literal */
kusano fc6ab3
            if (here.op == 0) {
kusano fc6ab3
                Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
kusano fc6ab3
                        "inflate:         literal '%c'\n" :
kusano fc6ab3
                        "inflate:         literal 0x%02x\n", here.val));
kusano fc6ab3
                ROOM();
kusano fc6ab3
                *put++ = (unsigned char)(state->length);
kusano fc6ab3
                left--;
kusano fc6ab3
                state->mode = LEN;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
kusano fc6ab3
            /* process end of block */
kusano fc6ab3
            if (here.op & 32) {
kusano fc6ab3
                Tracevv((stderr, "inflate:         end of block\n"));
kusano fc6ab3
                state->mode = TYPE;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
kusano fc6ab3
            /* invalid code */
kusano fc6ab3
            if (here.op & 64) {
kusano fc6ab3
                strm->msg = (char *)"invalid literal/length code";
kusano fc6ab3
                state->mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
kusano fc6ab3
            /* length code -- get extra bits, if any */
kusano fc6ab3
            state->extra = (unsigned)(here.op) & 15;
kusano fc6ab3
            if (state->extra != 0) {
kusano fc6ab3
                NEEDBITS(state->extra);
kusano fc6ab3
                state->length += BITS(state->extra);
kusano fc6ab3
                DROPBITS(state->extra);
kusano fc6ab3
            }
kusano fc6ab3
            Tracevv((stderr, "inflate:         length %u\n", state->length));
kusano fc6ab3
kusano fc6ab3
            /* get distance code */
kusano fc6ab3
            for (;;) {
kusano fc6ab3
                here = state->distcode[BITS(state->distbits)];
kusano fc6ab3
                if ((unsigned)(here.bits) <= bits) break;
kusano fc6ab3
                PULLBYTE();
kusano fc6ab3
            }
kusano fc6ab3
            if ((here.op & 0xf0) == 0) {
kusano fc6ab3
                last = here;
kusano fc6ab3
                for (;;) {
kusano fc6ab3
                    here = state->distcode[last.val +
kusano fc6ab3
                            (BITS(last.bits + last.op) >> last.bits)];
kusano fc6ab3
                    if ((unsigned)(last.bits + here.bits) <= bits) break;
kusano fc6ab3
                    PULLBYTE();
kusano fc6ab3
                }
kusano fc6ab3
                DROPBITS(last.bits);
kusano fc6ab3
            }
kusano fc6ab3
            DROPBITS(here.bits);
kusano fc6ab3
            if (here.op & 64) {
kusano fc6ab3
                strm->msg = (char *)"invalid distance code";
kusano fc6ab3
                state->mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            state->offset = (unsigned)here.val;
kusano fc6ab3
kusano fc6ab3
            /* get distance extra bits, if any */
kusano fc6ab3
            state->extra = (unsigned)(here.op) & 15;
kusano fc6ab3
            if (state->extra != 0) {
kusano fc6ab3
                NEEDBITS(state->extra);
kusano fc6ab3
                state->offset += BITS(state->extra);
kusano fc6ab3
                DROPBITS(state->extra);
kusano fc6ab3
            }
kusano fc6ab3
            if (state->offset > state->wsize - (state->whave < state->wsize ?
kusano fc6ab3
                                                left : 0)) {
kusano fc6ab3
                strm->msg = (char *)"invalid distance too far back";
kusano fc6ab3
                state->mode = BAD;
kusano fc6ab3
                break;
kusano fc6ab3
            }
kusano fc6ab3
            Tracevv((stderr, "inflate:         distance %u\n", state->offset));
kusano fc6ab3
kusano fc6ab3
            /* copy match from window to output */
kusano fc6ab3
            do {
kusano fc6ab3
                ROOM();
kusano fc6ab3
                copy = state->wsize - state->offset;
kusano fc6ab3
                if (copy < left) {
kusano fc6ab3
                    from = put + copy;
kusano fc6ab3
                    copy = left - copy;
kusano fc6ab3
                }
kusano fc6ab3
                else {
kusano fc6ab3
                    from = put - state->offset;
kusano fc6ab3
                    copy = left;
kusano fc6ab3
                }
kusano fc6ab3
                if (copy > state->length) copy = state->length;
kusano fc6ab3
                state->length -= copy;
kusano fc6ab3
                left -= copy;
kusano fc6ab3
                do {
kusano fc6ab3
                    *put++ = *from++;
kusano fc6ab3
                } while (--copy);
kusano fc6ab3
            } while (state->length != 0);
kusano fc6ab3
            break;
kusano fc6ab3
kusano fc6ab3
        case DONE:
kusano fc6ab3
            /* inflate stream terminated properly -- write leftover output */
kusano fc6ab3
            ret = Z_STREAM_END;
kusano fc6ab3
            if (left < state->wsize) {
kusano fc6ab3
                if (out(out_desc, state->window, state->wsize - left))
kusano fc6ab3
                    ret = Z_BUF_ERROR;
kusano fc6ab3
            }
kusano fc6ab3
            goto inf_leave;
kusano fc6ab3
kusano fc6ab3
        case BAD:
kusano fc6ab3
            ret = Z_DATA_ERROR;
kusano fc6ab3
            goto inf_leave;
kusano fc6ab3
kusano fc6ab3
        default:                /* can't happen, but makes compilers happy */
kusano fc6ab3
            ret = Z_STREAM_ERROR;
kusano fc6ab3
            goto inf_leave;
kusano fc6ab3
        }
kusano fc6ab3
kusano fc6ab3
    /* Return unused input */
kusano fc6ab3
  inf_leave:
kusano fc6ab3
    strm->next_in = next;
kusano fc6ab3
    strm->avail_in = have;
kusano fc6ab3
    return ret;
kusano fc6ab3
}
kusano fc6ab3
kusano fc6ab3
int ZEXPORT inflateBackEnd(strm)
kusano fc6ab3
z_streamp strm;
kusano fc6ab3
{
kusano fc6ab3
    if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
kusano fc6ab3
        return Z_STREAM_ERROR;
kusano fc6ab3
    ZFREE(strm, strm->state);
kusano fc6ab3
    strm->state = Z_NULL;
kusano fc6ab3
    Tracev((stderr, "inflate: end\n"));
kusano fc6ab3
    return Z_OK;
kusano fc6ab3
}