decompress_inflate.c 3.8 KB

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