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 184