root/lib/decompress_inflate.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nofill
  2. __gunzip
  3. gunzip
  4. __decompress

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

/* [<][>][^][v][top][bottom][index][help] */