2009-01-05 00:46:16 +03:00
# ifdef STATIC
/* Pre-boot environment: included */
/* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
* errors about console_printk etc . . . on ARM */
# define _LINUX_KERNEL_H
# include "zlib_inflate/inftrees.c"
# include "zlib_inflate/inffast.c"
# include "zlib_inflate/inflate.c"
# else /* STATIC */
/* initramfs et al: linked */
# include <linux/zutil.h>
# include "zlib_inflate/inftrees.h"
# include "zlib_inflate/inffast.h"
# include "zlib_inflate/inflate.h"
# include "zlib_inflate/infutil.h"
# endif /* STATIC */
# include <linux/decompress/mm.h>
2009-08-07 02:09:30 +04:00
# define GZIP_IOBUF_SIZE (16*1024)
2009-01-05 00:46:16 +03:00
2011-01-13 04:01:13 +03:00
static int INIT nofill ( void * buffer , unsigned int len )
2009-09-24 02:57:37 +04:00
{
return - 1 ;
}
2009-01-05 00:46:16 +03:00
/* Included from initramfs et al code */
STATIC int INIT gunzip ( unsigned char * buf , int len ,
int ( * fill ) ( void * , unsigned int ) ,
int ( * flush ) ( void * , unsigned int ) ,
unsigned char * out_buf ,
int * pos ,
2011-01-13 04:01:14 +03:00
void ( * error ) ( char * x ) ) {
2009-01-05 00:46:16 +03:00
u8 * zbuf ;
struct z_stream_s * strm ;
int rc ;
size_t out_len ;
rc = - 1 ;
if ( flush ) {
2009-01-09 02:09:12 +03:00
out_len = 0x8000 ; /* 32 K */
2009-01-05 00:46:16 +03:00
out_buf = malloc ( out_len ) ;
} else {
out_len = 0x7fffffff ; /* no limit */
}
if ( ! out_buf ) {
error ( " Out of memory while allocating output buffer " ) ;
goto gunzip_nomem1 ;
}
if ( buf )
zbuf = buf ;
else {
2009-08-07 02:09:30 +04:00
zbuf = malloc ( GZIP_IOBUF_SIZE ) ;
2009-01-05 00:46:16 +03:00
len = 0 ;
}
if ( ! zbuf ) {
error ( " Out of memory while allocating input buffer " ) ;
goto gunzip_nomem2 ;
}
strm = malloc ( sizeof ( * strm ) ) ;
if ( strm = = NULL ) {
error ( " Out of memory while allocating z_stream " ) ;
goto gunzip_nomem3 ;
}
strm - > workspace = malloc ( flush ? zlib_inflate_workspacesize ( ) :
sizeof ( struct inflate_state ) ) ;
if ( strm - > workspace = = NULL ) {
error ( " Out of memory while allocating workspace " ) ;
goto gunzip_nomem4 ;
}
2009-09-24 02:57:37 +04:00
if ( ! fill )
fill = nofill ;
2009-01-05 00:46:16 +03:00
if ( len = = 0 )
2009-08-07 02:09:30 +04:00
len = fill ( zbuf , GZIP_IOBUF_SIZE ) ;
2009-01-05 00:46:16 +03:00
/* 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 ;
2011-01-13 04:01:25 +03:00
strm - > avail_in = len - 10 ;
2009-01-05 00:46:16 +03:00
/* skip over asciz filename */
if ( zbuf [ 3 ] & 0x8 ) {
2011-01-13 04:01:25 +03:00
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 + + ) ;
2009-01-05 00:46:16 +03:00
}
strm - > next_out = out_buf ;
strm - > avail_out = out_len ;
rc = zlib_inflateInit2 ( strm , - MAX_WBITS ) ;
if ( ! flush ) {
WS ( strm ) - > inflate_state . wsize = 0 ;
WS ( strm ) - > inflate_state . window = NULL ;
}
while ( rc = = Z_OK ) {
if ( strm - > avail_in = = 0 ) {
/* TODO: handle case where both pos and fill are set */
2009-08-07 02:09:30 +04:00
len = fill ( zbuf , GZIP_IOBUF_SIZE ) ;
2009-01-05 00:46:16 +03:00
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 ) {
int 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 ;
} else if ( 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 ;
gunzip_5 :
free ( strm - > workspace ) ;
gunzip_nomem4 :
free ( strm ) ;
gunzip_nomem3 :
if ( ! buf )
free ( zbuf ) ;
gunzip_nomem2 :
if ( flush )
free ( out_buf ) ;
gunzip_nomem1 :
return rc ; /* returns Z_OK (0) if successful */
}
# define decompress gunzip