decompress_inflate.c 4.4 KB

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