1aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
2aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Copyright (C) 2009 The Android Open Source Project
3aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
4aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Licensed under the Apache License, Version 2.0 (the "License");
5aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// you may not use this file except in compliance with the License.
6aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// You may obtain a copy of the License at
7aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
8aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//      http://www.apache.org/licenses/LICENSE-2.0
9aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
10aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// Unless required by applicable law or agreed to in writing, software
11aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// distributed under the License is distributed on an "AS IS" BASIS,
12aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// See the License for the specific language governing permissions and
14aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo// limitations under the License.
15aea4c1cea20dda7ae7e85fc8924a2d784f70d806Alex Deymo//
168006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
1739910dcd1d68987ccee7c3031dc269233a8490bbAlex Deymo#include "update_engine/payload_consumer/bzip_extent_writer.h"
188006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
198006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyesusing std::vector;
208006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
218006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyesnamespace chromeos_update_engine {
228006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
238006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyesnamespace {
243f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenkoconst brillo::Blob::size_type kOutputBufferLength = 16 * 1024;
258006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes}
268006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
27f1d582e1a39e170d1a7e20bd21cad25b3f70f96aNam T. Nguyenbool BzipExtentWriter::Init(FileDescriptorPtr fd,
288006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes                            const vector<Extent>& extents,
2909e56d64202d2148b95008c5bd18cf719ec0f40cAndrew de los Reyes                            uint32_t block_size) {
308006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  // Init bzip2 stream
318006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  int rc = BZ2_bzDecompressInit(&stream_,
32d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko                                0,   // verbosity. (0 == silent)
33d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko                                0);  // 0 = faster algo, more memory
34d2779df63aaad8b65fc5d4badee7dbc9bed7f2b6Alex Vakulenko
358006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  TEST_AND_RETURN_FALSE(rc == BZ_OK);
368006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
378006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  return next_->Init(fd, extents, block_size);
388006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes}
398006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
408006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyesbool BzipExtentWriter::Write(const void* bytes, size_t count) {
413f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko  brillo::Blob output_buffer(kOutputBufferLength);
428006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
43e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov  // Copy the input data into |input_buffer_| only if |input_buffer_| already
44e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov  // contains unconsumed data. Otherwise, process the data directly from the
45e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov  // source.
46f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  const uint8_t* input = reinterpret_cast<const uint8_t*>(bytes);
47f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  const uint8_t* input_end = input + count;
48e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov  if (!input_buffer_.empty()) {
49e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov    input_buffer_.insert(input_buffer_.end(), input, input_end);
50f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko    input = input_buffer_.data();
51e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov    input_end = input + input_buffer_.size();
52e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov  }
53f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko  stream_.next_in = reinterpret_cast<char*>(const_cast<uint8_t*>(input));
54e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov  stream_.avail_in = input_end - input;
558006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
568006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  for (;;) {
57f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko    stream_.next_out = reinterpret_cast<char*>(output_buffer.data());
588006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    stream_.avail_out = output_buffer.size();
598006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
608006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    int rc = BZ2_bzDecompress(&stream_);
618006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    TEST_AND_RETURN_FALSE(rc == BZ_OK || rc == BZ_STREAM_END);
62e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov
638006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    if (stream_.avail_out == output_buffer.size())
648006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes      break;  // got no new bytes
65e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov
668006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    TEST_AND_RETURN_FALSE(
67f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko        next_->Write(output_buffer.data(),
688006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes                     output_buffer.size() - stream_.avail_out));
69e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov
708006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    if (rc == BZ_STREAM_END)
71f68bbbc952aa9a71898e4939b5f36187fa564a50Alex Vakulenko      CHECK_EQ(stream_.avail_in, 0u);
728006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes    if (stream_.avail_in == 0)
738006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes      break;  // no more input to process
748006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  }
758006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
76e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov  // Store unconsumed data (if any) in |input_buffer_|.
77e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov  if (stream_.avail_in || !input_buffer_.empty()) {
783f39d5cc753905874d8d93bef94f857b8808f19eAlex Vakulenko    brillo::Blob new_input_buffer(input_end - stream_.avail_in, input_end);
79e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov    new_input_buffer.swap(input_buffer_);
80e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov  }
81e0622398a00e884db6d488011d8f7ecd293eb04bDarin Petkov
828006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  return true;
838006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes}
848006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
858006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyesbool BzipExtentWriter::EndImpl() {
868006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  TEST_AND_RETURN_FALSE(input_buffer_.empty());
878006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  TEST_AND_RETURN_FALSE(BZ2_bzDecompressEnd(&stream_) == BZ_OK);
888006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes  return next_->End();
898006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes}
908006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes
918006106bd8dea3761d7f4dd8c8aa82d43c35bd17Andrew de los Reyes}  // namespace chromeos_update_engine
92