The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/lib/decompress_inflate.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #ifdef STATIC
    2 /* Pre-boot environment: included */
    3 
    4 /* prevent inclusion of _LINUX_KERNEL_H in pre-boot environment: lots
    5  * errors about console_printk etc... on ARM */
    6 #define _LINUX_KERNEL_H
    7 
    8 #include "zlib_inflate/inftrees.c"
    9 #include "zlib_inflate/inffast.c"
   10 #include "zlib_inflate/inflate.c"
   11 
   12 #else /* STATIC */
   13 /* initramfs et al: linked */
   14 
   15 #include <linux/zutil.h>
   16 
   17 #include "zlib_inflate/inftrees.h"
   18 #include "zlib_inflate/inffast.h"
   19 #include "zlib_inflate/inflate.h"
   20 
   21 #include "zlib_inflate/infutil.h"
   22 
   23 #endif /* STATIC */
   24 
   25 #include <linux/decompress/mm.h>
   26 
   27 #define GZIP_IOBUF_SIZE (16*1024)
   28 
   29 static int INIT nofill(void *buffer, unsigned int len)
   30 {
   31         return -1;
   32 }
   33 
   34 /* Included from initramfs et al code */
   35 STATIC int INIT gunzip(unsigned char *buf, int len,
   36                        int(*fill)(void*, unsigned int),
   37                        int(*flush)(void*, unsigned int),
   38                        unsigned char *out_buf,
   39                        int *pos,
   40                        void(*error)(char *x)) {
   41         u8 *zbuf;
   42         struct z_stream_s *strm;
   43         int rc;
   44         size_t out_len;
   45 
   46         rc = -1;
   47         if (flush) {
   48                 out_len = 0x8000; /* 32 K */
   49                 out_buf = malloc(out_len);
   50         } else {
   51                 out_len = 0x7fffffff; /* no limit */
   52         }
   53         if (!out_buf) {
   54                 error("Out of memory while allocating output buffer");
   55                 goto gunzip_nomem1;
   56         }
   57 
   58         if (buf)
   59                 zbuf = buf;
   60         else {
   61                 zbuf = malloc(GZIP_IOBUF_SIZE);
   62                 len = 0;
   63         }
   64         if (!zbuf) {
   65                 error("Out of memory while allocating input buffer");
   66                 goto gunzip_nomem2;
   67         }
   68 
   69         strm = malloc(sizeof(*strm));
   70         if (strm == NULL) {
   71                 error("Out of memory while allocating z_stream");
   72                 goto gunzip_nomem3;
   73         }
   74 
   75         strm->workspace = malloc(flush ? zlib_inflate_workspacesize() :
   76                                  sizeof(struct inflate_state));
   77         if (strm->workspace == NULL) {
   78                 error("Out of memory while allocating workspace");
   79                 goto gunzip_nomem4;
   80         }
   81 
   82         if (!fill)
   83                 fill = nofill;
   84 
   85         if (len == 0)
   86                 len = fill(zbuf, GZIP_IOBUF_SIZE);
   87 
   88         /* verify the gzip header */
   89         if (len < 10 ||
   90            zbuf[0] != 0x1f || zbuf[1] != 0x8b || zbuf[2] != 0x08) {
   91                 if (pos)
   92                         *pos = 0;
   93                 error("Not a gzip file");
   94                 goto gunzip_5;
   95         }
   96 
   97         /* skip over gzip header (1f,8b,08... 10 bytes total +
   98          * possible asciz filename)
   99          */
  100         strm->next_in = zbuf + 10;
  101         strm->avail_in = len - 10;
  102         /* skip over asciz filename */
  103         if (zbuf[3] & 0x8) {
  104                 do {
  105                         /*
  106                          * If the filename doesn't fit into the buffer,
  107                          * the file is very probably corrupt. Don't try
  108                          * to read more data.
  109                          */
  110                         if (strm->avail_in == 0) {
  111                                 error("header error");
  112                                 goto gunzip_5;
  113                         }
  114                         --strm->avail_in;
  115                 } while (*strm->next_in++);
  116         }
  117 
  118         strm->next_out = out_buf;
  119         strm->avail_out = out_len;
  120 
  121         rc = zlib_inflateInit2(strm, -MAX_WBITS);
  122 
  123         if (!flush) {
  124                 WS(strm)->inflate_state.wsize = 0;
  125                 WS(strm)->inflate_state.window = NULL;
  126         }
  127 
  128         while (rc == Z_OK) {
  129                 if (strm->avail_in == 0) {
  130                         /* TODO: handle case where both pos and fill are set */
  131                         len = fill(zbuf, GZIP_IOBUF_SIZE);
  132                         if (len < 0) {
  133                                 rc = -1;
  134                                 error("read error");
  135                                 break;
  136                         }
  137                         strm->next_in = zbuf;
  138                         strm->avail_in = len;
  139                 }
  140                 rc = zlib_inflate(strm, 0);
  141 
  142                 /* Write any data generated */
  143                 if (flush && strm->next_out > out_buf) {
  144                         int l = strm->next_out - out_buf;
  145                         if (l != flush(out_buf, l)) {
  146                                 rc = -1;
  147                                 error("write error");
  148                                 break;
  149                         }
  150                         strm->next_out = out_buf;
  151                         strm->avail_out = out_len;
  152                 }
  153 
  154                 /* after Z_FINISH, only Z_STREAM_END is "we unpacked it all" */
  155                 if (rc == Z_STREAM_END) {
  156                         rc = 0;
  157                         break;
  158                 } else if (rc != Z_OK) {
  159                         error("uncompression error");
  160                         rc = -1;
  161                 }
  162         }
  163 
  164         zlib_inflateEnd(strm);
  165         if (pos)
  166                 /* add + 8 to skip over trailer */
  167                 *pos = strm->next_in - zbuf+8;
  168 
  169 gunzip_5:
  170         free(strm->workspace);
  171 gunzip_nomem4:
  172         free(strm);
  173 gunzip_nomem3:
  174         if (!buf)
  175                 free(zbuf);
  176 gunzip_nomem2:
  177         if (flush)
  178                 free(out_buf);
  179 gunzip_nomem1:
  180         return rc; /* returns Z_OK (0) if successful */
  181 }
  182 
  183 #define decompress gunzip

Cache object: 882ddf9de6901fd40b2a9fcf03297a25


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.