1 // Copyright 2017 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 "bsdiff/bz2_decompressor.h"
6 
7 #include <algorithm>
8 #include <limits>
9 
10 #include <bzlib.h>
11 
12 #include "bsdiff/logging.h"
13 
14 namespace bsdiff {
15 
SetInputData(const uint8_t * input_data,size_t size)16 bool BZ2Decompressor::SetInputData(const uint8_t* input_data, size_t size) {
17   // TODO(xunchang) update the avail_in for size > 2GB.
18   if (size > std::numeric_limits<unsigned int>::max()) {
19     LOG(ERROR) << "Oversized input data" << size;
20     return false;
21   }
22 
23   stream_.next_in = reinterpret_cast<char*>(const_cast<uint8_t*>(input_data));
24   stream_.avail_in = size;
25   stream_.bzalloc = nullptr;
26   stream_.bzfree = nullptr;
27   stream_.opaque = nullptr;
28   int bz2err = BZ2_bzDecompressInit(&stream_, 0, 0);
29   if (bz2err != BZ_OK) {
30     LOG(ERROR) << "Failed to bzinit control stream: " << bz2err;
31     return false;
32   }
33   return true;
34 }
35 
Read(uint8_t * output_data,size_t bytes_to_output)36 bool BZ2Decompressor::Read(uint8_t* output_data, size_t bytes_to_output) {
37   stream_.next_out = reinterpret_cast<char*>(output_data);
38   while (bytes_to_output > 0) {
39     size_t output_size = std::min<size_t>(
40         std::numeric_limits<unsigned int>::max(), bytes_to_output);
41     stream_.avail_out = output_size;
42 
43     int bz2err = BZ2_bzDecompress(&stream_);
44     if (bz2err != BZ_OK && bz2err != BZ_STREAM_END) {
45       LOG(ERROR) << "Failed to decompress " << output_size
46                  << " bytes of data, error: " << bz2err;
47       return false;
48     }
49     bytes_to_output -= (output_size - stream_.avail_out);
50   }
51   return true;
52 }
53 
Close()54 bool BZ2Decompressor::Close() {
55   int bz2err = BZ2_bzDecompressEnd(&stream_);
56   if (bz2err != BZ_OK) {
57     LOG(ERROR) << "BZ2_bzDecompressEnd returns with " << bz2err;
58     return false;
59   }
60   return true;
61 }
62 
63 }  // namespace bsdiff
64