/* * When an architecture needs to share the malloc()/free() implementation * between compilation units, it needs to have non-local visibility. */ #ifndef MALLOC_VISIBLE #define MALLOC_VISIBLE static #endif
/* A trivial malloc implementation, adapted from * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 */ STATIC_RW_DATA unsignedlong malloc_ptr; STATIC_RW_DATA int malloc_count;
MALLOC_VISIBLE void *malloc(int size) { void *p;
if (size < 0) returnNULL; if (!malloc_ptr) malloc_ptr = free_mem_ptr;
malloc_ptr = (malloc_ptr + 7) & ~7; /* Align */
p = (void *)malloc_ptr; malloc_ptr += size;
if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr) returnNULL;
/* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # define MAX_MEM_LEVEL 8 #endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif
intzlib_inflate(z_streamp strm, int flush) { structinflate_state *state; constunsignedchar *next; /* next input */ unsignedchar *put; /* next output */ unsigned have, left; /* available input and output */ unsignedlong hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned in, out; /* save starting available input and output */ unsigned copy; /* number of stored or match bytes to copy */ unsignedchar *from; /* where to copy match bytes from */ code this; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ staticconstunsignedshort order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
/* Do not check for strm->next_out == NULL here as ppc zImage inflates to strm->next_out = 0 */
/** * buf: 需要解压的buf * flush:则out_len限制为0x8000(32K),使用malloc分配 * out_len: 为0则无限制 */ staticint INIT __gunzip(unsignedchar *buf, long len, long (*fill)(void*, unsignedlong), long (*flush)(void*, unsignedlong), unsignedchar *out_buf, long out_len, long *pos, void(*error)(char *x)) { u8 *zbuf; structz_stream_s *strm; int rc;
rc = -1;
/* verify the gzip header */ if (len < 10 || zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) { if (pos) *pos = 0; error("Not a gzip file"); goto gunzip_5; }
/* skip over gzip header (1f,8b,08... 10 bytes total + * possible asciz filename) */ strm->next_in = zbuf + 10; strm->avail_in = len - 10; /* skip over asciz filename */ if (zbuf[3] & 0x8) { do { /* * If the filename doesn't fit into the buffer, * the file is very probably corrupt. Don't try * to read more data. */ if (strm->avail_in == 0) { error("header error"); goto gunzip_5; } --strm->avail_in; } while (*strm->next_in++); }
#ifdef CONFIG_ZLIB_DFLTCC /* Always keep the window for DFLTCC */ #else if (!flush) { WS(strm)->inflate_state.wsize = 0; WS(strm)->inflate_state.window = NULL; } #endif
while (rc == Z_OK) { if (strm->avail_in == 0) { /* TODO: handle case where both pos and fill are set */ len = fill(zbuf, GZIP_IOBUF_SIZE); if (len < 0) { rc = -1; error("read error"); break; } strm->next_in = zbuf; strm->avail_in = len; } rc = zlib_inflate(strm, 0); //按照滑动窗口的大小进行解压缩
/* Write any data generated */ if (flush && strm->next_out > out_buf) { long l = strm->next_out - out_buf; if (l != flush(out_buf, l)) { rc = -1; error("write error"); break; } strm->next_out = out_buf; strm->avail_out = out_len; }
/* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */ if (rc == Z_STREAM_END) { rc = 0; break; } elseif (rc != Z_OK) { error("uncompression error"); rc = -1; } }
zlib_inflateEnd(strm); if (pos) /* add + 8 to skip over trailer */ *pos = strm->next_in - zbuf+8;