Back to home page

LXR

 
 

    


0001 #ifdef STATIC
0002 #define PREBOOT
0003 /* Pre-boot environment: included */
0004 
0005 /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
0006  * errors about console_printk etc... on ARM */
0007 #define _LINUX_KERNEL_H
0008 
0009 #include "zlib_inflate/inftrees.c"
0010 #include "zlib_inflate/inffast.c"
0011 #include "zlib_inflate/inflate.c"
0012 
0013 #else /* STATIC */
0014 /* initramfs et al: linked */
0015 
0016 #include <linux/zutil.h>
0017 
0018 #include "zlib_inflate/inftrees.h"
0019 #include "zlib_inflate/inffast.h"
0020 #include "zlib_inflate/inflate.h"
0021 
0022 #include "zlib_inflate/infutil.h"
0023 #include <linux/decompress/inflate.h>
0024 
0025 #endif /* STATIC */
0026 
0027 #include <linux/decompress/mm.h>
0028 
0029 #define GZIP_IOBUF_SIZE (16*1024)
0030 
0031 static long INIT nofill(void *buffer, unsigned long len)
0032 {
0033     return -1;
0034 }
0035 
0036 /* Included from initramfs et al code */
0037 STATIC int INIT __gunzip(unsigned char *buf, long len,
0038                long (*fill)(void*, unsigned long),
0039                long (*flush)(void*, unsigned long),
0040                unsigned char *out_buf, long out_len,
0041                long *pos,
0042                void(*error)(char *x)) {
0043     u8 *zbuf;
0044     struct z_stream_s *strm;
0045     int rc;
0046 
0047     rc = -1;
0048     if (flush) {
0049         out_len = 0x8000; /* 32 K */
0050         out_buf = malloc(out_len);
0051     } else {
0052         if (!out_len)
0053             out_len = ((size_t)~0) - (size_t)out_buf; /* no limit */
0054     }
0055     if (!out_buf) {
0056         error("Out of memory while allocating output buffer");
0057         goto gunzip_nomem1;
0058     }
0059 
0060     if (buf)
0061         zbuf = buf;
0062     else {
0063         zbuf = malloc(GZIP_IOBUF_SIZE);
0064         len = 0;
0065     }
0066     if (!zbuf) {
0067         error("Out of memory while allocating input buffer");
0068         goto gunzip_nomem2;
0069     }
0070 
0071     strm = malloc(sizeof(*strm));
0072     if (strm == NULL) {
0073         error("Out of memory while allocating z_stream");
0074         goto gunzip_nomem3;
0075     }
0076 
0077     strm->workspace = malloc(flush ? zlib_inflate_workspacesize() :
0078                  sizeof(struct inflate_state));
0079     if (strm->workspace == NULL) {
0080         error("Out of memory while allocating workspace");
0081         goto gunzip_nomem4;
0082     }
0083 
0084     if (!fill)
0085         fill = nofill;
0086 
0087     if (len == 0)
0088         len = fill(zbuf, GZIP_IOBUF_SIZE);
0089 
0090     /* verify the gzip header */
0091     if (len < 10 ||
0092        zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) {
0093         if (pos)
0094             *pos = 0;
0095         error("Not a gzip file");
0096         goto gunzip_5;
0097     }
0098 
0099     /* skip over gzip header (1f,8b,08... 10 bytes total +
0100      * possible asciz filename)
0101      */
0102     strm->next_in = zbuf + 10;
0103     strm->avail_in = len - 10;
0104     /* skip over asciz filename */
0105     if (zbuf[3] & 0x8) {
0106         do {
0107             /*
0108              * If the filename doesn't fit into the buffer,
0109              * the file is very probably corrupt. Don't try
0110              * to read more data.
0111              */
0112             if (strm->avail_in == 0) {
0113                 error("header error");
0114                 goto gunzip_5;
0115             }
0116             --strm->avail_in;
0117         } while (*strm->next_in++);
0118     }
0119 
0120     strm->next_out = out_buf;
0121     strm->avail_out = out_len;
0122 
0123     rc = zlib_inflateInit2(strm, -MAX_WBITS);
0124 
0125     if (!flush) {
0126         WS(strm)->inflate_state.wsize = 0;
0127         WS(strm)->inflate_state.window = NULL;
0128     }
0129 
0130     while (rc == Z_OK) {
0131         if (strm->avail_in == 0) {
0132             /* TODO: handle case where both pos and fill are set */
0133             len = fill(zbuf, GZIP_IOBUF_SIZE);
0134             if (len < 0) {
0135                 rc = -1;
0136                 error("read error");
0137                 break;
0138             }
0139             strm->next_in = zbuf;
0140             strm->avail_in = len;
0141         }
0142         rc = zlib_inflate(strm, 0);
0143 
0144         /* Write any data generated */
0145         if (flush && strm->next_out > out_buf) {
0146             long l = strm->next_out - out_buf;
0147             if (l != flush(out_buf, l)) {
0148                 rc = -1;
0149                 error("write error");
0150                 break;
0151             }
0152             strm->next_out = out_buf;
0153             strm->avail_out = out_len;
0154         }
0155 
0156         /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
0157         if (rc == Z_STREAM_END) {
0158             rc = 0;
0159             break;
0160         } else if (rc != Z_OK) {
0161             error("uncompression error");
0162             rc = -1;
0163         }
0164     }
0165 
0166     zlib_inflateEnd(strm);
0167     if (pos)
0168         /* add + 8 to skip over trailer */
0169         *pos = strm->next_in - zbuf+8;
0170 
0171 gunzip_5:
0172     free(strm->workspace);
0173 gunzip_nomem4:
0174     free(strm);
0175 gunzip_nomem3:
0176     if (!buf)
0177         free(zbuf);
0178 gunzip_nomem2:
0179     if (flush)
0180         free(out_buf);
0181 gunzip_nomem1:
0182     return rc; /* returns Z_OK (0) if successful */
0183 }
0184 
0185 #ifndef PREBOOT
0186 STATIC int INIT gunzip(unsigned char *buf, long len,
0187                long (*fill)(void*, unsigned long),
0188                long (*flush)(void*, unsigned long),
0189                unsigned char *out_buf,
0190                long *pos,
0191                void (*error)(char *x))
0192 {
0193     return __gunzip(buf, len, fill, flush, out_buf, 0, pos, error);
0194 }
0195 #else
0196 STATIC int INIT __decompress(unsigned char *buf, long len,
0197                long (*fill)(void*, unsigned long),
0198                long (*flush)(void*, unsigned long),
0199                unsigned char *out_buf, long out_len,
0200                long *pos,
0201                void (*error)(char *x))
0202 {
0203     return __gunzip(buf, len, fill, flush, out_buf, out_len, pos, error);
0204 }
0205 #endif