decompress_inflate.c 3.5 KB

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