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