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