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