aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/ijar
diff options
context:
space:
mode:
authorGravatar Rumou Duan <rduan@google.com>2016-09-21 21:59:01 +0000
committerGravatar Laszlo Csomor <laszlocsomor@google.com>2016-09-22 09:55:50 +0000
commita518f63e6a9f42996b1707dd6bb9a9287eb5b675 (patch)
tree0dc35c1f3a1dd9a7b6f2297a23b32a82e35ede4f /third_party/ijar
parentd7886f0589c217f90dca42cb5269d004ed3abbd1 (diff)
Move zlib-interfacing code from third_party/ijar/zip.cc into a separate class. And add a dummy zlib client.
-- MOS_MIGRATED_REVID=133879880
Diffstat (limited to 'third_party/ijar')
-rw-r--r--third_party/ijar/BUILD10
-rw-r--r--third_party/ijar/dummy_zlib_client.cc37
-rw-r--r--third_party/ijar/zip.cc146
-rw-r--r--third_party/ijar/zip.h3
-rw-r--r--third_party/ijar/zlib_client.cc161
-rw-r--r--third_party/ijar/zlib_client.h68
6 files changed, 311 insertions, 114 deletions
diff --git a/third_party/ijar/BUILD b/third_party/ijar/BUILD
index 85245de548..9abfd4d46c 100644
--- a/third_party/ijar/BUILD
+++ b/third_party/ijar/BUILD
@@ -24,6 +24,16 @@ cc_library(
"mapped_file.h",
"zip.h",
],
+ deps = [":zlib_client"],
+)
+
+cc_library(
+ name = "zlib_client",
+ srcs = ["zlib_client.cc"],
+ hdrs = [
+ "common.h",
+ "zlib_client.h",
+ ],
deps = ["//third_party/zlib"],
)
diff --git a/third_party/ijar/dummy_zlib_client.cc b/third_party/ijar/dummy_zlib_client.cc
new file mode 100644
index 0000000000..fe1498770a
--- /dev/null
+++ b/third_party/ijar/dummy_zlib_client.cc
@@ -0,0 +1,37 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <algorithm>
+
+#include "third_party/ijar/common.h"
+#include "third_party/ijar/zlib_client.h"
+
+namespace devtools_ijar {
+
+u4 ComputeCrcChecksum(u1* buf, size_t length) { return 0; }
+
+size_t TryDeflate(u1* buf, size_t length) { return 0; }
+
+Decompressor::Decompressor() {}
+Decompressor::~Decompressor() {}
+
+DecompressedFile* Decompressor::UncompressFile(const u1* buffer,
+ size_t bytes_avail) {
+ return NULL;
+}
+
+char* Decompressor::GetError() { return NULL; }
+
+int Decompressor::error(const char* fmt, ...) { return 0; }
+} // namespace devtools_ijar
diff --git a/third_party/ijar/zip.cc b/third_party/ijar/zip.cc
index a3d8c53831..3a56103eae 100644
--- a/third_party/ijar/zip.cc
+++ b/third_party/ijar/zip.cc
@@ -38,7 +38,7 @@
#include "third_party/ijar/mapped_file.h"
#include "third_party/ijar/zip.h"
-#include <zlib.h>
+#include "third_party/ijar/zlib_client.h"
#define LOCAL_FILE_HEADER_SIGNATURE 0x04034b50
#define CENTRAL_FILE_HEADER_SIGNATURE 0x02014b50
@@ -160,6 +160,8 @@ class InputZipFile : public ZipExtractor {
// last error
char errmsg[4*PATH_MAX];
+ Decompressor *decompressor_;
+
int error(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
@@ -458,73 +460,20 @@ int InputZipFile::SkipFile(const bool compressed) {
u1* InputZipFile::UncompressFile() {
size_t in_offset = p - zipdata_in_;
size_t remaining = input_file_->Length() - in_offset;
- z_stream stream;
-
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
- stream.avail_in = remaining;
- stream.next_in = (Bytef *) p;
-
- int ret = inflateInit2(&stream, -MAX_WBITS);
- if (ret != Z_OK) {
- error("inflateInit: %d\n", ret);
- return NULL;
- }
-
- int uncompressed_until_now = 0;
-
- while (true) {
- stream.avail_out = uncompressed_data_allocated_ - uncompressed_until_now;
- stream.next_out = uncompressed_data_ + uncompressed_until_now;
- int old_avail_out = stream.avail_out;
-
- ret = inflate(&stream, Z_SYNC_FLUSH);
- int uncompressed_now = old_avail_out - stream.avail_out;
- uncompressed_until_now += uncompressed_now;
-
- switch (ret) {
- case Z_STREAM_END: {
- // zlib said that there is no more data to decompress.
-
- u1 *new_p = reinterpret_cast<u1*>(stream.next_in);
- compressed_size_ = new_p - p;
- uncompressed_size_ = uncompressed_until_now;
- p = new_p;
- inflateEnd(&stream);
- return uncompressed_data_;
- }
-
- case Z_OK: {
- // zlib said that there is no more room in the buffer allocated for
- // the decompressed data. Enlarge that buffer and try again.
-
- if (uncompressed_data_allocated_ == MAX_BUFFER_SIZE) {
- error("ijar does not support decompressing files "
- "larger than %dMB.\n",
- (int) (MAX_BUFFER_SIZE/(1024*1024)));
- return NULL;
- }
-
- uncompressed_data_allocated_ *= 2;
- if (uncompressed_data_allocated_ > MAX_BUFFER_SIZE) {
- uncompressed_data_allocated_ = MAX_BUFFER_SIZE;
- }
-
- uncompressed_data_ = reinterpret_cast<u1*>(
- realloc(uncompressed_data_, uncompressed_data_allocated_));
- break;
- }
-
- case Z_DATA_ERROR:
- case Z_BUF_ERROR:
- case Z_STREAM_ERROR:
- case Z_NEED_DICT:
- default: {
- error("zlib returned error code %d during inflate.\n", ret);
- return NULL;
- }
+ DecompressedFile *decompressed_file =
+ decompressor_->UncompressFile(p, remaining);
+ if (decompressed_file == NULL) {
+ if (decompressor_->GetError() != NULL) {
+ error(decompressor_->GetError());
}
+ return NULL;
+ } else {
+ compressed_size_ = decompressed_file->compressed_size;
+ uncompressed_size_ = decompressed_file->uncompressed_size;
+ u1 *uncompressed_data = decompressed_file->uncompressed_data;
+ free(decompressed_file);
+ p += compressed_size_;
+ return uncompressed_data;
}
}
@@ -859,9 +808,7 @@ InputZipFile::InputZipFile(ZipExtractorProcessor *processor,
const char* filename)
: processor(processor), filename_(filename), input_file_(NULL),
bytes_unmapped_(0) {
- uncompressed_data_allocated_ = INITIAL_BUFFER_SIZE;
- uncompressed_data_ =
- reinterpret_cast<u1*>(malloc(uncompressed_data_allocated_));
+ decompressor_ = new Decompressor();
errmsg[0] = 0;
}
@@ -900,7 +847,7 @@ bool InputZipFile::Open() {
}
InputZipFile::~InputZipFile() {
- free(uncompressed_data_);
+ delete decompressor_;
if (input_file_ != NULL) {
input_file_->Close();
delete input_file_;
@@ -1064,46 +1011,6 @@ u1* OutputZipFile::WriteLocalFileHeader(const char* filename, const u4 attr) {
return header_ptr;
}
-// Try to compress a file entry in memory using the deflate algorithm.
-// It will compress buf (of size length) unless the compressed size is bigger
-// than the input size. The result will overwrite the content of buf and the
-// final size is returned.
-size_t TryDeflate(u1 *buf, size_t length) {
- u1 *outbuf = reinterpret_cast<u1 *>(malloc(length));
- z_stream stream;
-
- // Initialize the z_stream strcut for reading from buf and wrinting in outbuf.
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
- stream.total_in = length;
- stream.avail_in = length;
- stream.total_out = length;
- stream.avail_out = length;
- stream.next_in = buf;
- stream.next_out = outbuf;
-
- // deflateInit2 negative windows size prevent the zlib wrapper to be used.
- if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
- -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
- // Failure to compress => return the buffer uncompressed
- free(outbuf);
- return length;
- }
-
- if (deflate(&stream, Z_FINISH) == Z_STREAM_END) {
- // Compression successful and fits in outbuf, let's copy the result in buf.
- length = stream.total_out;
- memcpy(buf, outbuf, length);
- }
-
- deflateEnd(&stream);
- free(outbuf);
-
- // Return the length of the resulting buffer
- return length;
-}
-
size_t OutputZipFile::WriteFileSizeInLocalFileHeader(u1 *header_ptr,
size_t out_length,
bool compress,
@@ -1149,10 +1056,21 @@ int OutputZipFile::FinishFile(size_t filelength, bool compress,
bool compute_crc) {
u4 crc = 0;
if (compute_crc) {
- crc = crc32(crc, q, filelength);
+ crc = ComputeCrcChecksum(q, filelength);
+
+ if (filelength > 0 && crc == 0) {
+ fprintf(stderr, "Error calculating CRC32 checksum.\n");
+ return -1;
+ }
}
size_t compressed_size =
WriteFileSizeInLocalFileHeader(header_ptr, filelength, compress, crc);
+
+ if (compressed_size == 0 && filelength > 0) {
+ fprintf(stderr, "Error compressing files.\n");
+ return -1;
+ }
+
entries_.back()->crc32 = crc;
entries_.back()->compressed_length = compressed_size;
entries_.back()->uncompressed_length = filelength;
@@ -1200,7 +1118,9 @@ ZipBuilder* ZipBuilder::Create(const char* zip_file, u8 estimated_size) {
return result;
}
-u8 ZipBuilder::EstimateSize(char **files, char **zip_paths, int nb_entries) {
+u8 ZipBuilder::EstimateSize(char const* const* files,
+ char const* const* zip_paths,
+ int nb_entries) {
struct stat statst;
// Digital signature field size = 6, End of central directory = 22, Total = 28
u8 size = 28;
diff --git a/third_party/ijar/zip.h b/third_party/ijar/zip.h
index 6ca2e40f88..15b0198bb2 100644
--- a/third_party/ijar/zip.h
+++ b/third_party/ijar/zip.h
@@ -103,7 +103,8 @@ class ZipBuilder {
// Estimate the maximum size of the ZIP files containing files in the "files"
// null-terminated array.
// Returns 0 on error.
- static u8 EstimateSize(char** files, char** zip_paths, int nb_entries);
+ static u8 EstimateSize(char const* const* files, char const* const* zip_paths,
+ int nb_entries);
};
//
diff --git a/third_party/ijar/zlib_client.cc b/third_party/ijar/zlib_client.cc
new file mode 100644
index 0000000000..1738a05465
--- /dev/null
+++ b/third_party/ijar/zlib_client.cc
@@ -0,0 +1,161 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdlib.h>
+#include <algorithm>
+
+#include "third_party/ijar/common.h"
+#include "third_party/ijar/zlib_client.h"
+#include <zlib.h>
+
+namespace devtools_ijar {
+
+u4 ComputeCrcChecksum(u1 *buf, size_t length) {
+ return crc32(0, buf, length);
+}
+
+size_t TryDeflate(u1 *buf, size_t length) {
+ u1 *outbuf = reinterpret_cast<u1 *>(malloc(length));
+ z_stream stream;
+
+ // Initialize the z_stream strcut for reading from buf and wrinting in outbuf.
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+ stream.total_in = length;
+ stream.avail_in = length;
+ stream.total_out = length;
+ stream.avail_out = length;
+ stream.next_in = buf;
+ stream.next_out = outbuf;
+
+ // deflateInit2 negative windows size prevent the zlib wrapper to be used.
+ if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8,
+ Z_DEFAULT_STRATEGY) != Z_OK) {
+ // Failure to compress => return the buffer uncompressed
+ free(outbuf);
+ return length;
+ }
+
+ if (deflate(&stream, Z_FINISH) == Z_STREAM_END) {
+ // Compression successful and fits in outbuf, let's copy the result in buf.
+ length = stream.total_out;
+ memcpy(buf, outbuf, length);
+ }
+
+ deflateEnd(&stream);
+ free(outbuf);
+
+ // Return the length of the resulting buffer
+ return length;
+}
+
+Decompressor::Decompressor() {
+ uncompressed_data_allocated_ = INITIAL_BUFFER_SIZE;
+ uncompressed_data_ =
+ reinterpret_cast<u1 *>(malloc(uncompressed_data_allocated_));
+}
+
+Decompressor::~Decompressor() { free(uncompressed_data_); }
+
+DecompressedFile *Decompressor::UncompressFile(const u1 *buffer,
+ size_t bytes_avail) {
+ z_stream stream;
+
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+ stream.avail_in = bytes_avail;
+ stream.next_in = const_cast<Bytef*>(reinterpret_cast<const Bytef*>(buffer));
+
+ int ret = inflateInit2(&stream, -MAX_WBITS);
+ if (ret != Z_OK) {
+ error("inflateInit: %d\n", ret);
+ return NULL;
+ }
+
+ int uncompressed_until_now = 0;
+
+ while (true) {
+ stream.avail_out = uncompressed_data_allocated_ - uncompressed_until_now;
+ stream.next_out = uncompressed_data_ + uncompressed_until_now;
+ int old_avail_out = stream.avail_out;
+
+ ret = inflate(&stream, Z_SYNC_FLUSH);
+ int uncompressed_now = old_avail_out - stream.avail_out;
+ uncompressed_until_now += uncompressed_now;
+
+ switch (ret) {
+ case Z_STREAM_END: {
+ struct DecompressedFile *decompressedFile =
+ reinterpret_cast<DecompressedFile *>(
+ malloc(sizeof(DecompressedFile)));
+ // zlib said that there is no more data to decompress.
+ u1 *new_p = reinterpret_cast<u1 *>(stream.next_in);
+ decompressedFile->compressed_size = new_p - buffer;
+ decompressedFile->uncompressed_size = uncompressed_until_now;
+ decompressedFile->uncompressed_data = uncompressed_data_;
+ inflateEnd(&stream);
+ return decompressedFile;
+ }
+
+ case Z_OK: {
+ // zlib said that there is no more room in the buffer allocated for
+ // the decompressed data. Enlarge that buffer and try again.
+
+ if (uncompressed_data_allocated_ == MAX_BUFFER_SIZE) {
+ error(
+ "ijar does not support decompressing files "
+ "larger than %dMB.\n",
+ static_cast<int>((MAX_BUFFER_SIZE / (1024 * 1024))));
+ return NULL;
+ }
+
+ uncompressed_data_allocated_ *= 2;
+ if (uncompressed_data_allocated_ > MAX_BUFFER_SIZE) {
+ uncompressed_data_allocated_ = MAX_BUFFER_SIZE;
+ }
+
+ uncompressed_data_ = reinterpret_cast<u1 *>(
+ realloc(uncompressed_data_, uncompressed_data_allocated_));
+ break;
+ }
+
+ case Z_DATA_ERROR:
+ case Z_BUF_ERROR:
+ case Z_STREAM_ERROR:
+ case Z_NEED_DICT:
+ default: {
+ error("zlib returned error code %d during inflate.\n", ret);
+ return NULL;
+ }
+ }
+ }
+}
+
+char *Decompressor::GetError() {
+ if (errmsg[0] == 0) {
+ return NULL;
+ }
+ return errmsg;
+}
+
+int Decompressor::error(const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(errmsg, 4 * PATH_MAX, fmt, ap);
+ va_end(ap);
+ return -1;
+}
+} // namespace devtools_ijar
diff --git a/third_party/ijar/zlib_client.h b/third_party/ijar/zlib_client.h
new file mode 100644
index 0000000000..ed6616362f
--- /dev/null
+++ b/third_party/ijar/zlib_client.h
@@ -0,0 +1,68 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef THIRD_PARTY_IJAR_ZLIB_CLIENT_H_
+#define THIRD_PARTY_IJAR_ZLIB_CLIENT_H_
+
+#include <limits.h>
+
+#include "third_party/ijar/common.h"
+
+namespace devtools_ijar {
+// Try to compress a file entry in memory using the deflate algorithm.
+// It will compress buf (of size length) unless the compressed size is bigger
+// than the input size. The result will overwrite the content of buf and the
+// final size is returned.
+size_t TryDeflate(u1* buf, size_t length);
+
+u4 ComputeCrcChecksum(u1* buf, size_t length);
+
+struct DecompressedFile {
+ u1* uncompressed_data;
+ u4 uncompressed_size;
+ u4 compressed_size;
+};
+
+class Decompressor {
+ public:
+ Decompressor();
+ ~Decompressor();
+ DecompressedFile* UncompressFile(const u1* buffer, size_t bytes_avail);
+ char* GetError();
+
+ private:
+ // Administration of memory reserved for decompressed data. We use the same
+ // buffer for each file to avoid some malloc()/free() calls and free the
+ // memory only in the dtor. C-style memory management is used so that we
+ // can call realloc.
+ u1* uncompressed_data_;
+ size_t uncompressed_data_allocated_;
+ // last error
+ char errmsg[4 * PATH_MAX];
+
+ int error(const char* fmt, ...);
+
+ // Buffer size is initially INITIAL_BUFFER_SIZE. It doubles in size every
+ // time it is found too small, until it reaches MAX_BUFFER_SIZE. If that is
+ // not enough, we bail out. We only decompress class files, so they should
+ // be smaller than 64K anyway, but we give a little leeway.
+ // MAX_BUFFER_SIZE must be bigger than the size of the biggest file in the
+ // ZIP. It is set to 2GB here because no one has audited the code for 64-bit
+ // cleanliness.
+ static const size_t INITIAL_BUFFER_SIZE = 256 * 1024; // 256K
+ static const size_t MAX_BUFFER_SIZE = std::numeric_limits<int32_t>::max();
+};
+} // namespace devtools_ijar
+
+#endif // THIRD_PARTY_IJAR_ZLIB_CLIENT_H_