Almost there...
git-svn-id: svn://chrome-svn/chromeos/trunk@24 06c00378-0e64-4dae-be16-12b19f9950a1
diff --git a/decompressing_file_writer.cc b/decompressing_file_writer.cc
new file mode 100644
index 0000000..15bd4fd
--- /dev/null
+++ b/decompressing_file_writer.cc
@@ -0,0 +1,77 @@
+// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "update_engine/decompressing_file_writer.h"
+
+namespace chromeos_update_engine {
+
+// typedef struct z_stream_s {
+// Bytef *next_in; /* next input byte */
+// uInt avail_in; /* number of bytes available at next_in */
+// uLong total_in; /* total nb of input bytes read so far */
+//
+// Bytef *next_out; /* next output byte should be put there */
+// uInt avail_out; /* remaining free space at next_out */
+// uLong total_out; /* total nb of bytes output so far */
+//
+// char *msg; /* last error message, NULL if no error */
+// struct internal_state FAR *state; /* not visible by applications */
+//
+// alloc_func zalloc; /* used to allocate the internal state */
+// free_func zfree; /* used to free the internal state */
+// voidpf opaque; /* private data object passed to zalloc and zfree */
+//
+// int data_type; /* best guess about the data type: binary or text */
+// uLong adler; /* adler32 value of the uncompressed data */
+// uLong reserved; /* reserved for future use */
+// } z_stream;
+
+int GzipDecompressingFileWriter::Write(const void* bytes, size_t count) {
+ // Steps:
+ // put the data on next_in
+ // call inflate until it returns nothing, each time writing what we get
+ // check that next_in has no data left.
+
+ // It seems that zlib can keep internal buffers in the stream object,
+ // so not all data we get fed to us this time will necessarily
+ // be written out this time (in decompressed form).
+
+ CHECK_EQ(0, stream_.avail_in);
+ char buf[1024];
+
+ buffer_.reserve(count);
+ buffer_.clear();
+ CHECK_GE(buffer_.capacity(), count);
+ const char* char_bytes = reinterpret_cast<const char*>(bytes);
+ buffer_.insert(buffer_.end(), char_bytes, char_bytes + count);
+
+ stream_.next_in = reinterpret_cast<Bytef*>(&buffer_[0]);
+ stream_.avail_in = count;
+ int retcode = Z_OK;
+
+ while (Z_OK == retcode) {
+ stream_.next_out = reinterpret_cast<Bytef*>(buf);
+ stream_.avail_out = sizeof(buf);
+ int retcode = inflate(&stream_, Z_NO_FLUSH);
+ // check for Z_STREAM_END, Z_OK, or Z_BUF_ERROR (which is non-fatal)
+ if (Z_STREAM_END != retcode && Z_OK != retcode && Z_BUF_ERROR != retcode) {
+ LOG(ERROR) << "zlib inflate() error:" << retcode;
+ if (stream_.msg)
+ LOG(ERROR) << "message:" << stream_.msg;
+ return 0;
+ }
+ int count_received = sizeof(buf) - stream_.avail_out;
+ if (count_received > 0) {
+ next_->Write(buf, count_received);
+ } else {
+ // Inflate returned no data; we're done for now. Make sure no
+ // input data remain.
+ CHECK_EQ(0, stream_.avail_in);
+ break;
+ }
+ }
+ return count;
+}
+
+} // namespace chromeos_update_engine