blob: 15bd4fd66372802b3a03bf744f847814131597a7 [file] [log] [blame]
rspangler@google.com49fdf182009-10-10 00:57:34 +00001// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "update_engine/decompressing_file_writer.h"
6
7namespace chromeos_update_engine {
8
9// typedef struct z_stream_s {
10// Bytef *next_in; /* next input byte */
11// uInt avail_in; /* number of bytes available at next_in */
12// uLong total_in; /* total nb of input bytes read so far */
13//
14// Bytef *next_out; /* next output byte should be put there */
15// uInt avail_out; /* remaining free space at next_out */
16// uLong total_out; /* total nb of bytes output so far */
17//
18// char *msg; /* last error message, NULL if no error */
19// struct internal_state FAR *state; /* not visible by applications */
20//
21// alloc_func zalloc; /* used to allocate the internal state */
22// free_func zfree; /* used to free the internal state */
23// voidpf opaque; /* private data object passed to zalloc and zfree */
24//
25// int data_type; /* best guess about the data type: binary or text */
26// uLong adler; /* adler32 value of the uncompressed data */
27// uLong reserved; /* reserved for future use */
28// } z_stream;
29
30int GzipDecompressingFileWriter::Write(const void* bytes, size_t count) {
31 // Steps:
32 // put the data on next_in
33 // call inflate until it returns nothing, each time writing what we get
34 // check that next_in has no data left.
35
36 // It seems that zlib can keep internal buffers in the stream object,
37 // so not all data we get fed to us this time will necessarily
38 // be written out this time (in decompressed form).
39
40 CHECK_EQ(0, stream_.avail_in);
41 char buf[1024];
42
43 buffer_.reserve(count);
44 buffer_.clear();
45 CHECK_GE(buffer_.capacity(), count);
46 const char* char_bytes = reinterpret_cast<const char*>(bytes);
47 buffer_.insert(buffer_.end(), char_bytes, char_bytes + count);
48
49 stream_.next_in = reinterpret_cast<Bytef*>(&buffer_[0]);
50 stream_.avail_in = count;
51 int retcode = Z_OK;
52
53 while (Z_OK == retcode) {
54 stream_.next_out = reinterpret_cast<Bytef*>(buf);
55 stream_.avail_out = sizeof(buf);
56 int retcode = inflate(&stream_, Z_NO_FLUSH);
57 // check for Z_STREAM_END, Z_OK, or Z_BUF_ERROR (which is non-fatal)
58 if (Z_STREAM_END != retcode && Z_OK != retcode && Z_BUF_ERROR != retcode) {
59 LOG(ERROR) << "zlib inflate() error:" << retcode;
60 if (stream_.msg)
61 LOG(ERROR) << "message:" << stream_.msg;
62 return 0;
63 }
64 int count_received = sizeof(buf) - stream_.avail_out;
65 if (count_received > 0) {
66 next_->Write(buf, count_received);
67 } else {
68 // Inflate returned no data; we're done for now. Make sure no
69 // input data remain.
70 CHECK_EQ(0, stream_.avail_in);
71 break;
72 }
73 }
74 return count;
75}
76
77} // namespace chromeos_update_engine