zlib_client.cc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Copyright 2016 The Bazel Authors. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <stdlib.h>
  15. #include <algorithm>
  16. #include <cstdio>
  17. #include "third_party/ijar/common.h"
  18. #include "third_party/ijar/zlib_client.h"
  19. #include <zlib.h>
  20. namespace devtools_ijar {
  21. u4 ComputeCrcChecksum(u1 *buf, size_t length) {
  22. return crc32(0, buf, length);
  23. }
  24. size_t TryDeflate(u1 *buf, size_t length) {
  25. u1 *outbuf = reinterpret_cast<u1 *>(malloc(length));
  26. z_stream stream;
  27. // Initialize the z_stream strcut for reading from buf and wrinting in outbuf.
  28. stream.zalloc = Z_NULL;
  29. stream.zfree = Z_NULL;
  30. stream.opaque = Z_NULL;
  31. stream.total_in = length;
  32. stream.avail_in = length;
  33. stream.total_out = length;
  34. stream.avail_out = length;
  35. stream.next_in = buf;
  36. stream.next_out = outbuf;
  37. // deflateInit2 negative windows size prevent the zlib wrapper to be used.
  38. if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8,
  39. Z_DEFAULT_STRATEGY) != Z_OK) {
  40. // Failure to compress => return the buffer uncompressed
  41. free(outbuf);
  42. return length;
  43. }
  44. if (deflate(&stream, Z_FINISH) == Z_STREAM_END) {
  45. // Compression successful and fits in outbuf, let's copy the result in buf.
  46. length = stream.total_out;
  47. memcpy(buf, outbuf, length);
  48. }
  49. deflateEnd(&stream);
  50. free(outbuf);
  51. // Return the length of the resulting buffer
  52. return length;
  53. }
  54. Decompressor::Decompressor() {
  55. uncompressed_data_allocated_ = INITIAL_BUFFER_SIZE;
  56. uncompressed_data_ =
  57. reinterpret_cast<u1 *>(malloc(uncompressed_data_allocated_));
  58. }
  59. Decompressor::~Decompressor() { free(uncompressed_data_); }
  60. DecompressedFile *Decompressor::UncompressFile(const u1 *buffer,
  61. size_t bytes_avail) {
  62. z_stream stream;
  63. stream.zalloc = Z_NULL;
  64. stream.zfree = Z_NULL;
  65. stream.opaque = Z_NULL;
  66. stream.avail_in = bytes_avail;
  67. stream.next_in = const_cast<Bytef*>(reinterpret_cast<const Bytef*>(buffer));
  68. int ret = inflateInit2(&stream, -MAX_WBITS);
  69. if (ret != Z_OK) {
  70. error("inflateInit: %d\n", ret);
  71. return NULL;
  72. }
  73. int uncompressed_until_now = 0;
  74. while (true) {
  75. stream.avail_out = uncompressed_data_allocated_ - uncompressed_until_now;
  76. stream.next_out = uncompressed_data_ + uncompressed_until_now;
  77. int old_avail_out = stream.avail_out;
  78. ret = inflate(&stream, Z_SYNC_FLUSH);
  79. int uncompressed_now = old_avail_out - stream.avail_out;
  80. uncompressed_until_now += uncompressed_now;
  81. switch (ret) {
  82. case Z_STREAM_END: {
  83. struct DecompressedFile *decompressedFile =
  84. reinterpret_cast<DecompressedFile *>(
  85. malloc(sizeof(DecompressedFile)));
  86. // zlib said that there is no more data to decompress.
  87. u1 *new_p = reinterpret_cast<u1 *>(stream.next_in);
  88. decompressedFile->compressed_size = new_p - buffer;
  89. decompressedFile->uncompressed_size = uncompressed_until_now;
  90. decompressedFile->uncompressed_data = uncompressed_data_;
  91. inflateEnd(&stream);
  92. return decompressedFile;
  93. }
  94. case Z_OK: {
  95. // zlib said that there is no more room in the buffer allocated for
  96. // the decompressed data. Enlarge that buffer and try again.
  97. if (uncompressed_data_allocated_ == MAX_BUFFER_SIZE) {
  98. error(
  99. "ijar does not support decompressing files "
  100. "larger than %dMB.\n",
  101. static_cast<int>((MAX_BUFFER_SIZE / (1024 * 1024))));
  102. return NULL;
  103. }
  104. uncompressed_data_allocated_ *= 2;
  105. if (uncompressed_data_allocated_ > MAX_BUFFER_SIZE) {
  106. uncompressed_data_allocated_ = MAX_BUFFER_SIZE;
  107. }
  108. uncompressed_data_ = reinterpret_cast<u1 *>(
  109. realloc(uncompressed_data_, uncompressed_data_allocated_));
  110. break;
  111. }
  112. case Z_DATA_ERROR:
  113. case Z_BUF_ERROR:
  114. case Z_STREAM_ERROR:
  115. case Z_NEED_DICT:
  116. default: {
  117. error("zlib returned error code %d during inflate.\n", ret);
  118. return NULL;
  119. }
  120. }
  121. }
  122. }
  123. char *Decompressor::GetError() {
  124. if (errmsg[0] == 0) {
  125. return NULL;
  126. }
  127. return errmsg;
  128. }
  129. int Decompressor::error(const char *fmt, ...) {
  130. va_list ap;
  131. va_start(ap, fmt);
  132. vsnprintf(errmsg, 4 * PATH_MAX, fmt, ap);
  133. va_end(ap);
  134. return -1;
  135. }
  136. } // namespace devtools_ijar