Move zlib-interfacing code from third_party/ijar/zip.cc into a separate class. And add a dummy zlib client.

--
MOS_MIGRATED_REVID=133879880
diff --git a/third_party/ijar/BUILD b/third_party/ijar/BUILD
index 85245de..9abfd4d 100644
--- a/third_party/ijar/BUILD
+++ b/third_party/ijar/BUILD
@@ -24,6 +24,16 @@
         "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 0000000..fe14987
--- /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 a3d8c53..3a56103 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 @@
   // 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 @@
 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 @@
                            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 @@
 }
 
 InputZipFile::~InputZipFile() {
-  free(uncompressed_data_);
+  delete decompressor_;
   if (input_file_ != NULL) {
     input_file_->Close();
     delete input_file_;
@@ -1064,46 +1011,6 @@
   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 @@
                               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 @@
   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 6ca2e40..15b0198 100644
--- a/third_party/ijar/zip.h
+++ b/third_party/ijar/zip.h
@@ -103,7 +103,8 @@
   // 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 0000000..1738a05
--- /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 0000000..ed66163
--- /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_