~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/decompress_inflate.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php